blob: e47e8f3d14b873dacc9687b8f8e74c3eff7b5d9c [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
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300118 So we need to use a lock around all uses of Tcl. Previously, the
119 Python interpreter lock was used for this. However, this causes
120 problems when other Python threads need to run while Tcl is blocked
121 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000122
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300123 To solve this problem, a separate lock for Tcl is introduced.
124 Holding it is incompatible with holding Python's interpreter lock.
125 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000126
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300127 ENTER_TCL and LEAVE_TCL are brackets, just like
128 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
129 used whenever a call into Tcl is made that could call an event
130 handler, or otherwise affect the state of a Tcl interpreter. These
131 assume that the surrounding code has the Python interpreter lock;
132 inside the brackets, the Python interpreter lock has been released
133 and the lock for Tcl has been acquired.
134
135 Sometimes, it is necessary to have both the Python lock and the Tcl
136 lock. (For example, when transferring data from the Tcl
137 interpreter result to a Python string object.) This can be done by
138 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
139 reacquires the Python lock (and restores the thread state) but
140 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
141 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000142
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000143 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300144 handlers when the handler needs to use Python. Such event handlers
145 are entered while the lock for Tcl is held; the event handler
146 presumably needs to use Python. ENTER_PYTHON releases the lock for
147 Tcl and acquires the Python interpreter lock, restoring the
148 appropriate thread state, and LEAVE_PYTHON releases the Python
149 interpreter lock and re-acquires the lock for Tcl. It is okay for
150 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
151 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000152
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300153 These locks expand to several statements and brackets; they should
154 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000155
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300156 If Tcl is threaded, this approach won't work anymore. The Tcl
157 interpreter is only valid in the thread that created it, and all Tk
158 activity must happen in this thread, also. That means that the
159 mainloop must be invoked in the thread that created the
160 interpreter. Invoking commands from other threads is possible;
161 _tkinter will queue an event for the interpreter thread, which will
162 then execute the command and pass back the result. If the main
163 thread is not in the mainloop, and invoking commands causes an
164 exception; if the main loop is running but not processing events,
165 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000166
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300167 In addition, for a threaded Tcl, a single global tcl_tstate won't
168 be sufficient anymore, since multiple Tcl interpreters may
169 simultaneously dispatch in different threads. So we use the Tcl TLS
170 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000171
Guido van Rossum00d93061998-05-28 23:06:38 +0000172*/
173
Guido van Rossum65d5b571998-12-21 19:32:43 +0000174static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000175
176#ifdef TCL_THREADS
177static Tcl_ThreadDataKey state_key;
178typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300179#define tcl_tstate \
180 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000182static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000184
185#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
187 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000188
189#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300190 tcl_tstate = NULL; \
191 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
Guido van Rossum62320c91998-06-15 04:36:09 +0000193#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000195
196#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000198
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000199#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300201 if(tcl_lock) \
202 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = PyEval_SaveThread(); \
206 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207
208#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 if (((TkappObject *)self)->threaded && \
210 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300211 PyErr_SetString(PyExc_RuntimeError, \
212 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 return 0; \
214 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#else
217
218#define ENTER_TCL
219#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000220#define ENTER_OVERLAP
221#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000222#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000223#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000224#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000225
226#endif
227
Guido van Rossum97867b21996-08-08 19:09:53 +0000228#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000229#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000230#endif
231
Guido van Rossum18468821994-06-20 07:49:28 +0000232/**** Tkapp Object Declaration ****/
233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300234static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000235
Guido van Rossum00d93061998-05-28 23:06:38 +0000236typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000237 PyObject_HEAD
238 Tcl_Interp *interp;
239 int wantobjects;
240 int threaded; /* True if tcl_platform[threaded] */
241 Tcl_ThreadId thread_id;
242 int dispatching;
243 /* We cannot include tclInt.h, as this is internal.
244 So we cache interesting types here. */
245 Tcl_ObjType *BooleanType;
246 Tcl_ObjType *ByteArrayType;
247 Tcl_ObjType *DoubleType;
248 Tcl_ObjType *IntType;
249 Tcl_ObjType *ListType;
250 Tcl_ObjType *ProcBodyType;
251 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000252} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000253
Guido van Rossum18468821994-06-20 07:49:28 +0000254#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000255#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum35d43371997-08-02 00:09:09 +0000257#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000258(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Barry Warsawfa701a81997-01-16 00:15:11 +0000260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262/**** Error Handling ****/
263
264static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000265static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000266static int errorInCmd = 0;
267static PyObject *excInCmd;
268static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000269static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000270
Guilherme Polob681df42009-02-09 22:33:59 +0000271#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000272static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000273#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275
Guido van Rossum18468821994-06-20 07:49:28 +0000276static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000277Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000279 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
280 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000281}
282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000286
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000287static int Tkinter_busywaitinterval = 20;
288
Guido van Rossum00d93061998-05-28 23:06:38 +0000289#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000290#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000291
Guido van Rossum00d93061998-05-28 23:06:38 +0000292/* Millisecond sleep() for Unix platforms. */
293
294static void
Fred Drake509d79a2000-07-08 04:04:38 +0000295Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000296{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 /* XXX Too bad if you don't have select(). */
298 struct timeval t;
299 t.tv_sec = milli/1000;
300 t.tv_usec = (milli%1000) * 1000;
301 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000302}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000303#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000304
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000305/* Wait up to 1s for the mainloop to come up. */
306
307static int
308WaitForMainloop(TkappObject* self)
309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 int i;
311 for (i = 0; i < 10; i++) {
312 if (self->dispatching)
313 return 1;
314 Py_BEGIN_ALLOW_THREADS
315 Sleep(100);
316 Py_END_ALLOW_THREADS
317 }
318 if (self->dispatching)
319 return 1;
320 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
321 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000323#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326
Guido van Rossum18468821994-06-20 07:49:28 +0000327#define ARGSZ 64
328
Barry Warsawfa701a81997-01-16 00:15:11 +0000329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000330
Guido van Rossum18468821994-06-20 07:49:28 +0000331static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200332unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
333{
334 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
335 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
336 /* Tcl encodes null character as \xc0\x80 */
337 if (memchr(s, '\xc0', size)) {
338 char *buf, *q;
339 const char *e = s + size;
340 PyErr_Clear();
341 q = buf = (char *)PyMem_Malloc(size);
342 if (buf == NULL)
343 return NULL;
344 while (s != e) {
345 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
346 *q++ = '\0';
347 s += 2;
348 }
349 else
350 *q++ = *s++;
351 }
352 s = buf;
353 size = q - s;
354 r = PyUnicode_DecodeUTF8(s, size, NULL);
355 PyMem_Free(buf);
356 }
357 }
358 return r;
359}
360
361static PyObject *
362unicodeFromTclString(const char *s)
363{
364 return unicodeFromTclStringAndSize(s, strlen(s));
365}
366
367static PyObject *
368unicodeFromTclObj(Tcl_Obj *value)
369{
370 int len;
371 char *s = Tcl_GetStringFromObj(value, &len);
372 return unicodeFromTclStringAndSize(s, len);
373}
374
375
376static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000377Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 int argc;
380 char **argv;
381 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300384 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 }
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
388 /* Not a list.
389 * Could be a quoted string containing funnies, e.g. {"}.
390 * Return the string itself.
391 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200392 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 }
Guido van Rossum18468821994-06-20 07:49:28 +0000394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 if (argc == 0)
396 v = PyUnicode_FromString("");
397 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200398 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 else if ((v = PyTuple_New(argc)) != NULL) {
400 int i;
401 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 for (i = 0; i < argc; i++) {
404 if ((w = Split(argv[i])) == NULL) {
405 Py_DECREF(v);
406 v = NULL;
407 break;
408 }
409 PyTuple_SetItem(v, i, w);
410 }
411 }
412 Tcl_Free(FREECAST argv);
413 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000414}
415
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300416/* In some cases, Tcl will still return strings that are supposed to
417 be lists. SplitObj walks through a nested tuple, finding string
418 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000419
Martin v. Löwis59683e82008-06-13 07:50:45 +0000420static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000421SplitObj(PyObject *arg)
422{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 if (PyTuple_Check(arg)) {
424 int i, size;
425 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 size = PyTuple_Size(arg);
428 result = NULL;
429 /* Recursively invoke SplitObj for all tuple items.
430 If this does not return a new object, no action is
431 needed. */
432 for(i = 0; i < size; i++) {
433 elem = PyTuple_GetItem(arg, i);
434 newelem = SplitObj(elem);
435 if (!newelem) {
436 Py_XDECREF(result);
437 return NULL;
438 }
439 if (!result) {
440 int k;
441 if (newelem == elem) {
442 Py_DECREF(newelem);
443 continue;
444 }
445 result = PyTuple_New(size);
446 if (!result)
447 return NULL;
448 for(k = 0; k < i; k++) {
449 elem = PyTuple_GetItem(arg, k);
450 Py_INCREF(elem);
451 PyTuple_SetItem(result, k, elem);
452 }
453 }
454 PyTuple_SetItem(result, i, newelem);
455 }
456 if (result)
457 return result;
458 /* Fall through, returning arg. */
459 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300460 else if (PyList_Check(arg)) {
461 int i, size;
462 PyObject *elem, *newelem, *result;
463
464 size = PyList_GET_SIZE(arg);
465 result = PyTuple_New(size);
466 if (!result)
467 return NULL;
468 /* Recursively invoke SplitObj for all list items. */
469 for(i = 0; i < size; i++) {
470 elem = PyList_GET_ITEM(arg, i);
471 newelem = SplitObj(elem);
472 if (!newelem) {
473 Py_XDECREF(result);
474 return NULL;
475 }
476 PyTuple_SetItem(result, i, newelem);
477 }
478 return result;
479 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300480 else if (PyUnicode_Check(arg)) {
481 int argc;
482 char **argv;
483 char *list = PyUnicode_AsUTF8(arg);
484
485 if (list == NULL ||
486 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
487 Py_INCREF(arg);
488 return arg;
489 }
490 Tcl_Free(FREECAST argv);
491 if (argc > 1)
492 return Split(list);
493 /* Fall through, returning arg. */
494 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 else if (PyBytes_Check(arg)) {
496 int argc;
497 char **argv;
498 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
501 Py_INCREF(arg);
502 return arg;
503 }
504 Tcl_Free(FREECAST argv);
505 if (argc > 1)
506 return Split(PyBytes_AsString(arg));
507 /* Fall through, returning arg. */
508 }
509 Py_INCREF(arg);
510 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000511}
Barry Warsawfa701a81997-01-16 00:15:11 +0000512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513
Guido van Rossum18468821994-06-20 07:49:28 +0000514/**** Tkapp Object ****/
515
516#ifndef WITH_APPINIT
517int
Fred Drake509d79a2000-07-08 04:04:38 +0000518Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000519{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000522 if (Tcl_Init(interp) == TCL_ERROR) {
523 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
524 return TCL_ERROR;
525 }
Guilherme Polob681df42009-02-09 22:33:59 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 _tkinter_skip_tk_init = Tcl_GetVar(interp,
528 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
529 if (_tkinter_skip_tk_init != NULL &&
530 strcmp(_tkinter_skip_tk_init, "1") == 0) {
531 return TCL_OK;
532 }
Guilherme Polob681df42009-02-09 22:33:59 +0000533
534#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 if (tk_load_failed) {
536 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
537 return TCL_ERROR;
538 }
Guilherme Polob681df42009-02-09 22:33:59 +0000539#endif
540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000542#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000543 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000544#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
546 return TCL_ERROR;
547 }
Guilherme Polob681df42009-02-09 22:33:59 +0000548
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000550}
551#endif /* !WITH_APPINIT */
552
Guido van Rossum18468821994-06-20 07:49:28 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554
Barry Warsawfa701a81997-01-16 00:15:11 +0000555
556/* Initialize the Tk application; see the `main' function in
557 * `tkMain.c'.
558 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000559
Thomas Wouters58d05102000-07-24 14:43:35 +0000560static void EnableEventHook(void); /* Forward */
561static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000562
Barry Warsawfa701a81997-01-16 00:15:11 +0000563static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000564Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 TkappObject *v;
568 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000569
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300570 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 if (v == NULL)
572 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200573 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 v->interp = Tcl_CreateInterp();
576 v->wantobjects = wantobjects;
577 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
578 TCL_GLOBAL_ONLY) != NULL;
579 v->thread_id = Tcl_GetCurrentThread();
580 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000581
582#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300584 PyErr_SetString(PyExc_RuntimeError,
585 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000586 Py_DECREF(v);
587 return 0;
588 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000589#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000590#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 if (v->threaded && tcl_lock) {
592 /* If Tcl is threaded, we don't need the lock. */
593 PyThread_free_lock(tcl_lock);
594 tcl_lock = NULL;
595 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000596#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 v->BooleanType = Tcl_GetObjType("boolean");
599 v->ByteArrayType = Tcl_GetObjType("bytearray");
600 v->DoubleType = Tcl_GetObjType("double");
601 v->IntType = Tcl_GetObjType("int");
602 v->ListType = Tcl_GetObjType("list");
603 v->ProcBodyType = Tcl_GetObjType("procbody");
604 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 /* Delete the 'exit' command, which can screw things up */
607 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (screenName != NULL)
610 Tcl_SetVar2(v->interp, "env", "DISPLAY",
611 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 if (interactive)
614 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
615 else
616 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000617
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000618 /* This is used to get the application class for Tk 4.1 and up */
619 argv0 = (char*)ckalloc(strlen(className) + 1);
620 if (!argv0) {
621 PyErr_NoMemory();
622 Py_DECREF(v);
623 return NULL;
624 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200627 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
628 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
630 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632 if (! wantTk) {
633 Tcl_SetVar(v->interp,
634 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
635 }
Guilherme Polob681df42009-02-09 22:33:59 +0000636#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 else if (tk_load_failed) {
638 Tcl_SetVar(v->interp,
639 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
640 }
Guilherme Polob681df42009-02-09 22:33:59 +0000641#endif
David Aschere2b4b322004-02-18 05:59:53 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 /* some initial arguments need to be in argv */
644 if (sync || use) {
645 char *args;
646 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 if (sync)
649 len += sizeof "-sync";
650 if (use)
651 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 args = (char*)ckalloc(len);
654 if (!args) {
655 PyErr_NoMemory();
656 Py_DECREF(v);
657 return NULL;
658 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 args[0] = '\0';
661 if (sync)
662 strcat(args, "-sync");
663 if (use) {
664 if (sync)
665 strcat(args, " ");
666 strcat(args, "-use ");
667 strcat(args, use);
668 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
671 ckfree(args);
672 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 if (Tcl_AppInit(v->interp) != TCL_OK) {
675 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000676#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 if (wantTk) {
678 const char *_tkinter_tk_failed;
679 _tkinter_tk_failed = Tcl_GetVar(v->interp,
680 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 if ( _tkinter_tk_failed != NULL &&
683 strcmp(_tkinter_tk_failed, "1") == 0) {
684 tk_load_failed = 1;
685 }
686 }
Guilherme Polob681df42009-02-09 22:33:59 +0000687#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 Py_DECREF((PyObject *)v);
689 return (TkappObject *)result;
690 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000695}
696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697
Benjamin Peterson5879d412009-03-30 14:51:56 +0000698#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000702{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000710}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000711#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713
Guido van Rossum18468821994-06-20 07:49:28 +0000714/** Tcl Eval **/
715
Martin v. Löwisffad6332002-11-26 09:28:05 +0000716typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 PyObject_HEAD
718 Tcl_Obj *value;
719 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000720} PyTclObject;
721
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300722static PyObject *PyTclObject_Type;
723#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000724
725static PyObject *
726newPyTclObject(Tcl_Obj *arg)
727{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300729 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 if (self == NULL)
731 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200732 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 Tcl_IncrRefCount(arg);
734 self->value = arg;
735 self->string = NULL;
736 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000737}
738
739static void
740PyTclObject_dealloc(PyTclObject *self)
741{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200742 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 Tcl_DecrRefCount(self->value);
744 Py_XDECREF(self->string);
745 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200746 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000747}
748
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000749static char*
750PyTclObject_TclString(PyObject *self)
751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000753}
754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000756PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000757"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000758
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000759static PyObject *
760PyTclObject_string(PyTclObject *self, void *ignored)
761{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200763 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 if (!self->string)
765 return NULL;
766 }
767 Py_INCREF(self->string);
768 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000769}
770
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000771static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000772PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200774 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 Py_INCREF(self->string);
776 return self->string;
777 }
778 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200779 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000780}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000781
Martin v. Löwisffad6332002-11-26 09:28:05 +0000782static PyObject *
783PyTclObject_repr(PyTclObject *self)
784{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300785 PyObject *repr, *str = PyTclObject_str(self, NULL);
786 if (str == NULL)
787 return NULL;
788 repr = PyUnicode_FromFormat("<%s object: %R>",
789 self->value->typePtr->name, str);
790 Py_DECREF(str);
791 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000792}
793
Mark Dickinson211c6252009-02-01 10:28:51 +0000794#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
795
796static PyObject *
797PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 int result;
800 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 /* neither argument should be NULL, unless something's gone wrong */
803 if (self == NULL || other == NULL) {
804 PyErr_BadInternalCall();
805 return NULL;
806 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 /* both arguments should be instances of PyTclObject */
809 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
810 v = Py_NotImplemented;
811 goto finished;
812 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 if (self == other)
815 /* fast path when self and other are identical */
816 result = 0;
817 else
818 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
819 Tcl_GetString(((PyTclObject *)other)->value));
820 /* Convert return value to a Boolean */
821 switch (op) {
822 case Py_EQ:
823 v = TEST_COND(result == 0);
824 break;
825 case Py_NE:
826 v = TEST_COND(result != 0);
827 break;
828 case Py_LE:
829 v = TEST_COND(result <= 0);
830 break;
831 case Py_GE:
832 v = TEST_COND(result >= 0);
833 break;
834 case Py_LT:
835 v = TEST_COND(result < 0);
836 break;
837 case Py_GT:
838 v = TEST_COND(result > 0);
839 break;
840 default:
841 PyErr_BadArgument();
842 return NULL;
843 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000844 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000845 Py_INCREF(v);
846 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000847}
848
Martin v. Löwis39195712003-01-04 00:33:13 +0000849PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
850
Martin v. Löwisffad6332002-11-26 09:28:05 +0000851static PyObject*
852get_typename(PyTclObject* obj, void* ignored)
853{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200854 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855}
856
Martin v. Löwis39195712003-01-04 00:33:13 +0000857
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 {"typename", (getter)get_typename, NULL, get_typename__doc__},
860 {"string", (getter)PyTclObject_string, NULL,
861 PyTclObject_string__doc__},
862 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000863};
864
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300865static PyType_Slot PyTclObject_Type_slots[] = {
866 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
867 {Py_tp_repr, (reprfunc)PyTclObject_repr},
868 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200869 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300870 {Py_tp_richcompare, PyTclObject_richcompare},
871 {Py_tp_getset, PyTclObject_getsetlist},
872 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873};
874
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300875static PyType_Spec PyTclObject_Type_spec = {
876 "_tkinter.Tcl_Obj",
877 sizeof(PyTclObject),
878 0,
879 Py_TPFLAGS_DEFAULT,
880 PyTclObject_Type_slots,
881};
882
883
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000884static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000885AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000886{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 Tcl_Obj *result;
888 long longVal;
889 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000891 if (PyBytes_Check(value))
892 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
893 PyBytes_GET_SIZE(value));
894 else if (PyBool_Check(value))
895 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
896 else if (PyLong_CheckExact(value) &&
897 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
898 !overflow)) {
899 /* If there is an overflow in the long conversion,
900 fall through to default object handling. */
901 return Tcl_NewLongObj(longVal);
902 }
903 else if (PyFloat_Check(value))
904 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300905 else if (PyTuple_Check(value) || PyList_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300906 Tcl_Obj **argv;
907 Py_ssize_t size, i;
908
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300909 size = PySequence_Fast_GET_SIZE(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300910 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300911 PyErr_SetString(PyExc_OverflowError,
912 PyTuple_Check(value) ? "tuple is too long" :
913 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300914 return NULL;
915 }
916 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000917 if(!argv)
918 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300919 for (i = 0; i < size; i++)
Serhiy Storchaka2b00c492014-05-21 17:12:21 +0300920 argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
921 result = Tcl_NewListObj(size, argv);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922 ckfree(FREECAST argv);
923 return result;
924 }
925 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200926 void *inbuf;
927 Py_ssize_t size;
928 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 Tcl_UniChar *outbuf = NULL;
930 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200931 size_t allocsize;
932
933 if (PyUnicode_READY(value) == -1)
934 return NULL;
935
936 inbuf = PyUnicode_DATA(value);
937 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300938 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
939 PyErr_SetString(PyExc_OverflowError, "string is too long");
940 return NULL;
941 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200942 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200943 if (kind == sizeof(Tcl_UniChar))
944 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200945 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
946 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000947 /* Else overflow occurred, and we take the next exit */
948 if (!outbuf) {
949 PyErr_NoMemory();
950 return NULL;
951 }
952 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200953 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
954 /* We cannot test for sizeof(Tcl_UniChar) directly,
955 so we test for UTF-8 size instead. */
956#if TCL_UTF_MAX == 3
957 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000958 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200959 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100960 "character U+%x is above the range "
961 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100962 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000963 ckfree(FREECAST outbuf);
964 return NULL;
965 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300966#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200967 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 }
969 result = Tcl_NewUnicodeObj(outbuf, size);
970 ckfree(FREECAST outbuf);
971 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000972 }
973 else if(PyTclObject_Check(value)) {
974 Tcl_Obj *v = ((PyTclObject*)value)->value;
975 Tcl_IncrRefCount(v);
976 return v;
977 }
978 else {
979 PyObject *v = PyObject_Str(value);
980 if (!v)
981 return 0;
982 result = AsObj(v);
983 Py_DECREF(v);
984 return result;
985 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000986}
987
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988static PyObject*
989FromObj(PyObject* tkapp, Tcl_Obj *value)
990{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 PyObject *result = NULL;
992 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000994 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200995 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000996 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 if (value->typePtr == app->BooleanType) {
999 result = value->internalRep.longValue ? Py_True : Py_False;
1000 Py_INCREF(result);
1001 return result;
1002 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 if (value->typePtr == app->ByteArrayType) {
1005 int size;
1006 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1007 return PyBytes_FromStringAndSize(data, size);
1008 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 if (value->typePtr == app->DoubleType) {
1011 return PyFloat_FromDouble(value->internalRep.doubleValue);
1012 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 if (value->typePtr == app->IntType) {
1015 return PyLong_FromLong(value->internalRep.longValue);
1016 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 if (value->typePtr == app->ListType) {
1019 int size;
1020 int i, status;
1021 PyObject *elem;
1022 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001024 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1025 if (status == TCL_ERROR)
1026 return Tkinter_Error(tkapp);
1027 result = PyTuple_New(size);
1028 if (!result)
1029 return NULL;
1030 for (i = 0; i < size; i++) {
1031 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1032 value, i, &tcl_elem);
1033 if (status == TCL_ERROR) {
1034 Py_DECREF(result);
1035 return Tkinter_Error(tkapp);
1036 }
1037 elem = FromObj(tkapp, tcl_elem);
1038 if (!elem) {
1039 Py_DECREF(result);
1040 return NULL;
1041 }
1042 PyTuple_SetItem(result, i, elem);
1043 }
1044 return result;
1045 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 if (value->typePtr == app->ProcBodyType) {
1048 /* fall through: return tcl object. */
1049 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001052 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001053 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001054 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001058}
1059
Benjamin Peterson5879d412009-03-30 14:51:56 +00001060#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001062TCL_DECLARE_MUTEX(call_mutex)
1063
1064typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 Tcl_Event ev; /* Must be first */
1066 TkappObject *self;
1067 PyObject *args;
1068 int flags;
1069 PyObject **res;
1070 PyObject **exc_type, **exc_value, **exc_tb;
1071 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001073#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001074
1075void
1076Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 int i;
1079 for (i = 0; i < objc; i++)
1080 Tcl_DecrRefCount(objv[i]);
1081 if (objv != objStore)
1082 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001083}
Guido van Rossum18468821994-06-20 07:49:28 +00001084
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001085/* Convert Python objects to Tcl objects. This must happen in the
1086 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001087
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001088static Tcl_Obj**
1089Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001092 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001093 if (args == NULL)
1094 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001095
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001096 else if (!(PyTuple_Check(args) || PyList_Check(args))) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 objv[0] = AsObj(args);
1098 if (objv[0] == 0)
1099 goto finally;
1100 objc = 1;
1101 Tcl_IncrRefCount(objv[0]);
1102 }
1103 else {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001104 objc = PySequence_Fast_GET_SIZE(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001107 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001108 PyErr_SetString(PyExc_OverflowError,
1109 PyTuple_Check(args) ? "tuple is too long" :
1110 "list is too long");
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001111 return NULL;
1112 }
1113 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 if (objv == NULL) {
1115 PyErr_NoMemory();
1116 objc = 0;
1117 goto finally;
1118 }
1119 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 for (i = 0; i < objc; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001122 PyObject *v = PySequence_Fast_GET_ITEM(args, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001123 if (v == Py_None) {
1124 objc = i;
1125 break;
1126 }
1127 objv[i] = AsObj(v);
1128 if (!objv[i]) {
1129 /* Reset objc, so it attempts to clear
1130 objects only up to i. */
1131 objc = i;
1132 goto finally;
1133 }
1134 Tcl_IncrRefCount(objv[i]);
1135 }
1136 }
1137 *pobjc = objc;
1138 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001139finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 Tkapp_CallDeallocArgs(objv, objStore, objc);
1141 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001142}
Guido van Rossum212643f1998-04-29 16:22:14 +00001143
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001145
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001146static PyObject*
1147Tkapp_CallResult(TkappObject *self)
1148{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001150 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 /* Not sure whether the IncrRef is necessary, but something
1153 may overwrite the interpreter result while we are
1154 converting it. */
1155 Tcl_IncrRefCount(value);
1156 res = FromObj((PyObject*)self, value);
1157 Tcl_DecrRefCount(value);
1158 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001159 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 }
1161 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001162}
Guido van Rossum632de272000-03-29 00:19:50 +00001163
Benjamin Peterson5879d412009-03-30 14:51:56 +00001164#ifdef WITH_THREAD
1165
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166/* Tkapp_CallProc is the event procedure that is executed in the context of
1167 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1168 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001169
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170static int
1171Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 Tcl_Obj *objStore[ARGSZ];
1174 Tcl_Obj **objv;
1175 int objc;
1176 int i;
1177 ENTER_PYTHON
1178 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1179 if (!objv) {
1180 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1181 *(e->res) = NULL;
1182 }
1183 LEAVE_PYTHON
1184 if (!objv)
1185 goto done;
1186 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1187 ENTER_PYTHON
1188 if (i == TCL_ERROR) {
1189 *(e->res) = NULL;
1190 *(e->exc_type) = NULL;
1191 *(e->exc_tb) = NULL;
1192 *(e->exc_value) = PyObject_CallFunction(
1193 Tkinter_TclError, "s",
1194 Tcl_GetStringResult(e->self->interp));
1195 }
1196 else {
1197 *(e->res) = Tkapp_CallResult(e->self);
1198 }
1199 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001202done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 /* Wake up calling thread. */
1204 Tcl_MutexLock(&call_mutex);
1205 Tcl_ConditionNotify(e->done);
1206 Tcl_MutexUnlock(&call_mutex);
1207 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001208}
1209
Benjamin Peterson5879d412009-03-30 14:51:56 +00001210#endif
1211
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001212/* This is the main entry point for calling a Tcl command.
1213 It supports three cases, with regard to threading:
1214 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1215 the context of the calling thread.
1216 2. Tcl is threaded, caller of the command is in the interpreter thread:
1217 Execute the command in the calling thread. Since the Tcl lock will
1218 not be used, we can merge that with case 1.
1219 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1220 the interpreter thread. Allocation of Tcl objects needs to occur in the
1221 interpreter thread, so we ship the PyObject* args to the target thread,
1222 and perform processing there. */
1223
1224static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001225Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 Tcl_Obj *objStore[ARGSZ];
1228 Tcl_Obj **objv = NULL;
1229 int objc, i;
1230 PyObject *res = NULL;
1231 TkappObject *self = (TkappObject*)selfptr;
1232 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001234 /* If args is a single tuple, replace with contents of tuple */
1235 if (1 == PyTuple_Size(args)){
1236 PyObject* item = PyTuple_GetItem(args, 0);
1237 if (PyTuple_Check(item))
1238 args = item;
1239 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001240#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1242 /* We cannot call the command directly. Instead, we must
1243 marshal the parameters to the interpreter thread. */
1244 Tkapp_CallEvent *ev;
1245 Tcl_Condition cond = NULL;
1246 PyObject *exc_type, *exc_value, *exc_tb;
1247 if (!WaitForMainloop(self))
1248 return NULL;
1249 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1250 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1251 ev->self = self;
1252 ev->args = args;
1253 ev->res = &res;
1254 ev->exc_type = &exc_type;
1255 ev->exc_value = &exc_value;
1256 ev->exc_tb = &exc_tb;
1257 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001259 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001261 if (res == NULL) {
1262 if (exc_type)
1263 PyErr_Restore(exc_type, exc_value, exc_tb);
1264 else
1265 PyErr_SetObject(Tkinter_TclError, exc_value);
1266 }
1267 Tcl_ConditionFinalize(&cond);
1268 }
1269 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001270#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 objv = Tkapp_CallArgs(args, objStore, &objc);
1274 if (!objv)
1275 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 if (i == TCL_ERROR)
1284 Tkinter_Error(selfptr);
1285 else
1286 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001289
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 Tkapp_CallDeallocArgs(objv, objStore, objc);
1291 }
1292 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001293}
1294
1295
1296static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001297Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001299 char *script;
1300 PyObject *res = NULL;
1301 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 if (!PyArg_ParseTuple(args, "s:eval", &script))
1304 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001307
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001308 ENTER_TCL
1309 err = Tcl_Eval(Tkapp_Interp(self), script);
1310 ENTER_OVERLAP
1311 if (err == TCL_ERROR)
1312 res = Tkinter_Error(self);
1313 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001314 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 LEAVE_OVERLAP_TCL
1316 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001317}
1318
1319static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001320Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001321{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001322 char *fileName;
1323 PyObject *res = NULL;
1324 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1327 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 ENTER_TCL
1332 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1333 ENTER_OVERLAP
1334 if (err == TCL_ERROR)
1335 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001337 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 LEAVE_OVERLAP_TCL
1339 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001340}
1341
1342static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001343Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001344{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001345 char *script;
1346 PyObject *res = NULL;
1347 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 if (!PyArg_ParseTuple(args, "s", &script))
1350 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001352 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 ENTER_TCL
1355 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1356 ENTER_OVERLAP
1357 if (err == TCL_ERROR)
1358 res = Tkinter_Error(self);
1359 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001360 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 LEAVE_OVERLAP_TCL
1362 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001363}
1364
1365static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001366Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1371 return NULL;
1372 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001373
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001374 ENTER_TCL
1375 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1376 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001377
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001378 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001379}
1380
Barry Warsawfa701a81997-01-16 00:15:11 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382
Guido van Rossum18468821994-06-20 07:49:28 +00001383/** Tcl Variable **/
1384
Benjamin Peterson5879d412009-03-30 14:51:56 +00001385typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1386
1387#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388TCL_DECLARE_MUTEX(var_mutex)
1389
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 Tcl_Event ev; /* must be first */
1392 PyObject *self;
1393 PyObject *args;
1394 int flags;
1395 EventFunc func;
1396 PyObject **res;
1397 PyObject **exc_type;
1398 PyObject **exc_val;
1399 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001400} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001401#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001402
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001403static int
1404varname_converter(PyObject *in, void *_out)
1405{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001406 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 char **out = (char**)_out;
1408 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001409 if (PyBytes_Size(in) > INT_MAX) {
1410 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1411 return 0;
1412 }
1413 s = PyBytes_AsString(in);
1414 if (strlen(s) != PyBytes_Size(in)) {
1415 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1416 return 0;
1417 }
1418 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001419 return 1;
1420 }
1421 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001422 Py_ssize_t size;
1423 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001424 if (s == NULL) {
1425 return 0;
1426 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001427 if (size > INT_MAX) {
1428 PyErr_SetString(PyExc_OverflowError, "string is too long");
1429 return 0;
1430 }
1431 if (strlen(s) != size) {
1432 PyErr_SetString(PyExc_ValueError, "null character in string");
1433 return 0;
1434 }
1435 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 return 1;
1437 }
1438 if (PyTclObject_Check(in)) {
1439 *out = PyTclObject_TclString(in);
1440 return 1;
1441 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001442 PyErr_Format(PyExc_TypeError,
1443 "must be str, bytes or Tcl_Obj, not %.50s",
1444 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001446}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001447
Benjamin Peterson5879d412009-03-30 14:51:56 +00001448#ifdef WITH_THREAD
1449
Martin v. Löwis59683e82008-06-13 07:50:45 +00001450static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451var_perform(VarEvent *ev)
1452{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1454 if (!*(ev->res)) {
1455 PyObject *exc, *val, *tb;
1456 PyErr_Fetch(&exc, &val, &tb);
1457 PyErr_NormalizeException(&exc, &val, &tb);
1458 *(ev->exc_type) = exc;
1459 *(ev->exc_val) = val;
1460 Py_DECREF(tb);
1461 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001462
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463}
1464
1465static int
1466var_proc(VarEvent* ev, int flags)
1467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 ENTER_PYTHON
1469 var_perform(ev);
1470 Tcl_MutexLock(&var_mutex);
1471 Tcl_ConditionNotify(ev->cond);
1472 Tcl_MutexUnlock(&var_mutex);
1473 LEAVE_PYTHON
1474 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001475}
1476
Benjamin Peterson5879d412009-03-30 14:51:56 +00001477#endif
1478
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001480var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001482#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 TkappObject *self = (TkappObject*)selfptr;
1484 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1485 TkappObject *self = (TkappObject*)selfptr;
1486 VarEvent *ev;
1487 PyObject *res, *exc_type, *exc_val;
1488 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 /* The current thread is not the interpreter thread. Marshal
1491 the call to the interpreter thread, then wait for
1492 completion. */
1493 if (!WaitForMainloop(self))
1494 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 ev->self = selfptr;
1499 ev->args = args;
1500 ev->flags = flags;
1501 ev->func = func;
1502 ev->res = &res;
1503 ev->exc_type = &exc_type;
1504 ev->exc_val = &exc_val;
1505 ev->cond = &cond;
1506 ev->ev.proc = (Tcl_EventProc*)var_proc;
1507 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1508 Tcl_ConditionFinalize(&cond);
1509 if (!res) {
1510 PyErr_SetObject(exc_type, exc_val);
1511 Py_DECREF(exc_type);
1512 Py_DECREF(exc_val);
1513 return NULL;
1514 }
1515 return res;
1516 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001517#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 /* Tcl is not threaded, or this is the interpreter thread. */
1519 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001520}
1521
Guido van Rossum18468821994-06-20 07:49:28 +00001522static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001523SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001524{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001525 char *name1, *name2;
1526 PyObject *newValue;
1527 PyObject *res = NULL;
1528 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001529
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001530 switch (PyTuple_GET_SIZE(args)) {
1531 case 2:
1532 if (!PyArg_ParseTuple(args, "O&O:setvar",
1533 varname_converter, &name1, &newValue))
1534 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 /* XXX Acquire tcl lock??? */
1536 newval = AsObj(newValue);
1537 if (newval == NULL)
1538 return NULL;
1539 ENTER_TCL
1540 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1541 newval, flags);
1542 ENTER_OVERLAP
1543 if (!ok)
1544 Tkinter_Error(self);
1545 else {
1546 res = Py_None;
1547 Py_INCREF(res);
1548 }
1549 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001550 break;
1551 case 3:
1552 if (!PyArg_ParseTuple(args, "ssO:setvar",
1553 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001555 /* XXX must hold tcl lock already??? */
1556 newval = AsObj(newValue);
1557 ENTER_TCL
1558 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1559 ENTER_OVERLAP
1560 if (!ok)
1561 Tkinter_Error(self);
1562 else {
1563 res = Py_None;
1564 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001566 LEAVE_OVERLAP_TCL
1567 break;
1568 default:
1569 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1570 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 }
1572 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001573}
1574
1575static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001576Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001577{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001579}
1580
1581static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001582Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001583{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
Barry Warsawfa701a81997-01-16 00:15:11 +00001587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001588
Guido van Rossum18468821994-06-20 07:49:28 +00001589static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001590GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 char *name1, *name2=NULL;
1593 PyObject *res = NULL;
1594 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001596 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1597 varname_converter, &name1, &name2))
1598 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 ENTER_TCL
1601 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1602 ENTER_OVERLAP
1603 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001604 PyErr_SetString(Tkinter_TclError,
1605 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001606 } else {
1607 if (((TkappObject*)self)->wantobjects) {
1608 res = FromObj(self, tres);
1609 }
1610 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001611 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001612 }
1613 }
1614 LEAVE_OVERLAP_TCL
1615 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001616}
1617
1618static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001619Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001622}
1623
1624static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001625Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001626{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001627 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001628}
1629
Barry Warsawfa701a81997-01-16 00:15:11 +00001630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001631
Guido van Rossum18468821994-06-20 07:49:28 +00001632static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001633UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001634{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001635 char *name1, *name2=NULL;
1636 int code;
1637 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001638
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1640 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001642 ENTER_TCL
1643 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1644 ENTER_OVERLAP
1645 if (code == TCL_ERROR)
1646 res = Tkinter_Error(self);
1647 else {
1648 Py_INCREF(Py_None);
1649 res = Py_None;
1650 }
1651 LEAVE_OVERLAP_TCL
1652 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
1655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001664 return var_invoke(UnsetVar, self, args,
1665 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001666}
1667
Barry Warsawfa701a81997-01-16 00:15:11 +00001668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001669
Guido van Rossum18468821994-06-20 07:49:28 +00001670/** Tcl to Python **/
1671
1672static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001673Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001674{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 char *s;
1676 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 if (PyTuple_Size(args) == 1) {
1679 PyObject* o = PyTuple_GetItem(args, 0);
1680 if (PyLong_Check(o)) {
1681 Py_INCREF(o);
1682 return o;
1683 }
1684 }
1685 if (!PyArg_ParseTuple(args, "s:getint", &s))
1686 return NULL;
1687 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1688 return Tkinter_Error(self);
1689 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001690}
1691
1692static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001693Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695 char *s;
1696 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001698 if (PyTuple_Size(args) == 1) {
1699 PyObject *o = PyTuple_GetItem(args, 0);
1700 if (PyFloat_Check(o)) {
1701 Py_INCREF(o);
1702 return o;
1703 }
1704 }
1705 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1706 return NULL;
1707 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1708 return Tkinter_Error(self);
1709 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001710}
1711
1712static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001713Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001714{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 char *s;
1716 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 if (PyTuple_Size(args) == 1) {
1719 PyObject *o = PyTuple_GetItem(args, 0);
1720 if (PyLong_Check(o)) {
1721 Py_INCREF(o);
1722 return o;
1723 }
1724 }
1725 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1726 return NULL;
1727 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1728 return Tkinter_Error(self);
1729 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
1732static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001733Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001734{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735 char *s;
1736 PyObject *res = NULL;
1737 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1740 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001744 ENTER_TCL
1745 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1746 ENTER_OVERLAP
1747 if (retval == TCL_ERROR)
1748 res = Tkinter_Error(self);
1749 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001750 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001751 LEAVE_OVERLAP_TCL
1752 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001753}
1754
1755static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001756Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001757{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 char *s;
1759 PyObject *res = NULL;
1760 int retval;
1761 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001763 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1764 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001766 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001767
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 ENTER_TCL
1769 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1770 ENTER_OVERLAP
1771 if (retval == TCL_ERROR)
1772 res = Tkinter_Error(self);
1773 else
1774 res = Py_BuildValue("l", v);
1775 LEAVE_OVERLAP_TCL
1776 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001777}
1778
1779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001780Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 char *s;
1783 PyObject *res = NULL;
1784 double v;
1785 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001787 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1788 return NULL;
1789 CHECK_TCL_APPARTMENT;
1790 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1791 ENTER_TCL
1792 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1793 ENTER_OVERLAP
1794 PyFPE_END_PROTECT(retval)
1795 if (retval == TCL_ERROR)
1796 res = Tkinter_Error(self);
1797 else
1798 res = Py_BuildValue("d", v);
1799 LEAVE_OVERLAP_TCL
1800 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001801}
1802
1803static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001804Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001805{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001806 char *s;
1807 PyObject *res = NULL;
1808 int retval;
1809 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001810
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1812 return NULL;
1813 CHECK_TCL_APPARTMENT;
1814 ENTER_TCL
1815 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1816 ENTER_OVERLAP
1817 if (retval == TCL_ERROR)
1818 res = Tkinter_Error(self);
1819 else
1820 res = Py_BuildValue("i", v);
1821 LEAVE_OVERLAP_TCL
1822 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001823}
1824
Barry Warsawfa701a81997-01-16 00:15:11 +00001825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826
Guido van Rossum18468821994-06-20 07:49:28 +00001827static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001828Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001829{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 char *list;
1831 int argc;
1832 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001833 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001835
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001836 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1837 return NULL;
1838 if (PyTclObject_Check(arg)) {
1839 int objc;
1840 Tcl_Obj **objv;
1841 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1842 ((PyTclObject*)arg)->value,
1843 &objc, &objv) == TCL_ERROR) {
1844 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001845 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001846 if (!(v = PyTuple_New(objc)))
1847 return NULL;
1848 for (i = 0; i < objc; i++) {
1849 PyObject *s = FromObj(self, objv[i]);
1850 if (!s || PyTuple_SetItem(v, i, s)) {
1851 Py_DECREF(v);
1852 return NULL;
1853 }
1854 }
1855 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001856 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001857 if (PyTuple_Check(arg)) {
1858 Py_INCREF(arg);
1859 return arg;
1860 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001861 if (PyList_Check(arg)) {
1862 return PySequence_Tuple(arg);
1863 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001864
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001865 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1866 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001867
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 if (Tcl_SplitList(Tkapp_Interp(self), list,
1869 &argc, &argv) == TCL_ERROR) {
1870 PyMem_Free(list);
1871 return Tkinter_Error(self);
1872 }
Guido van Rossum18468821994-06-20 07:49:28 +00001873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 if (!(v = PyTuple_New(argc)))
1875 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001876
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001877 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001878 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001879 if (!s || PyTuple_SetItem(v, i, s)) {
1880 Py_DECREF(v);
1881 v = NULL;
1882 goto finally;
1883 }
1884 }
Guido van Rossum18468821994-06-20 07:49:28 +00001885
Barry Warsawfa701a81997-01-16 00:15:11 +00001886 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 ckfree(FREECAST argv);
1888 PyMem_Free(list);
1889 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001890}
1891
1892static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001893Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001894{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001895 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001897
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001898 if (!PyArg_ParseTuple(args, "O:split", &arg))
1899 return NULL;
1900 if (PyTclObject_Check(arg)) {
1901 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1902 int objc;
1903 Tcl_Obj **objv;
1904 int i;
1905 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1906 &objc, &objv) == TCL_ERROR) {
1907 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001909 if (objc == 0)
1910 return PyUnicode_FromString("");
1911 if (objc == 1)
1912 return FromObj(self, objv[0]);
1913 if (!(v = PyTuple_New(objc)))
1914 return NULL;
1915 for (i = 0; i < objc; i++) {
1916 PyObject *s = FromObj(self, objv[i]);
1917 if (!s || PyTuple_SetItem(v, i, s)) {
1918 Py_DECREF(v);
1919 return NULL;
1920 }
1921 }
1922 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001923 }
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03001924 if (PyTuple_Check(arg) || PyList_Check(arg))
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001925 return SplitObj(arg);
1926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1928 return NULL;
1929 v = Split(list);
1930 PyMem_Free(list);
1931 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001932}
1933
Barry Warsawfa701a81997-01-16 00:15:11 +00001934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935
Guido van Rossum18468821994-06-20 07:49:28 +00001936/** Tcl Command **/
1937
Guido van Rossum00d93061998-05-28 23:06:38 +00001938/* Client data struct */
1939typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 PyObject *self;
1941 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001942} PythonCmd_ClientData;
1943
1944static int
Fred Drake509d79a2000-07-08 04:04:38 +00001945PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001946{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001947 errorInCmd = 1;
1948 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1949 LEAVE_PYTHON
1950 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001951}
1952
Guido van Rossum18468821994-06-20 07:49:28 +00001953/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001954 * function or method.
1955 */
Guido van Rossum18468821994-06-20 07:49:28 +00001956static int
Fred Drake509d79a2000-07-08 04:04:38 +00001957PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001958{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001959 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001960 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001961 int i, rv;
1962 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001966 /* TBD: no error checking here since we know, via the
1967 * Tkapp_CreateCommand() that the client data is a two-tuple
1968 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 /* Create argument list (argv1, ..., argvN) */
1972 if (!(arg = PyTuple_New(argc - 1)))
1973 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001976 PyObject *s = unicodeFromTclString(argv[i + 1]);
1977 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 Py_DECREF(arg);
1979 return PythonCmd_Error(interp);
1980 }
1981 }
1982 res = PyEval_CallObject(func, arg);
1983 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 if (res == NULL)
1986 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 obj_res = AsObj(res);
1989 if (obj_res == NULL) {
1990 Py_DECREF(res);
1991 return PythonCmd_Error(interp);
1992 }
1993 else {
1994 Tcl_SetObjResult(interp, obj_res);
1995 rv = TCL_OK;
1996 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001997
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001998 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001999
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002000 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002002 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002003}
2004
2005static void
Fred Drake509d79a2000-07-08 04:04:38 +00002006PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002007{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 ENTER_PYTHON
2011 Py_XDECREF(data->self);
2012 Py_XDECREF(data->func);
2013 PyMem_DEL(data);
2014 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002015}
2016
Barry Warsawfa701a81997-01-16 00:15:11 +00002017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002019
Benjamin Peterson5879d412009-03-30 14:51:56 +00002020#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002021TCL_DECLARE_MUTEX(command_mutex)
2022
2023typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002024 Tcl_Event ev;
2025 Tcl_Interp* interp;
2026 char *name;
2027 int create;
2028 int *status;
2029 ClientData *data;
2030 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002031} CommandEvent;
2032
2033static int
2034Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002035{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002036 if (ev->create)
2037 *ev->status = Tcl_CreateCommand(
2038 ev->interp, ev->name, PythonCmd,
2039 ev->data, PythonCmdDelete) == NULL;
2040 else
2041 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2042 Tcl_MutexLock(&command_mutex);
2043 Tcl_ConditionNotify(ev->done);
2044 Tcl_MutexUnlock(&command_mutex);
2045 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002046}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002047#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002048
2049static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002050Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002052 TkappObject *self = (TkappObject*)selfptr;
2053 PythonCmd_ClientData *data;
2054 char *cmdName;
2055 PyObject *func;
2056 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002057
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002058 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2059 return NULL;
2060 if (!PyCallable_Check(func)) {
2061 PyErr_SetString(PyExc_TypeError, "command not callable");
2062 return NULL;
2063 }
Guido van Rossum18468821994-06-20 07:49:28 +00002064
Martin v. Löwisa9656492003-03-30 08:44:58 +00002065#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002066 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2067 !WaitForMainloop(self))
2068 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002069#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 data = PyMem_NEW(PythonCmd_ClientData, 1);
2072 if (!data)
2073 return PyErr_NoMemory();
2074 Py_INCREF(self);
2075 Py_INCREF(func);
2076 data->self = selfptr;
2077 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002078#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002079 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2080 Tcl_Condition cond = NULL;
2081 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2082 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2083 ev->interp = self->interp;
2084 ev->create = 1;
2085 ev->name = cmdName;
2086 ev->data = (ClientData)data;
2087 ev->status = &err;
2088 ev->done = &cond;
2089 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2090 Tcl_ConditionFinalize(&cond);
2091 }
2092 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002093#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 {
2095 ENTER_TCL
2096 err = Tcl_CreateCommand(
2097 Tkapp_Interp(self), cmdName, PythonCmd,
2098 (ClientData)data, PythonCmdDelete) == NULL;
2099 LEAVE_TCL
2100 }
2101 if (err) {
2102 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2103 PyMem_DEL(data);
2104 return NULL;
2105 }
Guido van Rossum18468821994-06-20 07:49:28 +00002106
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002107 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002108}
2109
Barry Warsawfa701a81997-01-16 00:15:11 +00002110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111
Guido van Rossum18468821994-06-20 07:49:28 +00002112static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002113Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 TkappObject *self = (TkappObject*)selfptr;
2116 char *cmdName;
2117 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2120 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002121
2122#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2124 Tcl_Condition cond = NULL;
2125 CommandEvent *ev;
2126 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2127 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2128 ev->interp = self->interp;
2129 ev->create = 0;
2130 ev->name = cmdName;
2131 ev->status = &err;
2132 ev->done = &cond;
2133 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2134 &command_mutex);
2135 Tcl_ConditionFinalize(&cond);
2136 }
2137 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002138#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 {
2140 ENTER_TCL
2141 err = Tcl_DeleteCommand(self->interp, cmdName);
2142 LEAVE_TCL
2143 }
2144 if (err == -1) {
2145 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2146 return NULL;
2147 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002148 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002149}
2150
Barry Warsawfa701a81997-01-16 00:15:11 +00002151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002152
Guido van Rossum00d93061998-05-28 23:06:38 +00002153#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002154/** File Handler **/
2155
Guido van Rossum00d93061998-05-28 23:06:38 +00002156typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 PyObject *func;
2158 PyObject *file;
2159 int id;
2160 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002161} FileHandler_ClientData;
2162
2163static FileHandler_ClientData *HeadFHCD;
2164
2165static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002166NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002167{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 FileHandler_ClientData *p;
2169 p = PyMem_NEW(FileHandler_ClientData, 1);
2170 if (p != NULL) {
2171 Py_XINCREF(func);
2172 Py_XINCREF(file);
2173 p->func = func;
2174 p->file = file;
2175 p->id = id;
2176 p->next = HeadFHCD;
2177 HeadFHCD = p;
2178 }
2179 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002180}
2181
2182static void
Fred Drake509d79a2000-07-08 04:04:38 +00002183DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002184{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002186
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 pp = &HeadFHCD;
2188 while ((p = *pp) != NULL) {
2189 if (p->id == id) {
2190 *pp = p->next;
2191 Py_XDECREF(p->func);
2192 Py_XDECREF(p->file);
2193 PyMem_DEL(p);
2194 }
2195 else
2196 pp = &p->next;
2197 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002198}
2199
Guido van Rossuma597dde1995-01-10 20:56:29 +00002200static void
Fred Drake509d79a2000-07-08 04:04:38 +00002201FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002202{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2204 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002205
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 ENTER_PYTHON
2207 func = data->func;
2208 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210 arg = Py_BuildValue("(Oi)", file, (long) mask);
2211 res = PyEval_CallObject(func, arg);
2212 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 if (res == NULL) {
2215 errorInCmd = 1;
2216 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2217 }
2218 Py_XDECREF(res);
2219 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002220}
2221
Guido van Rossum18468821994-06-20 07:49:28 +00002222static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002223Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2224 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 FileHandler_ClientData *data;
2227 PyObject *file, *func;
2228 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2231 &file, &mask, &func))
2232 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 tfile = PyObject_AsFileDescriptor(file);
2237 if (tfile < 0)
2238 return NULL;
2239 if (!PyCallable_Check(func)) {
2240 PyErr_SetString(PyExc_TypeError, "bad argument list");
2241 return NULL;
2242 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002243
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 data = NewFHCD(func, file, tfile);
2245 if (data == NULL)
2246 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 /* Ought to check for null Tcl_File object... */
2249 ENTER_TCL
2250 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2251 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002252 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002253}
2254
2255static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002256Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002257{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258 PyObject *file;
2259 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002261 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2262 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 tfile = PyObject_AsFileDescriptor(file);
2267 if (tfile < 0)
2268 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002271
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002272 /* Ought to check for null Tcl_File object... */
2273 ENTER_TCL
2274 Tcl_DeleteFileHandler(tfile);
2275 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002276 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002277}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002278#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002281/**** Tktt Object (timer token) ****/
2282
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002283static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002284
Guido van Rossum00d93061998-05-28 23:06:38 +00002285typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 PyObject_HEAD
2287 Tcl_TimerToken token;
2288 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002289} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290
2291static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002292Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002293{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002294 TkttObject *v = (TkttObject *)self;
2295 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2298 return NULL;
2299 if (v->token != NULL) {
2300 Tcl_DeleteTimerHandler(v->token);
2301 v->token = NULL;
2302 }
2303 if (func != NULL) {
2304 v->func = NULL;
2305 Py_DECREF(func);
2306 Py_DECREF(v); /* See Tktt_New() */
2307 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002308 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002309}
2310
2311static PyMethodDef Tktt_methods[] =
2312{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2314 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002315};
2316
2317static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002318Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002320 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002321
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002322 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002323 if (v == NULL)
2324 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002325 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 Py_INCREF(func);
2328 v->token = NULL;
2329 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 /* Extra reference, deleted when called or when handler is deleted */
2332 Py_INCREF(v);
2333 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334}
2335
2336static void
Fred Drake509d79a2000-07-08 04:04:38 +00002337Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002338{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002339 TkttObject *v = (TkttObject *)self;
2340 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002341 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002346 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002347}
2348
Guido van Rossum597ac201998-05-12 14:36:19 +00002349static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002350Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002353 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2354 v,
2355 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002356}
2357
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002358static PyType_Slot Tktt_Type_slots[] = {
2359 {Py_tp_dealloc, Tktt_Dealloc},
2360 {Py_tp_repr, Tktt_Repr},
2361 {Py_tp_methods, Tktt_methods},
2362 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363};
2364
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002365static PyType_Spec Tktt_Type_spec = {
2366 "tktimertoken",
2367 sizeof(TkttObject),
2368 0,
2369 Py_TPFLAGS_DEFAULT,
2370 Tktt_Type_slots,
2371};
Barry Warsawfa701a81997-01-16 00:15:11 +00002372
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002373
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002374/** Timer Handler **/
2375
2376static void
Fred Drake509d79a2000-07-08 04:04:38 +00002377TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 TkttObject *v = (TkttObject *)clientData;
2380 PyObject *func = v->func;
2381 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 if (func == NULL)
2384 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 res = PyEval_CallObject(func, NULL);
2391 Py_DECREF(func);
2392 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 if (res == NULL) {
2395 errorInCmd = 1;
2396 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2397 }
2398 else
2399 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402}
2403
2404static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002405Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 int milliseconds;
2408 PyObject *func;
2409 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2412 &milliseconds, &func))
2413 return NULL;
2414 if (!PyCallable_Check(func)) {
2415 PyErr_SetString(PyExc_TypeError, "bad argument list");
2416 return NULL;
2417 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002419 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002421 v = Tktt_New(func);
2422 if (v) {
2423 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2424 (ClientData)v);
2425 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428}
2429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430
Guido van Rossum18468821994-06-20 07:49:28 +00002431/** Event Loop **/
2432
Guido van Rossum18468821994-06-20 07:49:28 +00002433static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002434Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002435{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 int threshold = 0;
2437 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002438#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002440#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2443 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 CHECK_TCL_APPARTMENT;
2446 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002448 quitMainLoop = 0;
2449 while (Tk_GetNumMainWindows() > threshold &&
2450 !quitMainLoop &&
2451 !errorInCmd)
2452 {
2453 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002454
2455#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 if (self->threaded) {
2457 /* Allow other Python threads to run. */
2458 ENTER_TCL
2459 result = Tcl_DoOneEvent(0);
2460 LEAVE_TCL
2461 }
2462 else {
2463 Py_BEGIN_ALLOW_THREADS
2464 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2465 tcl_tstate = tstate;
2466 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2467 tcl_tstate = NULL;
2468 if(tcl_lock)PyThread_release_lock(tcl_lock);
2469 if (result == 0)
2470 Sleep(Tkinter_busywaitinterval);
2471 Py_END_ALLOW_THREADS
2472 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002473#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002475#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (PyErr_CheckSignals() != 0) {
2478 self->dispatching = 0;
2479 return NULL;
2480 }
2481 if (result < 0)
2482 break;
2483 }
2484 self->dispatching = 0;
2485 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002487 if (errorInCmd) {
2488 errorInCmd = 0;
2489 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2490 excInCmd = valInCmd = trbInCmd = NULL;
2491 return NULL;
2492 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002493 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002494}
2495
2496static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002497Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002498{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499 int flags = 0;
2500 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2503 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 ENTER_TCL
2506 rv = Tcl_DoOneEvent(flags);
2507 LEAVE_TCL
2508 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002509}
2510
2511static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002512Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002513{
2514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002515 if (!PyArg_ParseTuple(args, ":quit"))
2516 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002518 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002519 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002520}
2521
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002522static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002523Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002524{
2525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 if (!PyArg_ParseTuple(args, ":interpaddr"))
2527 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002528
Victor Stinnere1040e22013-09-05 00:22:24 +02002529 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002530}
2531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002533Tkapp_TkInit(PyObject *self, PyObject *args)
2534{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 Tcl_Interp *interp = Tkapp_Interp(self);
2536 const char * _tk_exists = NULL;
2537 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002538
Guilherme Polob681df42009-02-09 22:33:59 +00002539#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002540 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2541 * first call failed.
2542 * To avoid the deadlock, we just refuse the second call through
2543 * a static variable.
2544 */
2545 if (tk_load_failed) {
2546 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2547 return NULL;
2548 }
Guilherme Polob681df42009-02-09 22:33:59 +00002549#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002551 /* We want to guard against calling Tk_Init() multiple times */
2552 CHECK_TCL_APPARTMENT;
2553 ENTER_TCL
2554 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2555 ENTER_OVERLAP
2556 if (err == TCL_ERROR) {
2557 /* This sets an exception, but we cannot return right
2558 away because we need to exit the overlap first. */
2559 Tkinter_Error(self);
2560 } else {
2561 _tk_exists = Tkapp_Result(self);
2562 }
2563 LEAVE_OVERLAP_TCL
2564 if (err == TCL_ERROR) {
2565 return NULL;
2566 }
2567 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2568 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002569 PyErr_SetString(Tkinter_TclError,
2570 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002571#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002573#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002574 return NULL;
2575 }
2576 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002577 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002578}
Barry Warsawfa701a81997-01-16 00:15:11 +00002579
Martin v. Löwisffad6332002-11-26 09:28:05 +00002580static PyObject *
2581Tkapp_WantObjects(PyObject *self, PyObject *args)
2582{
2583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 int wantobjects = -1;
2585 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2586 return NULL;
2587 if (wantobjects == -1)
2588 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2589 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002590
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002591 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002592}
2593
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002594static PyObject *
2595Tkapp_WillDispatch(PyObject *self, PyObject *args)
2596{
2597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002598 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002599
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002600 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002601}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002603
Guido van Rossum18468821994-06-20 07:49:28 +00002604/**** Tkapp Method List ****/
2605
2606static PyMethodDef Tkapp_methods[] =
2607{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2609 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2610 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002612 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2613 {"record", Tkapp_Record, METH_VARARGS},
2614 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2615 {"setvar", Tkapp_SetVar, METH_VARARGS},
2616 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2617 {"getvar", Tkapp_GetVar, METH_VARARGS},
2618 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2619 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2620 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2621 {"getint", Tkapp_GetInt, METH_VARARGS},
2622 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2623 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2624 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2625 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2626 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2627 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2628 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2629 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2631 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002632#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2634 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002635#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2637 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2638 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2639 {"quit", Tkapp_Quit, METH_VARARGS},
2640 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2641 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2642 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002643};
2644
Barry Warsawfa701a81997-01-16 00:15:11 +00002645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646
Guido van Rossum18468821994-06-20 07:49:28 +00002647/**** Tkapp Type Methods ****/
2648
2649static void
Fred Drake509d79a2000-07-08 04:04:38 +00002650Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002651{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002652 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002653 /*CHECK_TCL_APPARTMENT;*/
2654 ENTER_TCL
2655 Tcl_DeleteInterp(Tkapp_Interp(self));
2656 LEAVE_TCL
2657 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002658 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002660}
2661
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002662static PyType_Slot Tkapp_Type_slots[] = {
2663 {Py_tp_dealloc, Tkapp_Dealloc},
2664 {Py_tp_methods, Tkapp_methods},
2665 {0, 0}
2666};
2667
2668
2669static PyType_Spec Tkapp_Type_spec = {
2670 "tkapp",
2671 sizeof(TkappObject),
2672 0,
2673 Py_TPFLAGS_DEFAULT,
2674 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002675};
2676
Barry Warsawfa701a81997-01-16 00:15:11 +00002677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678
Guido van Rossum18468821994-06-20 07:49:28 +00002679/**** Tkinter Module ****/
2680
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002681typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 PyObject* tuple;
2683 int size; /* current size */
2684 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002685} FlattenContext;
2686
2687static int
2688_bump(FlattenContext* context, int size)
2689{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690 /* expand tuple to hold (at least) size new items.
2691 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002692
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002693 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 if (maxsize < context->size + size)
2696 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002698 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002701}
2702
2703static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002704_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002707
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002708 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710 if (depth > 1000) {
2711 PyErr_SetString(PyExc_ValueError,
2712 "nesting too deep in _flatten");
2713 return 0;
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002714 } else if (PyTuple_Check(item) || PyList_Check(item)) {
2715 size = PySequence_Fast_GET_SIZE(item);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 /* preallocate (assume no nesting) */
2717 if (context->size + size > context->maxsize &&
2718 !_bump(context, size))
2719 return 0;
2720 /* copy items to output tuple */
2721 for (i = 0; i < size; i++) {
Serhiy Storchaka2b00c492014-05-21 17:12:21 +03002722 PyObject *o = PySequence_Fast_GET_ITEM(item, i);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 if (PyList_Check(o) || PyTuple_Check(o)) {
2724 if (!_flatten1(context, o, depth + 1))
2725 return 0;
2726 } else if (o != Py_None) {
2727 if (context->size + 1 > context->maxsize &&
2728 !_bump(context, 1))
2729 return 0;
2730 Py_INCREF(o);
2731 PyTuple_SET_ITEM(context->tuple,
2732 context->size++, o);
2733 }
2734 }
2735 } else {
2736 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2737 return 0;
2738 }
2739 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002740}
2741
2742static PyObject *
2743Tkinter_Flatten(PyObject* self, PyObject* args)
2744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 FlattenContext context;
2746 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002748 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2749 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002751 context.maxsize = PySequence_Size(item);
2752 if (context.maxsize < 0)
2753 return NULL;
2754 if (context.maxsize == 0)
2755 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 context.tuple = PyTuple_New(context.maxsize);
2758 if (!context.tuple)
2759 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002761 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002763 if (!_flatten1(&context, item,0))
2764 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766 if (_PyTuple_Resize(&context.tuple, context.size))
2767 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002770}
2771
Guido van Rossum18468821994-06-20 07:49:28 +00002772static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002773Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 char *screenName = NULL;
2776 char *baseName = NULL; /* XXX this is not used anymore;
2777 try getting rid of it. */
2778 char *className = NULL;
2779 int interactive = 0;
2780 int wantobjects = 0;
2781 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2782 int sync = 0; /* pass -sync to wish */
2783 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2788 &screenName, &baseName, &className,
2789 &interactive, &wantobjects, &wantTk,
2790 &sync, &use))
2791 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002794 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002796}
2797
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002798static PyObject *
2799Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2800{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 int new_val;
2802 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2803 return NULL;
2804 if (new_val < 0) {
2805 PyErr_SetString(PyExc_ValueError,
2806 "busywaitinterval must be >= 0");
2807 return NULL;
2808 }
2809 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002810 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002811}
2812
2813static char setbusywaitinterval_doc[] =
2814"setbusywaitinterval(n) -> None\n\
2815\n\
2816Set the busy-wait interval in milliseconds between successive\n\
2817calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2818It should be set to a divisor of the maximum time between\n\
2819frames in an animation.";
2820
2821static PyObject *
2822Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2823{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002825}
2826
2827static char getbusywaitinterval_doc[] =
2828"getbusywaitinterval() -> int\n\
2829\n\
2830Return the current busy-wait interval between successive\n\
2831calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2832
Guido van Rossum18468821994-06-20 07:49:28 +00002833static PyMethodDef moduleMethods[] =
2834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2836 {"create", Tkinter_Create, METH_VARARGS},
2837 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2838 setbusywaitinterval_doc},
2839 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2840 METH_NOARGS, getbusywaitinterval_doc},
2841 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002842};
2843
Guido van Rossum7bf15641998-05-22 18:28:17 +00002844#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002845
2846static int stdin_ready = 0;
2847
Guido van Rossumad4db171998-06-13 13:56:28 +00002848#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002849static void
Fred Drake509d79a2000-07-08 04:04:38 +00002850MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002851{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002853}
Guido van Rossumad4db171998-06-13 13:56:28 +00002854#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002855
Martin v. Löwisa9656492003-03-30 08:44:58 +00002856#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002857static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002858#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002859
Guido van Rossum18468821994-06-20 07:49:28 +00002860static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002861EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002862{
Guido van Rossumad4db171998-06-13 13:56:28 +00002863#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002865#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002866#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002868#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 stdin_ready = 0;
2870 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002871#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 tfile = fileno(stdin);
2873 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002874#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 while (!errorInCmd && !stdin_ready) {
2876 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002877#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 if (_kbhit()) {
2879 stdin_ready = 1;
2880 break;
2881 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002882#endif
2883#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002884 Py_BEGIN_ALLOW_THREADS
2885 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2886 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 tcl_tstate = NULL;
2891 if(tcl_lock)PyThread_release_lock(tcl_lock);
2892 if (result == 0)
2893 Sleep(Tkinter_busywaitinterval);
2894 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002895#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002897#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002898
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002899 if (result < 0)
2900 break;
2901 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002902#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002904#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 if (errorInCmd) {
2906 errorInCmd = 0;
2907 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2908 excInCmd = valInCmd = trbInCmd = NULL;
2909 PyErr_Print();
2910 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002911#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002913#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002915}
Guido van Rossum18468821994-06-20 07:49:28 +00002916
Guido van Rossum00d93061998-05-28 23:06:38 +00002917#endif
2918
Guido van Rossum7bf15641998-05-22 18:28:17 +00002919static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002920EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002921{
Guido van Rossum00d93061998-05-28 23:06:38 +00002922#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002923 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002924#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002925 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002926#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002927 PyOS_InputHook = EventHook;
2928 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002929#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002930}
2931
2932static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002933DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002934{
Guido van Rossum00d93061998-05-28 23:06:38 +00002935#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002936 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2937 PyOS_InputHook = NULL;
2938 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002939#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002940}
2941
Barry Warsawfa701a81997-01-16 00:15:11 +00002942
Martin v. Löwis1a214512008-06-11 05:26:20 +00002943static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 PyModuleDef_HEAD_INIT,
2945 "_tkinter",
2946 NULL,
2947 -1,
2948 moduleMethods,
2949 NULL,
2950 NULL,
2951 NULL,
2952 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002953};
2954
Mark Hammond62b1ab12002-07-23 06:31:15 +00002955PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002956PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002957{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002958 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002959
Guido van Rossum00d93061998-05-28 23:06:38 +00002960#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002962 if (tcl_lock == NULL)
2963 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002964#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002966 m = PyModule_Create(&_tkintermodule);
2967 if (m == NULL)
2968 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002969
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002970 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2971 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002972 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002974 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002975 Py_INCREF(o);
2976 if (PyModule_AddObject(m, "TclError", o)) {
2977 Py_DECREF(o);
2978 Py_DECREF(m);
2979 return NULL;
2980 }
2981 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002982
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002983 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2984 Py_DECREF(m);
2985 return NULL;
2986 }
2987 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2988 Py_DECREF(m);
2989 return NULL;
2990 }
2991 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2992 Py_DECREF(m);
2993 return NULL;
2994 }
2995 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2996 Py_DECREF(m);
2997 return NULL;
2998 }
2999 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3000 Py_DECREF(m);
3001 return NULL;
3002 }
3003 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3004 Py_DECREF(m);
3005 return NULL;
3006 }
3007 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3008 Py_DECREF(m);
3009 return NULL;
3010 }
3011 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3012 Py_DECREF(m);
3013 return NULL;
3014 }
3015 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3016 Py_DECREF(m);
3017 return NULL;
3018 }
3019 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3020 Py_DECREF(m);
3021 return NULL;
3022 }
3023 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3024 Py_DECREF(m);
3025 return NULL;
3026 }
3027
3028 o = PyType_FromSpec(&Tkapp_Type_spec);
3029 if (o == NULL) {
3030 Py_DECREF(m);
3031 return NULL;
3032 }
3033 if (PyModule_AddObject(m, "TkappType", o)) {
3034 Py_DECREF(o);
3035 Py_DECREF(m);
3036 return NULL;
3037 }
3038 Tkapp_Type = o;
3039
3040 o = PyType_FromSpec(&Tktt_Type_spec);
3041 if (o == NULL) {
3042 Py_DECREF(m);
3043 return NULL;
3044 }
3045 if (PyModule_AddObject(m, "TkttType", o)) {
3046 Py_DECREF(o);
3047 Py_DECREF(m);
3048 return NULL;
3049 }
3050 Tktt_Type = o;
3051
3052 o = PyType_FromSpec(&PyTclObject_Type_spec);
3053 if (o == NULL) {
3054 Py_DECREF(m);
3055 return NULL;
3056 }
3057 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3058 Py_DECREF(o);
3059 Py_DECREF(m);
3060 return NULL;
3061 }
3062 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003063
3064#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3066 * start waking up. Note that Tcl_FindExecutable will do this, this
3067 * code must be above it! The original warning from
3068 * tkMacOSXAppInit.c is copied below.
3069 *
3070 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3071 * Tcl interpreter for now. It probably should work to do this
3072 * in the other order, but for now it doesn't seem to.
3073 *
3074 */
3075 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003076#endif
3077
3078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003079 /* This helps the dynamic loader; in Unicode aware Tcl versions
3080 it also helps Tcl find its encodings. */
3081 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3082 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003083 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003084 if (cexe)
3085 Tcl_FindExecutable(PyBytes_AsString(cexe));
3086 Py_XDECREF(cexe);
3087 Py_DECREF(uexe);
3088 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003090 if (PyErr_Occurred()) {
3091 Py_DECREF(m);
3092 return NULL;
3093 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003094
Guido van Rossum43ff8681998-07-14 18:02:13 +00003095#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003096 /* This was not a good idea; through <Destroy> bindings,
3097 Tcl_Finalize() may invoke Python code but at that point the
3098 interpreter and thread state have already been destroyed! */
3099 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003100#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003102}