blob: 92dd94c4bef1e69d5b52e4e4f77fdc6bf4a82aeb [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 *
Fred Drake509d79a2000-07-08 04:04:38 +0000332Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000333{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 int argc;
335 char **argv;
336 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300339 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 }
Guido van Rossum18468821994-06-20 07:49:28 +0000341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
343 /* Not a list.
344 * Could be a quoted string containing funnies, e.g. {"}.
345 * Return the string itself.
346 */
347 return PyUnicode_FromString(list);
348 }
Guido van Rossum18468821994-06-20 07:49:28 +0000349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350 if (argc == 0)
351 v = PyUnicode_FromString("");
352 else if (argc == 1)
353 v = PyUnicode_FromString(argv[0]);
354 else if ((v = PyTuple_New(argc)) != NULL) {
355 int i;
356 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 for (i = 0; i < argc; i++) {
359 if ((w = Split(argv[i])) == NULL) {
360 Py_DECREF(v);
361 v = NULL;
362 break;
363 }
364 PyTuple_SetItem(v, i, w);
365 }
366 }
367 Tcl_Free(FREECAST argv);
368 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000369}
370
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300371/* In some cases, Tcl will still return strings that are supposed to
372 be lists. SplitObj walks through a nested tuple, finding string
373 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000374
Martin v. Löwis59683e82008-06-13 07:50:45 +0000375static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000376SplitObj(PyObject *arg)
377{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 if (PyTuple_Check(arg)) {
379 int i, size;
380 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 size = PyTuple_Size(arg);
383 result = NULL;
384 /* Recursively invoke SplitObj for all tuple items.
385 If this does not return a new object, no action is
386 needed. */
387 for(i = 0; i < size; i++) {
388 elem = PyTuple_GetItem(arg, i);
389 newelem = SplitObj(elem);
390 if (!newelem) {
391 Py_XDECREF(result);
392 return NULL;
393 }
394 if (!result) {
395 int k;
396 if (newelem == elem) {
397 Py_DECREF(newelem);
398 continue;
399 }
400 result = PyTuple_New(size);
401 if (!result)
402 return NULL;
403 for(k = 0; k < i; k++) {
404 elem = PyTuple_GetItem(arg, k);
405 Py_INCREF(elem);
406 PyTuple_SetItem(result, k, elem);
407 }
408 }
409 PyTuple_SetItem(result, i, newelem);
410 }
411 if (result)
412 return result;
413 /* Fall through, returning arg. */
414 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300415 else if (PyUnicode_Check(arg)) {
416 int argc;
417 char **argv;
418 char *list = PyUnicode_AsUTF8(arg);
419
420 if (list == NULL ||
421 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
422 Py_INCREF(arg);
423 return arg;
424 }
425 Tcl_Free(FREECAST argv);
426 if (argc > 1)
427 return Split(list);
428 /* Fall through, returning arg. */
429 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 else if (PyBytes_Check(arg)) {
431 int argc;
432 char **argv;
433 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000435 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
436 Py_INCREF(arg);
437 return arg;
438 }
439 Tcl_Free(FREECAST argv);
440 if (argc > 1)
441 return Split(PyBytes_AsString(arg));
442 /* Fall through, returning arg. */
443 }
444 Py_INCREF(arg);
445 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000446}
Barry Warsawfa701a81997-01-16 00:15:11 +0000447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448
Guido van Rossum18468821994-06-20 07:49:28 +0000449/**** Tkapp Object ****/
450
451#ifndef WITH_APPINIT
452int
Fred Drake509d79a2000-07-08 04:04:38 +0000453Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000454{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 if (Tcl_Init(interp) == TCL_ERROR) {
458 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
459 return TCL_ERROR;
460 }
Guilherme Polob681df42009-02-09 22:33:59 +0000461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 _tkinter_skip_tk_init = Tcl_GetVar(interp,
463 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
464 if (_tkinter_skip_tk_init != NULL &&
465 strcmp(_tkinter_skip_tk_init, "1") == 0) {
466 return TCL_OK;
467 }
Guilherme Polob681df42009-02-09 22:33:59 +0000468
469#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 if (tk_load_failed) {
471 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
472 return TCL_ERROR;
473 }
Guilherme Polob681df42009-02-09 22:33:59 +0000474#endif
475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000476 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000477#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000479#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000480 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
481 return TCL_ERROR;
482 }
Guilherme Polob681df42009-02-09 22:33:59 +0000483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486#endif /* !WITH_APPINIT */
487
Guido van Rossum18468821994-06-20 07:49:28 +0000488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000489
Barry Warsawfa701a81997-01-16 00:15:11 +0000490
491/* Initialize the Tk application; see the `main' function in
492 * `tkMain.c'.
493 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000494
Thomas Wouters58d05102000-07-24 14:43:35 +0000495static void EnableEventHook(void); /* Forward */
496static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000497
Barry Warsawfa701a81997-01-16 00:15:11 +0000498static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000499Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000500 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000501{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 TkappObject *v;
503 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000504
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300505 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 if (v == NULL)
507 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200508 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 v->interp = Tcl_CreateInterp();
511 v->wantobjects = wantobjects;
512 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
513 TCL_GLOBAL_ONLY) != NULL;
514 v->thread_id = Tcl_GetCurrentThread();
515 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000516
517#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300519 PyErr_SetString(PyExc_RuntimeError,
520 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 Py_DECREF(v);
522 return 0;
523 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000524#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000525#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 if (v->threaded && tcl_lock) {
527 /* If Tcl is threaded, we don't need the lock. */
528 PyThread_free_lock(tcl_lock);
529 tcl_lock = NULL;
530 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000531#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 v->BooleanType = Tcl_GetObjType("boolean");
534 v->ByteArrayType = Tcl_GetObjType("bytearray");
535 v->DoubleType = Tcl_GetObjType("double");
536 v->IntType = Tcl_GetObjType("int");
537 v->ListType = Tcl_GetObjType("list");
538 v->ProcBodyType = Tcl_GetObjType("procbody");
539 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000540
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000541 /* Delete the 'exit' command, which can screw things up */
542 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 if (screenName != NULL)
545 Tcl_SetVar2(v->interp, "env", "DISPLAY",
546 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 if (interactive)
549 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
550 else
551 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 /* This is used to get the application class for Tk 4.1 and up */
554 argv0 = (char*)ckalloc(strlen(className) + 1);
555 if (!argv0) {
556 PyErr_NoMemory();
557 Py_DECREF(v);
558 return NULL;
559 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200562 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
563 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
565 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 if (! wantTk) {
568 Tcl_SetVar(v->interp,
569 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
570 }
Guilherme Polob681df42009-02-09 22:33:59 +0000571#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 else if (tk_load_failed) {
573 Tcl_SetVar(v->interp,
574 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
575 }
Guilherme Polob681df42009-02-09 22:33:59 +0000576#endif
David Aschere2b4b322004-02-18 05:59:53 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 /* some initial arguments need to be in argv */
579 if (sync || use) {
580 char *args;
581 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 if (sync)
584 len += sizeof "-sync";
585 if (use)
586 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 args = (char*)ckalloc(len);
589 if (!args) {
590 PyErr_NoMemory();
591 Py_DECREF(v);
592 return NULL;
593 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000594
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 args[0] = '\0';
596 if (sync)
597 strcat(args, "-sync");
598 if (use) {
599 if (sync)
600 strcat(args, " ");
601 strcat(args, "-use ");
602 strcat(args, use);
603 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
606 ckfree(args);
607 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 if (Tcl_AppInit(v->interp) != TCL_OK) {
610 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000611#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if (wantTk) {
613 const char *_tkinter_tk_failed;
614 _tkinter_tk_failed = Tcl_GetVar(v->interp,
615 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617 if ( _tkinter_tk_failed != NULL &&
618 strcmp(_tkinter_tk_failed, "1") == 0) {
619 tk_load_failed = 1;
620 }
621 }
Guilherme Polob681df42009-02-09 22:33:59 +0000622#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 Py_DECREF((PyObject *)v);
624 return (TkappObject *)result;
625 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000627 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000629 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000630}
631
Barry Warsawfa701a81997-01-16 00:15:11 +0000632
Benjamin Peterson5879d412009-03-30 14:51:56 +0000633#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000634static void
635Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 Py_BEGIN_ALLOW_THREADS;
639 Tcl_MutexLock(mutex);
640 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
641 Tcl_ThreadAlert(self->thread_id);
642 Tcl_ConditionWait(cond, mutex, NULL);
643 Tcl_MutexUnlock(mutex);
644 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000645}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000646#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648
Guido van Rossum18468821994-06-20 07:49:28 +0000649/** Tcl Eval **/
650
Martin v. Löwisffad6332002-11-26 09:28:05 +0000651typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 PyObject_HEAD
653 Tcl_Obj *value;
654 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000655} PyTclObject;
656
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300657static PyObject *PyTclObject_Type;
658#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000659
660static PyObject *
661newPyTclObject(Tcl_Obj *arg)
662{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300664 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000665 if (self == NULL)
666 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200667 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 Tcl_IncrRefCount(arg);
669 self->value = arg;
670 self->string = NULL;
671 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000672}
673
674static void
675PyTclObject_dealloc(PyTclObject *self)
676{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200677 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 Tcl_DecrRefCount(self->value);
679 Py_XDECREF(self->string);
680 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200681 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000682}
683
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000684static char*
685PyTclObject_TclString(PyObject *self)
686{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000688}
689
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000690/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000691PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000692"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000693
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000694static PyObject *
695PyTclObject_string(PyTclObject *self, void *ignored)
696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 char *s;
698 int len;
699 if (!self->string) {
700 s = Tcl_GetStringFromObj(self->value, &len);
701 self->string = PyUnicode_FromStringAndSize(s, len);
702 if (!self->string)
703 return NULL;
704 }
705 Py_INCREF(self->string);
706 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000707}
708
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000709static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000710PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 char *s;
713 int len;
714 if (self->string && PyUnicode_Check(self->string)) {
715 Py_INCREF(self->string);
716 return self->string;
717 }
718 /* XXX Could chache result if it is non-ASCII. */
719 s = Tcl_GetStringFromObj(self->value, &len);
720 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000721}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000722
Martin v. Löwisffad6332002-11-26 09:28:05 +0000723static PyObject *
724PyTclObject_repr(PyTclObject *self)
725{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300726 PyObject *repr, *str = PyTclObject_str(self, NULL);
727 if (str == NULL)
728 return NULL;
729 repr = PyUnicode_FromFormat("<%s object: %R>",
730 self->value->typePtr->name, str);
731 Py_DECREF(str);
732 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000733}
734
Mark Dickinson211c6252009-02-01 10:28:51 +0000735#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
736
737static PyObject *
738PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 int result;
741 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 /* neither argument should be NULL, unless something's gone wrong */
744 if (self == NULL || other == NULL) {
745 PyErr_BadInternalCall();
746 return NULL;
747 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 /* both arguments should be instances of PyTclObject */
750 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
751 v = Py_NotImplemented;
752 goto finished;
753 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 if (self == other)
756 /* fast path when self and other are identical */
757 result = 0;
758 else
759 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
760 Tcl_GetString(((PyTclObject *)other)->value));
761 /* Convert return value to a Boolean */
762 switch (op) {
763 case Py_EQ:
764 v = TEST_COND(result == 0);
765 break;
766 case Py_NE:
767 v = TEST_COND(result != 0);
768 break;
769 case Py_LE:
770 v = TEST_COND(result <= 0);
771 break;
772 case Py_GE:
773 v = TEST_COND(result >= 0);
774 break;
775 case Py_LT:
776 v = TEST_COND(result < 0);
777 break;
778 case Py_GT:
779 v = TEST_COND(result > 0);
780 break;
781 default:
782 PyErr_BadArgument();
783 return NULL;
784 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000785 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 Py_INCREF(v);
787 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000788}
789
Martin v. Löwis39195712003-01-04 00:33:13 +0000790PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
791
Martin v. Löwisffad6332002-11-26 09:28:05 +0000792static PyObject*
793get_typename(PyTclObject* obj, void* ignored)
794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000795 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000796}
797
Martin v. Löwis39195712003-01-04 00:33:13 +0000798
Martin v. Löwisffad6332002-11-26 09:28:05 +0000799static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 {"typename", (getter)get_typename, NULL, get_typename__doc__},
801 {"string", (getter)PyTclObject_string, NULL,
802 PyTclObject_string__doc__},
803 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000804};
805
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300806static PyType_Slot PyTclObject_Type_slots[] = {
807 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
808 {Py_tp_repr, (reprfunc)PyTclObject_repr},
809 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200810 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300811 {Py_tp_richcompare, PyTclObject_richcompare},
812 {Py_tp_getset, PyTclObject_getsetlist},
813 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814};
815
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300816static PyType_Spec PyTclObject_Type_spec = {
817 "_tkinter.Tcl_Obj",
818 sizeof(PyTclObject),
819 0,
820 Py_TPFLAGS_DEFAULT,
821 PyTclObject_Type_slots,
822};
823
824
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000825static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000826AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 Tcl_Obj *result;
829 long longVal;
830 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000832 if (PyBytes_Check(value))
833 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
834 PyBytes_GET_SIZE(value));
835 else if (PyBool_Check(value))
836 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
837 else if (PyLong_CheckExact(value) &&
838 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
839 !overflow)) {
840 /* If there is an overflow in the long conversion,
841 fall through to default object handling. */
842 return Tcl_NewLongObj(longVal);
843 }
844 else if (PyFloat_Check(value))
845 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
846 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300847 Tcl_Obj **argv;
848 Py_ssize_t size, i;
849
850 size = PyTuple_Size(value);
851 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
852 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
853 return NULL;
854 }
855 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000856 if(!argv)
857 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300858 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000859 argv[i] = AsObj(PyTuple_GetItem(value,i));
860 result = Tcl_NewListObj(PyTuple_Size(value), argv);
861 ckfree(FREECAST argv);
862 return result;
863 }
864 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200865 void *inbuf;
866 Py_ssize_t size;
867 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 Tcl_UniChar *outbuf = NULL;
869 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200870 size_t allocsize;
871
872 if (PyUnicode_READY(value) == -1)
873 return NULL;
874
875 inbuf = PyUnicode_DATA(value);
876 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300877 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
878 PyErr_SetString(PyExc_OverflowError, "string is too long");
879 return NULL;
880 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200881 kind = PyUnicode_KIND(value);
882 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
883 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000884 /* Else overflow occurred, and we take the next exit */
885 if (!outbuf) {
886 PyErr_NoMemory();
887 return NULL;
888 }
889 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200890 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
891 /* We cannot test for sizeof(Tcl_UniChar) directly,
892 so we test for UTF-8 size instead. */
893#if TCL_UTF_MAX == 3
894 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +0200896 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +0100897 "character U+%x is above the range "
898 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100899 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 ckfree(FREECAST outbuf);
901 return NULL;
902 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300903#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200904 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 }
906 result = Tcl_NewUnicodeObj(outbuf, size);
907 ckfree(FREECAST outbuf);
908 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000909 }
910 else if(PyTclObject_Check(value)) {
911 Tcl_Obj *v = ((PyTclObject*)value)->value;
912 Tcl_IncrRefCount(v);
913 return v;
914 }
915 else {
916 PyObject *v = PyObject_Str(value);
917 if (!v)
918 return 0;
919 result = AsObj(v);
920 Py_DECREF(v);
921 return result;
922 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000923}
924
Martin v. Löwisffad6332002-11-26 09:28:05 +0000925static PyObject*
926FromObj(PyObject* tkapp, Tcl_Obj *value)
927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000928 PyObject *result = NULL;
929 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931 if (value->typePtr == NULL) {
932 return PyUnicode_FromStringAndSize(value->bytes,
933 value->length);
934 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 if (value->typePtr == app->BooleanType) {
937 result = value->internalRep.longValue ? Py_True : Py_False;
938 Py_INCREF(result);
939 return result;
940 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 if (value->typePtr == app->ByteArrayType) {
943 int size;
944 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
945 return PyBytes_FromStringAndSize(data, size);
946 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 if (value->typePtr == app->DoubleType) {
949 return PyFloat_FromDouble(value->internalRep.doubleValue);
950 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 if (value->typePtr == app->IntType) {
953 return PyLong_FromLong(value->internalRep.longValue);
954 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000956 if (value->typePtr == app->ListType) {
957 int size;
958 int i, status;
959 PyObject *elem;
960 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
963 if (status == TCL_ERROR)
964 return Tkinter_Error(tkapp);
965 result = PyTuple_New(size);
966 if (!result)
967 return NULL;
968 for (i = 0; i < size; i++) {
969 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
970 value, i, &tcl_elem);
971 if (status == TCL_ERROR) {
972 Py_DECREF(result);
973 return Tkinter_Error(tkapp);
974 }
975 elem = FromObj(tkapp, tcl_elem);
976 if (!elem) {
977 Py_DECREF(result);
978 return NULL;
979 }
980 PyTuple_SetItem(result, i, elem);
981 }
982 return result;
983 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 if (value->typePtr == app->ProcBodyType) {
986 /* fall through: return tcl object. */
987 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200990#if TCL_UTF_MAX==3
991 return PyUnicode_FromKindAndData(
992 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
993 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000994#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200995 return PyUnicode_FromKindAndData(
996 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
997 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000998#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001000
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001002}
1003
Benjamin Peterson5879d412009-03-30 14:51:56 +00001004#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001005/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001006TCL_DECLARE_MUTEX(call_mutex)
1007
1008typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 Tcl_Event ev; /* Must be first */
1010 TkappObject *self;
1011 PyObject *args;
1012 int flags;
1013 PyObject **res;
1014 PyObject **exc_type, **exc_value, **exc_tb;
1015 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001016} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001017#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001018
1019void
1020Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001021{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001022 int i;
1023 for (i = 0; i < objc; i++)
1024 Tcl_DecrRefCount(objv[i]);
1025 if (objv != objStore)
1026 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001027}
Guido van Rossum18468821994-06-20 07:49:28 +00001028
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001029/* Convert Python objects to Tcl objects. This must happen in the
1030 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001031
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001032static Tcl_Obj**
1033Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001036 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (args == NULL)
1038 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001040 else if (!PyTuple_Check(args)) {
1041 objv[0] = AsObj(args);
1042 if (objv[0] == 0)
1043 goto finally;
1044 objc = 1;
1045 Tcl_IncrRefCount(objv[0]);
1046 }
1047 else {
1048 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001049
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001050 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001051 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1052 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1053 return NULL;
1054 }
1055 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 if (objv == NULL) {
1057 PyErr_NoMemory();
1058 objc = 0;
1059 goto finally;
1060 }
1061 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 for (i = 0; i < objc; i++) {
1064 PyObject *v = PyTuple_GetItem(args, i);
1065 if (v == Py_None) {
1066 objc = i;
1067 break;
1068 }
1069 objv[i] = AsObj(v);
1070 if (!objv[i]) {
1071 /* Reset objc, so it attempts to clear
1072 objects only up to i. */
1073 objc = i;
1074 goto finally;
1075 }
1076 Tcl_IncrRefCount(objv[i]);
1077 }
1078 }
1079 *pobjc = objc;
1080 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001081finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 Tkapp_CallDeallocArgs(objv, objStore, objc);
1083 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001084}
Guido van Rossum212643f1998-04-29 16:22:14 +00001085
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001086/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001087
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001088static PyObject*
1089Tkapp_CallResult(TkappObject *self)
1090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 PyObject *res = NULL;
1092 if(self->wantobjects) {
1093 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1094 /* Not sure whether the IncrRef is necessary, but something
1095 may overwrite the interpreter result while we are
1096 converting it. */
1097 Tcl_IncrRefCount(value);
1098 res = FromObj((PyObject*)self, value);
1099 Tcl_DecrRefCount(value);
1100 } else {
Serhiy Storchaka31f477c2013-09-20 23:21:44 +03001101 res = PyUnicode_FromString(Tcl_GetStringResult(self->interp));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 }
1103 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001104}
Guido van Rossum632de272000-03-29 00:19:50 +00001105
Benjamin Peterson5879d412009-03-30 14:51:56 +00001106#ifdef WITH_THREAD
1107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001108/* Tkapp_CallProc is the event procedure that is executed in the context of
1109 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1110 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001111
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001112static int
1113Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001115 Tcl_Obj *objStore[ARGSZ];
1116 Tcl_Obj **objv;
1117 int objc;
1118 int i;
1119 ENTER_PYTHON
1120 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1121 if (!objv) {
1122 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1123 *(e->res) = NULL;
1124 }
1125 LEAVE_PYTHON
1126 if (!objv)
1127 goto done;
1128 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1129 ENTER_PYTHON
1130 if (i == TCL_ERROR) {
1131 *(e->res) = NULL;
1132 *(e->exc_type) = NULL;
1133 *(e->exc_tb) = NULL;
1134 *(e->exc_value) = PyObject_CallFunction(
1135 Tkinter_TclError, "s",
1136 Tcl_GetStringResult(e->self->interp));
1137 }
1138 else {
1139 *(e->res) = Tkapp_CallResult(e->self);
1140 }
1141 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001144done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 /* Wake up calling thread. */
1146 Tcl_MutexLock(&call_mutex);
1147 Tcl_ConditionNotify(e->done);
1148 Tcl_MutexUnlock(&call_mutex);
1149 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001150}
1151
Benjamin Peterson5879d412009-03-30 14:51:56 +00001152#endif
1153
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154/* This is the main entry point for calling a Tcl command.
1155 It supports three cases, with regard to threading:
1156 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1157 the context of the calling thread.
1158 2. Tcl is threaded, caller of the command is in the interpreter thread:
1159 Execute the command in the calling thread. Since the Tcl lock will
1160 not be used, we can merge that with case 1.
1161 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1162 the interpreter thread. Allocation of Tcl objects needs to occur in the
1163 interpreter thread, so we ship the PyObject* args to the target thread,
1164 and perform processing there. */
1165
1166static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001167Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001168{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001169 Tcl_Obj *objStore[ARGSZ];
1170 Tcl_Obj **objv = NULL;
1171 int objc, i;
1172 PyObject *res = NULL;
1173 TkappObject *self = (TkappObject*)selfptr;
1174 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001176 /* If args is a single tuple, replace with contents of tuple */
1177 if (1 == PyTuple_Size(args)){
1178 PyObject* item = PyTuple_GetItem(args, 0);
1179 if (PyTuple_Check(item))
1180 args = item;
1181 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001182#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001183 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1184 /* We cannot call the command directly. Instead, we must
1185 marshal the parameters to the interpreter thread. */
1186 Tkapp_CallEvent *ev;
1187 Tcl_Condition cond = NULL;
1188 PyObject *exc_type, *exc_value, *exc_tb;
1189 if (!WaitForMainloop(self))
1190 return NULL;
1191 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1192 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1193 ev->self = self;
1194 ev->args = args;
1195 ev->res = &res;
1196 ev->exc_type = &exc_type;
1197 ev->exc_value = &exc_value;
1198 ev->exc_tb = &exc_tb;
1199 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001201 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 if (res == NULL) {
1204 if (exc_type)
1205 PyErr_Restore(exc_type, exc_value, exc_tb);
1206 else
1207 PyErr_SetObject(Tkinter_TclError, exc_value);
1208 }
1209 Tcl_ConditionFinalize(&cond);
1210 }
1211 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001212#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 objv = Tkapp_CallArgs(args, objStore, &objc);
1216 if (!objv)
1217 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001223 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 if (i == TCL_ERROR)
1226 Tkinter_Error(selfptr);
1227 else
1228 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001230 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001231
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001232 Tkapp_CallDeallocArgs(objv, objStore, objc);
1233 }
1234 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001235}
1236
1237
1238static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001239Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001240{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 char *script;
1242 PyObject *res = NULL;
1243 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001245 if (!PyArg_ParseTuple(args, "s:eval", &script))
1246 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001250 ENTER_TCL
1251 err = Tcl_Eval(Tkapp_Interp(self), script);
1252 ENTER_OVERLAP
1253 if (err == TCL_ERROR)
1254 res = Tkinter_Error(self);
1255 else
1256 res = PyUnicode_FromString(Tkapp_Result(self));
1257 LEAVE_OVERLAP_TCL
1258 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001259}
1260
1261static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001262Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001264 char *fileName;
1265 PyObject *res = NULL;
1266 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1269 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 ENTER_TCL
1274 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1275 ENTER_OVERLAP
1276 if (err == TCL_ERROR)
1277 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 else
1280 res = PyUnicode_FromString(Tkapp_Result(self));
1281 LEAVE_OVERLAP_TCL
1282 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001283}
1284
1285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001286Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 char *script;
1289 PyObject *res = NULL;
1290 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001292 if (!PyArg_ParseTuple(args, "s", &script))
1293 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 ENTER_TCL
1298 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1299 ENTER_OVERLAP
1300 if (err == TCL_ERROR)
1301 res = Tkinter_Error(self);
1302 else
1303 res = PyUnicode_FromString(Tkapp_Result(self));
1304 LEAVE_OVERLAP_TCL
1305 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001306}
1307
1308static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001309Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001310{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1314 return NULL;
1315 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 ENTER_TCL
1318 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1319 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001320
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001321 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001322}
1323
Barry Warsawfa701a81997-01-16 00:15:11 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325
Guido van Rossum18468821994-06-20 07:49:28 +00001326/** Tcl Variable **/
1327
Benjamin Peterson5879d412009-03-30 14:51:56 +00001328typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1329
1330#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331TCL_DECLARE_MUTEX(var_mutex)
1332
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001333typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 Tcl_Event ev; /* must be first */
1335 PyObject *self;
1336 PyObject *args;
1337 int flags;
1338 EventFunc func;
1339 PyObject **res;
1340 PyObject **exc_type;
1341 PyObject **exc_val;
1342 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001344#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001345
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001346static int
1347varname_converter(PyObject *in, void *_out)
1348{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 char **out = (char**)_out;
1350 if (PyBytes_Check(in)) {
1351 *out = PyBytes_AsString(in);
1352 return 1;
1353 }
1354 if (PyUnicode_Check(in)) {
1355 *out = _PyUnicode_AsString(in);
1356 return 1;
1357 }
1358 if (PyTclObject_Check(in)) {
1359 *out = PyTclObject_TclString(in);
1360 return 1;
1361 }
1362 /* XXX: Should give diagnostics. */
1363 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001364}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001365
Benjamin Peterson5879d412009-03-30 14:51:56 +00001366#ifdef WITH_THREAD
1367
Martin v. Löwis59683e82008-06-13 07:50:45 +00001368static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369var_perform(VarEvent *ev)
1370{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1372 if (!*(ev->res)) {
1373 PyObject *exc, *val, *tb;
1374 PyErr_Fetch(&exc, &val, &tb);
1375 PyErr_NormalizeException(&exc, &val, &tb);
1376 *(ev->exc_type) = exc;
1377 *(ev->exc_val) = val;
1378 Py_DECREF(tb);
1379 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001380
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001381}
1382
1383static int
1384var_proc(VarEvent* ev, int flags)
1385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 ENTER_PYTHON
1387 var_perform(ev);
1388 Tcl_MutexLock(&var_mutex);
1389 Tcl_ConditionNotify(ev->cond);
1390 Tcl_MutexUnlock(&var_mutex);
1391 LEAVE_PYTHON
1392 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393}
1394
Benjamin Peterson5879d412009-03-30 14:51:56 +00001395#endif
1396
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001398var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001399{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001400#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001401 TkappObject *self = (TkappObject*)selfptr;
1402 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1403 TkappObject *self = (TkappObject*)selfptr;
1404 VarEvent *ev;
1405 PyObject *res, *exc_type, *exc_val;
1406 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001408 /* The current thread is not the interpreter thread. Marshal
1409 the call to the interpreter thread, then wait for
1410 completion. */
1411 if (!WaitForMainloop(self))
1412 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 ev->self = selfptr;
1417 ev->args = args;
1418 ev->flags = flags;
1419 ev->func = func;
1420 ev->res = &res;
1421 ev->exc_type = &exc_type;
1422 ev->exc_val = &exc_val;
1423 ev->cond = &cond;
1424 ev->ev.proc = (Tcl_EventProc*)var_proc;
1425 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1426 Tcl_ConditionFinalize(&cond);
1427 if (!res) {
1428 PyErr_SetObject(exc_type, exc_val);
1429 Py_DECREF(exc_type);
1430 Py_DECREF(exc_val);
1431 return NULL;
1432 }
1433 return res;
1434 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001435#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001436 /* Tcl is not threaded, or this is the interpreter thread. */
1437 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438}
1439
Guido van Rossum18468821994-06-20 07:49:28 +00001440static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001441SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 char *name1, *name2;
1444 PyObject *newValue;
1445 PyObject *res = NULL;
1446 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 if (PyArg_ParseTuple(args, "O&O:setvar",
1449 varname_converter, &name1, &newValue)) {
1450 /* XXX Acquire tcl lock??? */
1451 newval = AsObj(newValue);
1452 if (newval == NULL)
1453 return NULL;
1454 ENTER_TCL
1455 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1456 newval, flags);
1457 ENTER_OVERLAP
1458 if (!ok)
1459 Tkinter_Error(self);
1460 else {
1461 res = Py_None;
1462 Py_INCREF(res);
1463 }
1464 LEAVE_OVERLAP_TCL
1465 }
1466 else {
1467 PyErr_Clear();
1468 if (PyArg_ParseTuple(args, "ssO:setvar",
1469 &name1, &name2, &newValue)) {
1470 /* XXX must hold tcl lock already??? */
1471 newval = AsObj(newValue);
1472 ENTER_TCL
1473 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1474 ENTER_OVERLAP
1475 if (!ok)
1476 Tkinter_Error(self);
1477 else {
1478 res = Py_None;
1479 Py_INCREF(res);
1480 }
1481 LEAVE_OVERLAP_TCL
1482 }
1483 else {
1484 return NULL;
1485 }
1486 }
1487 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001488}
1489
1490static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001491Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001492{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001493 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001494}
1495
1496static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001497Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001498{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
Barry Warsawfa701a81997-01-16 00:15:11 +00001502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001503
Guido van Rossum18468821994-06-20 07:49:28 +00001504static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001505GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001506{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 char *name1, *name2=NULL;
1508 PyObject *res = NULL;
1509 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1512 varname_converter, &name1, &name2))
1513 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001515 ENTER_TCL
1516 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1517 ENTER_OVERLAP
1518 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001519 PyErr_SetString(Tkinter_TclError,
1520 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 } else {
1522 if (((TkappObject*)self)->wantobjects) {
1523 res = FromObj(self, tres);
1524 }
1525 else {
1526 res = PyUnicode_FromString(Tcl_GetString(tres));
1527 }
1528 }
1529 LEAVE_OVERLAP_TCL
1530 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001531}
1532
1533static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001534Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001535{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001537}
1538
1539static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001540Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001543}
1544
Barry Warsawfa701a81997-01-16 00:15:11 +00001545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546
Guido van Rossum18468821994-06-20 07:49:28 +00001547static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001548UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 char *name1, *name2=NULL;
1551 int code;
1552 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1555 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 ENTER_TCL
1558 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1559 ENTER_OVERLAP
1560 if (code == TCL_ERROR)
1561 res = Tkinter_Error(self);
1562 else {
1563 Py_INCREF(Py_None);
1564 res = Py_None;
1565 }
1566 LEAVE_OVERLAP_TCL
1567 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001568}
1569
1570static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001571Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001572{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001574}
1575
1576static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001577Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001578{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001579 return var_invoke(UnsetVar, self, args,
1580 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001581}
1582
Barry Warsawfa701a81997-01-16 00:15:11 +00001583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001584
Guido van Rossum18468821994-06-20 07:49:28 +00001585/** Tcl to Python **/
1586
1587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001588Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001589{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001590 char *s;
1591 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001593 if (PyTuple_Size(args) == 1) {
1594 PyObject* o = PyTuple_GetItem(args, 0);
1595 if (PyLong_Check(o)) {
1596 Py_INCREF(o);
1597 return o;
1598 }
1599 }
1600 if (!PyArg_ParseTuple(args, "s:getint", &s))
1601 return NULL;
1602 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1603 return Tkinter_Error(self);
1604 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001605}
1606
1607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001608Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001609{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 char *s;
1611 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001613 if (PyTuple_Size(args) == 1) {
1614 PyObject *o = PyTuple_GetItem(args, 0);
1615 if (PyFloat_Check(o)) {
1616 Py_INCREF(o);
1617 return o;
1618 }
1619 }
1620 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1621 return NULL;
1622 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1623 return Tkinter_Error(self);
1624 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001625}
1626
1627static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001628Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001629{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 char *s;
1631 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001633 if (PyTuple_Size(args) == 1) {
1634 PyObject *o = PyTuple_GetItem(args, 0);
1635 if (PyLong_Check(o)) {
1636 Py_INCREF(o);
1637 return o;
1638 }
1639 }
1640 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1641 return NULL;
1642 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1643 return Tkinter_Error(self);
1644 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
1647static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001648Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001649{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001650 char *s;
1651 PyObject *res = NULL;
1652 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001654 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1655 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001656
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001657 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001659 ENTER_TCL
1660 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1661 ENTER_OVERLAP
1662 if (retval == TCL_ERROR)
1663 res = Tkinter_Error(self);
1664 else
1665 res = Py_BuildValue("s", Tkapp_Result(self));
1666 LEAVE_OVERLAP_TCL
1667 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001668}
1669
1670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001672{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001673 char *s;
1674 PyObject *res = NULL;
1675 int retval;
1676 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1679 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001681 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001682
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 ENTER_TCL
1684 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1685 ENTER_OVERLAP
1686 if (retval == TCL_ERROR)
1687 res = Tkinter_Error(self);
1688 else
1689 res = Py_BuildValue("l", v);
1690 LEAVE_OVERLAP_TCL
1691 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001692}
1693
1694static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001695Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 char *s;
1698 PyObject *res = NULL;
1699 double v;
1700 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1703 return NULL;
1704 CHECK_TCL_APPARTMENT;
1705 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1706 ENTER_TCL
1707 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1708 ENTER_OVERLAP
1709 PyFPE_END_PROTECT(retval)
1710 if (retval == TCL_ERROR)
1711 res = Tkinter_Error(self);
1712 else
1713 res = Py_BuildValue("d", v);
1714 LEAVE_OVERLAP_TCL
1715 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001716}
1717
1718static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001719Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 char *s;
1722 PyObject *res = NULL;
1723 int retval;
1724 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001726 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1727 return NULL;
1728 CHECK_TCL_APPARTMENT;
1729 ENTER_TCL
1730 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1731 ENTER_OVERLAP
1732 if (retval == TCL_ERROR)
1733 res = Tkinter_Error(self);
1734 else
1735 res = Py_BuildValue("i", v);
1736 LEAVE_OVERLAP_TCL
1737 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
Barry Warsawfa701a81997-01-16 00:15:11 +00001740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741
Guido van Rossum18468821994-06-20 07:49:28 +00001742static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001743Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 char *list;
1746 int argc;
1747 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001748 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001750
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001751 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1752 return NULL;
1753 if (PyTclObject_Check(arg)) {
1754 int objc;
1755 Tcl_Obj **objv;
1756 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1757 ((PyTclObject*)arg)->value,
1758 &objc, &objv) == TCL_ERROR) {
1759 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001761 if (!(v = PyTuple_New(objc)))
1762 return NULL;
1763 for (i = 0; i < objc; i++) {
1764 PyObject *s = FromObj(self, objv[i]);
1765 if (!s || PyTuple_SetItem(v, i, s)) {
1766 Py_DECREF(v);
1767 return NULL;
1768 }
1769 }
1770 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001771 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001772 if (PyTuple_Check(arg)) {
1773 Py_INCREF(arg);
1774 return arg;
1775 }
1776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1778 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001780 if (Tcl_SplitList(Tkapp_Interp(self), list,
1781 &argc, &argv) == TCL_ERROR) {
1782 PyMem_Free(list);
1783 return Tkinter_Error(self);
1784 }
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001786 if (!(v = PyTuple_New(argc)))
1787 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001788
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001789 for (i = 0; i < argc; i++) {
1790 PyObject *s = PyUnicode_FromString(argv[i]);
1791 if (!s || PyTuple_SetItem(v, i, s)) {
1792 Py_DECREF(v);
1793 v = NULL;
1794 goto finally;
1795 }
1796 }
Guido van Rossum18468821994-06-20 07:49:28 +00001797
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 ckfree(FREECAST argv);
1800 PyMem_Free(list);
1801 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001802}
1803
1804static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001805Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001806{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001807 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001808 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001810 if (!PyArg_ParseTuple(args, "O:split", &arg))
1811 return NULL;
1812 if (PyTclObject_Check(arg)) {
1813 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1814 int objc;
1815 Tcl_Obj **objv;
1816 int i;
1817 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1818 &objc, &objv) == TCL_ERROR) {
1819 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001821 if (objc == 0)
1822 return PyUnicode_FromString("");
1823 if (objc == 1)
1824 return FromObj(self, objv[0]);
1825 if (!(v = PyTuple_New(objc)))
1826 return NULL;
1827 for (i = 0; i < objc; i++) {
1828 PyObject *s = FromObj(self, objv[i]);
1829 if (!s || PyTuple_SetItem(v, i, s)) {
1830 Py_DECREF(v);
1831 return NULL;
1832 }
1833 }
1834 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001835 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001836 if (PyTuple_Check(arg))
1837 return SplitObj(arg);
1838
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001839 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1840 return NULL;
1841 v = Split(list);
1842 PyMem_Free(list);
1843 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001844}
1845
Barry Warsawfa701a81997-01-16 00:15:11 +00001846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847
Guido van Rossum18468821994-06-20 07:49:28 +00001848/** Tcl Command **/
1849
Guido van Rossum00d93061998-05-28 23:06:38 +00001850/* Client data struct */
1851typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 PyObject *self;
1853 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001854} PythonCmd_ClientData;
1855
1856static int
Fred Drake509d79a2000-07-08 04:04:38 +00001857PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001858{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001859 errorInCmd = 1;
1860 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1861 LEAVE_PYTHON
1862 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001863}
1864
Guido van Rossum18468821994-06-20 07:49:28 +00001865/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001866 * function or method.
1867 */
Guido van Rossum18468821994-06-20 07:49:28 +00001868static int
Fred Drake509d79a2000-07-08 04:04:38 +00001869PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001872 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001873 int i, rv;
1874 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 /* TBD: no error checking here since we know, via the
1879 * Tkapp_CreateCommand() that the client data is a two-tuple
1880 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001881 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001883 /* Create argument list (argv1, ..., argvN) */
1884 if (!(arg = PyTuple_New(argc - 1)))
1885 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 for (i = 0; i < (argc - 1); i++) {
1888 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001889 if (!s) {
1890 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1891 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1892 !strcmp(argv[i + 1], "\xC0\x80")) {
1893 PyErr_Clear();
1894 /* Convert to "strict" utf-8 null */
1895 s = PyUnicode_FromString("\0");
1896 } else {
1897 Py_DECREF(arg);
1898 return PythonCmd_Error(interp);
1899 }
1900 }
1901 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001902 Py_DECREF(arg);
1903 return PythonCmd_Error(interp);
1904 }
1905 }
1906 res = PyEval_CallObject(func, arg);
1907 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001909 if (res == NULL)
1910 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001912 obj_res = AsObj(res);
1913 if (obj_res == NULL) {
1914 Py_DECREF(res);
1915 return PythonCmd_Error(interp);
1916 }
1917 else {
1918 Tcl_SetObjResult(interp, obj_res);
1919 rv = TCL_OK;
1920 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001927}
1928
1929static void
Fred Drake509d79a2000-07-08 04:04:38 +00001930PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001931{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001933
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001934 ENTER_PYTHON
1935 Py_XDECREF(data->self);
1936 Py_XDECREF(data->func);
1937 PyMem_DEL(data);
1938 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001939}
1940
Barry Warsawfa701a81997-01-16 00:15:11 +00001941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001942
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001943
Benjamin Peterson5879d412009-03-30 14:51:56 +00001944#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001945TCL_DECLARE_MUTEX(command_mutex)
1946
1947typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001948 Tcl_Event ev;
1949 Tcl_Interp* interp;
1950 char *name;
1951 int create;
1952 int *status;
1953 ClientData *data;
1954 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001955} CommandEvent;
1956
1957static int
1958Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001959{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 if (ev->create)
1961 *ev->status = Tcl_CreateCommand(
1962 ev->interp, ev->name, PythonCmd,
1963 ev->data, PythonCmdDelete) == NULL;
1964 else
1965 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1966 Tcl_MutexLock(&command_mutex);
1967 Tcl_ConditionNotify(ev->done);
1968 Tcl_MutexUnlock(&command_mutex);
1969 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001970}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001971#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001972
1973static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001974Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001975{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 TkappObject *self = (TkappObject*)selfptr;
1977 PythonCmd_ClientData *data;
1978 char *cmdName;
1979 PyObject *func;
1980 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001982 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1983 return NULL;
1984 if (!PyCallable_Check(func)) {
1985 PyErr_SetString(PyExc_TypeError, "command not callable");
1986 return NULL;
1987 }
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Martin v. Löwisa9656492003-03-30 08:44:58 +00001989#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1991 !WaitForMainloop(self))
1992 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001993#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 data = PyMem_NEW(PythonCmd_ClientData, 1);
1996 if (!data)
1997 return PyErr_NoMemory();
1998 Py_INCREF(self);
1999 Py_INCREF(func);
2000 data->self = selfptr;
2001 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002002#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002003 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2004 Tcl_Condition cond = NULL;
2005 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2006 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2007 ev->interp = self->interp;
2008 ev->create = 1;
2009 ev->name = cmdName;
2010 ev->data = (ClientData)data;
2011 ev->status = &err;
2012 ev->done = &cond;
2013 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2014 Tcl_ConditionFinalize(&cond);
2015 }
2016 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002017#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 {
2019 ENTER_TCL
2020 err = Tcl_CreateCommand(
2021 Tkapp_Interp(self), cmdName, PythonCmd,
2022 (ClientData)data, PythonCmdDelete) == NULL;
2023 LEAVE_TCL
2024 }
2025 if (err) {
2026 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2027 PyMem_DEL(data);
2028 return NULL;
2029 }
Guido van Rossum18468821994-06-20 07:49:28 +00002030
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002031 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002032}
2033
Barry Warsawfa701a81997-01-16 00:15:11 +00002034
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035
Guido van Rossum18468821994-06-20 07:49:28 +00002036static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002037Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002038{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 TkappObject *self = (TkappObject*)selfptr;
2040 char *cmdName;
2041 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002043 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2044 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002045
2046#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002047 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2048 Tcl_Condition cond = NULL;
2049 CommandEvent *ev;
2050 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2051 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2052 ev->interp = self->interp;
2053 ev->create = 0;
2054 ev->name = cmdName;
2055 ev->status = &err;
2056 ev->done = &cond;
2057 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2058 &command_mutex);
2059 Tcl_ConditionFinalize(&cond);
2060 }
2061 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002062#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 {
2064 ENTER_TCL
2065 err = Tcl_DeleteCommand(self->interp, cmdName);
2066 LEAVE_TCL
2067 }
2068 if (err == -1) {
2069 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2070 return NULL;
2071 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002072 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002073}
2074
Barry Warsawfa701a81997-01-16 00:15:11 +00002075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076
Guido van Rossum00d93061998-05-28 23:06:38 +00002077#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002078/** File Handler **/
2079
Guido van Rossum00d93061998-05-28 23:06:38 +00002080typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081 PyObject *func;
2082 PyObject *file;
2083 int id;
2084 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002085} FileHandler_ClientData;
2086
2087static FileHandler_ClientData *HeadFHCD;
2088
2089static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002090NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002091{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 FileHandler_ClientData *p;
2093 p = PyMem_NEW(FileHandler_ClientData, 1);
2094 if (p != NULL) {
2095 Py_XINCREF(func);
2096 Py_XINCREF(file);
2097 p->func = func;
2098 p->file = file;
2099 p->id = id;
2100 p->next = HeadFHCD;
2101 HeadFHCD = p;
2102 }
2103 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002104}
2105
2106static void
Fred Drake509d79a2000-07-08 04:04:38 +00002107DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002108{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002109 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002110
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002111 pp = &HeadFHCD;
2112 while ((p = *pp) != NULL) {
2113 if (p->id == id) {
2114 *pp = p->next;
2115 Py_XDECREF(p->func);
2116 Py_XDECREF(p->file);
2117 PyMem_DEL(p);
2118 }
2119 else
2120 pp = &p->next;
2121 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002122}
2123
Guido van Rossuma597dde1995-01-10 20:56:29 +00002124static void
Fred Drake509d79a2000-07-08 04:04:38 +00002125FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002126{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2128 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002129
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002130 ENTER_PYTHON
2131 func = data->func;
2132 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 arg = Py_BuildValue("(Oi)", file, (long) mask);
2135 res = PyEval_CallObject(func, arg);
2136 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 if (res == NULL) {
2139 errorInCmd = 1;
2140 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2141 }
2142 Py_XDECREF(res);
2143 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002144}
2145
Guido van Rossum18468821994-06-20 07:49:28 +00002146static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002147Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2148 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 FileHandler_ClientData *data;
2151 PyObject *file, *func;
2152 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002154 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2155 &file, &mask, &func))
2156 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002160 tfile = PyObject_AsFileDescriptor(file);
2161 if (tfile < 0)
2162 return NULL;
2163 if (!PyCallable_Check(func)) {
2164 PyErr_SetString(PyExc_TypeError, "bad argument list");
2165 return NULL;
2166 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002167
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 data = NewFHCD(func, file, tfile);
2169 if (data == NULL)
2170 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 /* Ought to check for null Tcl_File object... */
2173 ENTER_TCL
2174 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2175 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002176 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002177}
2178
2179static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002180Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002182 PyObject *file;
2183 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2186 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002187
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002188 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 tfile = PyObject_AsFileDescriptor(file);
2191 if (tfile < 0)
2192 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002196 /* Ought to check for null Tcl_File object... */
2197 ENTER_TCL
2198 Tcl_DeleteFileHandler(tfile);
2199 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002200 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002201}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002202#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002205/**** Tktt Object (timer token) ****/
2206
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002207static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002208
Guido van Rossum00d93061998-05-28 23:06:38 +00002209typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002210 PyObject_HEAD
2211 Tcl_TimerToken token;
2212 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002213} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002214
2215static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002216Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002217{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 TkttObject *v = (TkttObject *)self;
2219 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2222 return NULL;
2223 if (v->token != NULL) {
2224 Tcl_DeleteTimerHandler(v->token);
2225 v->token = NULL;
2226 }
2227 if (func != NULL) {
2228 v->func = NULL;
2229 Py_DECREF(func);
2230 Py_DECREF(v); /* See Tktt_New() */
2231 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002232 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002233}
2234
2235static PyMethodDef Tktt_methods[] =
2236{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2238 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002239};
2240
2241static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002242Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002243{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002244 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002245
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002246 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247 if (v == NULL)
2248 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002249 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002251 Py_INCREF(func);
2252 v->token = NULL;
2253 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002255 /* Extra reference, deleted when called or when handler is deleted */
2256 Py_INCREF(v);
2257 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002258}
2259
2260static void
Fred Drake509d79a2000-07-08 04:04:38 +00002261Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002262{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002263 TkttObject *v = (TkttObject *)self;
2264 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002265 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002266
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002267 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002270 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002271}
2272
Guido van Rossum597ac201998-05-12 14:36:19 +00002273static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002274Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002275{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002276 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002277 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2278 v,
2279 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280}
2281
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002282static PyType_Slot Tktt_Type_slots[] = {
2283 {Py_tp_dealloc, Tktt_Dealloc},
2284 {Py_tp_repr, Tktt_Repr},
2285 {Py_tp_methods, Tktt_methods},
2286 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287};
2288
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002289static PyType_Spec Tktt_Type_spec = {
2290 "tktimertoken",
2291 sizeof(TkttObject),
2292 0,
2293 Py_TPFLAGS_DEFAULT,
2294 Tktt_Type_slots,
2295};
Barry Warsawfa701a81997-01-16 00:15:11 +00002296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298/** Timer Handler **/
2299
2300static void
Fred Drake509d79a2000-07-08 04:04:38 +00002301TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 TkttObject *v = (TkttObject *)clientData;
2304 PyObject *func = v->func;
2305 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 if (func == NULL)
2308 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002309
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002310 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002314 res = PyEval_CallObject(func, NULL);
2315 Py_DECREF(func);
2316 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002317
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002318 if (res == NULL) {
2319 errorInCmd = 1;
2320 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2321 }
2322 else
2323 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326}
2327
2328static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002329Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 int milliseconds;
2332 PyObject *func;
2333 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002335 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2336 &milliseconds, &func))
2337 return NULL;
2338 if (!PyCallable_Check(func)) {
2339 PyErr_SetString(PyExc_TypeError, "bad argument list");
2340 return NULL;
2341 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002343 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345 v = Tktt_New(func);
2346 if (v) {
2347 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2348 (ClientData)v);
2349 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002352}
2353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354
Guido van Rossum18468821994-06-20 07:49:28 +00002355/** Event Loop **/
2356
Guido van Rossum18468821994-06-20 07:49:28 +00002357static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002358Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002359{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 int threshold = 0;
2361 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002362#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002363 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002364#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2367 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 CHECK_TCL_APPARTMENT;
2370 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 quitMainLoop = 0;
2373 while (Tk_GetNumMainWindows() > threshold &&
2374 !quitMainLoop &&
2375 !errorInCmd)
2376 {
2377 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002378
2379#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002380 if (self->threaded) {
2381 /* Allow other Python threads to run. */
2382 ENTER_TCL
2383 result = Tcl_DoOneEvent(0);
2384 LEAVE_TCL
2385 }
2386 else {
2387 Py_BEGIN_ALLOW_THREADS
2388 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2389 tcl_tstate = tstate;
2390 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2391 tcl_tstate = NULL;
2392 if(tcl_lock)PyThread_release_lock(tcl_lock);
2393 if (result == 0)
2394 Sleep(Tkinter_busywaitinterval);
2395 Py_END_ALLOW_THREADS
2396 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002397#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002399#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 if (PyErr_CheckSignals() != 0) {
2402 self->dispatching = 0;
2403 return NULL;
2404 }
2405 if (result < 0)
2406 break;
2407 }
2408 self->dispatching = 0;
2409 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 if (errorInCmd) {
2412 errorInCmd = 0;
2413 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2414 excInCmd = valInCmd = trbInCmd = NULL;
2415 return NULL;
2416 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002417 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002418}
2419
2420static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002421Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002422{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423 int flags = 0;
2424 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2427 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 ENTER_TCL
2430 rv = Tcl_DoOneEvent(flags);
2431 LEAVE_TCL
2432 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002433}
2434
2435static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002436Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002437{
2438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 if (!PyArg_ParseTuple(args, ":quit"))
2440 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002443 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002444}
2445
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002447Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002448{
2449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 if (!PyArg_ParseTuple(args, ":interpaddr"))
2451 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002452
Victor Stinnere1040e22013-09-05 00:22:24 +02002453 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002454}
2455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002457Tkapp_TkInit(PyObject *self, PyObject *args)
2458{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002459 Tcl_Interp *interp = Tkapp_Interp(self);
2460 const char * _tk_exists = NULL;
2461 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002462
Guilherme Polob681df42009-02-09 22:33:59 +00002463#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2465 * first call failed.
2466 * To avoid the deadlock, we just refuse the second call through
2467 * a static variable.
2468 */
2469 if (tk_load_failed) {
2470 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2471 return NULL;
2472 }
Guilherme Polob681df42009-02-09 22:33:59 +00002473#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 /* We want to guard against calling Tk_Init() multiple times */
2476 CHECK_TCL_APPARTMENT;
2477 ENTER_TCL
2478 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2479 ENTER_OVERLAP
2480 if (err == TCL_ERROR) {
2481 /* This sets an exception, but we cannot return right
2482 away because we need to exit the overlap first. */
2483 Tkinter_Error(self);
2484 } else {
2485 _tk_exists = Tkapp_Result(self);
2486 }
2487 LEAVE_OVERLAP_TCL
2488 if (err == TCL_ERROR) {
2489 return NULL;
2490 }
2491 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2492 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002493 PyErr_SetString(Tkinter_TclError,
2494 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002495#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002497#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002498 return NULL;
2499 }
2500 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002501 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002502}
Barry Warsawfa701a81997-01-16 00:15:11 +00002503
Martin v. Löwisffad6332002-11-26 09:28:05 +00002504static PyObject *
2505Tkapp_WantObjects(PyObject *self, PyObject *args)
2506{
2507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 int wantobjects = -1;
2509 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2510 return NULL;
2511 if (wantobjects == -1)
2512 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2513 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002514
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002515 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002516}
2517
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002518static PyObject *
2519Tkapp_WillDispatch(PyObject *self, PyObject *args)
2520{
2521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002523
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002524 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002525}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527
Guido van Rossum18468821994-06-20 07:49:28 +00002528/**** Tkapp Method List ****/
2529
2530static PyMethodDef Tkapp_methods[] =
2531{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2533 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2534 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2537 {"record", Tkapp_Record, METH_VARARGS},
2538 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2539 {"setvar", Tkapp_SetVar, METH_VARARGS},
2540 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2541 {"getvar", Tkapp_GetVar, METH_VARARGS},
2542 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2543 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2544 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2545 {"getint", Tkapp_GetInt, METH_VARARGS},
2546 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2547 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2548 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2549 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2550 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2551 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2552 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2553 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002554 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2555 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002556#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002557 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2558 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002559#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2561 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2562 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2563 {"quit", Tkapp_Quit, METH_VARARGS},
2564 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2565 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2566 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002567};
2568
Barry Warsawfa701a81997-01-16 00:15:11 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570
Guido van Rossum18468821994-06-20 07:49:28 +00002571/**** Tkapp Type Methods ****/
2572
2573static void
Fred Drake509d79a2000-07-08 04:04:38 +00002574Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002575{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002576 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 /*CHECK_TCL_APPARTMENT;*/
2578 ENTER_TCL
2579 Tcl_DeleteInterp(Tkapp_Interp(self));
2580 LEAVE_TCL
2581 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002582 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002584}
2585
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002586static PyType_Slot Tkapp_Type_slots[] = {
2587 {Py_tp_dealloc, Tkapp_Dealloc},
2588 {Py_tp_methods, Tkapp_methods},
2589 {0, 0}
2590};
2591
2592
2593static PyType_Spec Tkapp_Type_spec = {
2594 "tkapp",
2595 sizeof(TkappObject),
2596 0,
2597 Py_TPFLAGS_DEFAULT,
2598 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002599};
2600
Barry Warsawfa701a81997-01-16 00:15:11 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602
Guido van Rossum18468821994-06-20 07:49:28 +00002603/**** Tkinter Module ****/
2604
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002605typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606 PyObject* tuple;
2607 int size; /* current size */
2608 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002609} FlattenContext;
2610
2611static int
2612_bump(FlattenContext* context, int size)
2613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 /* expand tuple to hold (at least) size new items.
2615 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 if (maxsize < context->size + size)
2620 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002623
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002624 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002625}
2626
2627static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002628_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002629{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002632 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 if (depth > 1000) {
2635 PyErr_SetString(PyExc_ValueError,
2636 "nesting too deep in _flatten");
2637 return 0;
2638 } else if (PyList_Check(item)) {
2639 size = PyList_GET_SIZE(item);
2640 /* preallocate (assume no nesting) */
2641 if (context->size + size > context->maxsize &&
2642 !_bump(context, size))
2643 return 0;
2644 /* copy items to output tuple */
2645 for (i = 0; i < size; i++) {
2646 PyObject *o = PyList_GET_ITEM(item, i);
2647 if (PyList_Check(o) || PyTuple_Check(o)) {
2648 if (!_flatten1(context, o, depth + 1))
2649 return 0;
2650 } else if (o != Py_None) {
2651 if (context->size + 1 > context->maxsize &&
2652 !_bump(context, 1))
2653 return 0;
2654 Py_INCREF(o);
2655 PyTuple_SET_ITEM(context->tuple,
2656 context->size++, o);
2657 }
2658 }
2659 } else if (PyTuple_Check(item)) {
2660 /* same, for tuples */
2661 size = PyTuple_GET_SIZE(item);
2662 if (context->size + size > context->maxsize &&
2663 !_bump(context, size))
2664 return 0;
2665 for (i = 0; i < size; i++) {
2666 PyObject *o = PyTuple_GET_ITEM(item, i);
2667 if (PyList_Check(o) || PyTuple_Check(o)) {
2668 if (!_flatten1(context, o, depth + 1))
2669 return 0;
2670 } else if (o != Py_None) {
2671 if (context->size + 1 > context->maxsize &&
2672 !_bump(context, 1))
2673 return 0;
2674 Py_INCREF(o);
2675 PyTuple_SET_ITEM(context->tuple,
2676 context->size++, o);
2677 }
2678 }
2679 } else {
2680 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2681 return 0;
2682 }
2683 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002684}
2685
2686static PyObject *
2687Tkinter_Flatten(PyObject* self, PyObject* args)
2688{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002689 FlattenContext context;
2690 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2693 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 context.maxsize = PySequence_Size(item);
2696 if (context.maxsize < 0)
2697 return NULL;
2698 if (context.maxsize == 0)
2699 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002701 context.tuple = PyTuple_New(context.maxsize);
2702 if (!context.tuple)
2703 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002704
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002705 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 if (!_flatten1(&context, item,0))
2708 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002710 if (_PyTuple_Resize(&context.tuple, context.size))
2711 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002714}
2715
Guido van Rossum18468821994-06-20 07:49:28 +00002716static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002717Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002718{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002719 char *screenName = NULL;
2720 char *baseName = NULL; /* XXX this is not used anymore;
2721 try getting rid of it. */
2722 char *className = NULL;
2723 int interactive = 0;
2724 int wantobjects = 0;
2725 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2726 int sync = 0; /* pass -sync to wish */
2727 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002729 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002731 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2732 &screenName, &baseName, &className,
2733 &interactive, &wantobjects, &wantTk,
2734 &sync, &use))
2735 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002738 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002740}
2741
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002742static PyObject *
2743Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 int new_val;
2746 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2747 return NULL;
2748 if (new_val < 0) {
2749 PyErr_SetString(PyExc_ValueError,
2750 "busywaitinterval must be >= 0");
2751 return NULL;
2752 }
2753 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002754 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002755}
2756
2757static char setbusywaitinterval_doc[] =
2758"setbusywaitinterval(n) -> None\n\
2759\n\
2760Set the busy-wait interval in milliseconds between successive\n\
2761calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2762It should be set to a divisor of the maximum time between\n\
2763frames in an animation.";
2764
2765static PyObject *
2766Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002768 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002769}
2770
2771static char getbusywaitinterval_doc[] =
2772"getbusywaitinterval() -> int\n\
2773\n\
2774Return the current busy-wait interval between successive\n\
2775calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2776
Guido van Rossum18468821994-06-20 07:49:28 +00002777static PyMethodDef moduleMethods[] =
2778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2780 {"create", Tkinter_Create, METH_VARARGS},
2781 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2782 setbusywaitinterval_doc},
2783 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2784 METH_NOARGS, getbusywaitinterval_doc},
2785 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002786};
2787
Guido van Rossum7bf15641998-05-22 18:28:17 +00002788#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002789
2790static int stdin_ready = 0;
2791
Guido van Rossumad4db171998-06-13 13:56:28 +00002792#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002793static void
Fred Drake509d79a2000-07-08 04:04:38 +00002794MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002795{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002797}
Guido van Rossumad4db171998-06-13 13:56:28 +00002798#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002799
Martin v. Löwisa9656492003-03-30 08:44:58 +00002800#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002801static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002802#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002803
Guido van Rossum18468821994-06-20 07:49:28 +00002804static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002805EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002806{
Guido van Rossumad4db171998-06-13 13:56:28 +00002807#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002808 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002809#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002810#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002812#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 stdin_ready = 0;
2814 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002815#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 tfile = fileno(stdin);
2817 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002818#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002819 while (!errorInCmd && !stdin_ready) {
2820 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002821#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 if (_kbhit()) {
2823 stdin_ready = 1;
2824 break;
2825 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002826#endif
2827#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 Py_BEGIN_ALLOW_THREADS
2829 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2830 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002832 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834 tcl_tstate = NULL;
2835 if(tcl_lock)PyThread_release_lock(tcl_lock);
2836 if (result == 0)
2837 Sleep(Tkinter_busywaitinterval);
2838 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002839#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002840 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002841#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843 if (result < 0)
2844 break;
2845 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002846#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002848#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 if (errorInCmd) {
2850 errorInCmd = 0;
2851 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2852 excInCmd = valInCmd = trbInCmd = NULL;
2853 PyErr_Print();
2854 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002855#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002857#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002858 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002859}
Guido van Rossum18468821994-06-20 07:49:28 +00002860
Guido van Rossum00d93061998-05-28 23:06:38 +00002861#endif
2862
Guido van Rossum7bf15641998-05-22 18:28:17 +00002863static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002864EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002865{
Guido van Rossum00d93061998-05-28 23:06:38 +00002866#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002867 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002868#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002870#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002871 PyOS_InputHook = EventHook;
2872 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002873#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002874}
2875
2876static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002877DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002878{
Guido van Rossum00d93061998-05-28 23:06:38 +00002879#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002880 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2881 PyOS_InputHook = NULL;
2882 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002883#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002884}
2885
Barry Warsawfa701a81997-01-16 00:15:11 +00002886
Martin v. Löwis1a214512008-06-11 05:26:20 +00002887static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 PyModuleDef_HEAD_INIT,
2889 "_tkinter",
2890 NULL,
2891 -1,
2892 moduleMethods,
2893 NULL,
2894 NULL,
2895 NULL,
2896 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002897};
2898
Mark Hammond62b1ab12002-07-23 06:31:15 +00002899PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002900PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002901{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002902 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00002903
Guido van Rossum00d93061998-05-28 23:06:38 +00002904#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002906 if (tcl_lock == NULL)
2907 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002908#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 m = PyModule_Create(&_tkintermodule);
2911 if (m == NULL)
2912 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002913
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002914 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2915 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02002916 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002918 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002919 Py_INCREF(o);
2920 if (PyModule_AddObject(m, "TclError", o)) {
2921 Py_DECREF(o);
2922 Py_DECREF(m);
2923 return NULL;
2924 }
2925 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00002926
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002927 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
2928 Py_DECREF(m);
2929 return NULL;
2930 }
2931 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
2932 Py_DECREF(m);
2933 return NULL;
2934 }
2935 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
2936 Py_DECREF(m);
2937 return NULL;
2938 }
2939 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
2940 Py_DECREF(m);
2941 return NULL;
2942 }
2943 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
2944 Py_DECREF(m);
2945 return NULL;
2946 }
2947 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
2948 Py_DECREF(m);
2949 return NULL;
2950 }
2951 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
2952 Py_DECREF(m);
2953 return NULL;
2954 }
2955 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
2956 Py_DECREF(m);
2957 return NULL;
2958 }
2959 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
2960 Py_DECREF(m);
2961 return NULL;
2962 }
2963 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
2964 Py_DECREF(m);
2965 return NULL;
2966 }
2967 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
2968 Py_DECREF(m);
2969 return NULL;
2970 }
2971
2972 o = PyType_FromSpec(&Tkapp_Type_spec);
2973 if (o == NULL) {
2974 Py_DECREF(m);
2975 return NULL;
2976 }
2977 if (PyModule_AddObject(m, "TkappType", o)) {
2978 Py_DECREF(o);
2979 Py_DECREF(m);
2980 return NULL;
2981 }
2982 Tkapp_Type = o;
2983
2984 o = PyType_FromSpec(&Tktt_Type_spec);
2985 if (o == NULL) {
2986 Py_DECREF(m);
2987 return NULL;
2988 }
2989 if (PyModule_AddObject(m, "TkttType", o)) {
2990 Py_DECREF(o);
2991 Py_DECREF(m);
2992 return NULL;
2993 }
2994 Tktt_Type = o;
2995
2996 o = PyType_FromSpec(&PyTclObject_Type_spec);
2997 if (o == NULL) {
2998 Py_DECREF(m);
2999 return NULL;
3000 }
3001 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3002 Py_DECREF(o);
3003 Py_DECREF(m);
3004 return NULL;
3005 }
3006 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003007
3008#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003009 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3010 * start waking up. Note that Tcl_FindExecutable will do this, this
3011 * code must be above it! The original warning from
3012 * tkMacOSXAppInit.c is copied below.
3013 *
3014 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3015 * Tcl interpreter for now. It probably should work to do this
3016 * in the other order, but for now it doesn't seem to.
3017 *
3018 */
3019 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003020#endif
3021
3022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 /* This helps the dynamic loader; in Unicode aware Tcl versions
3024 it also helps Tcl find its encodings. */
3025 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3026 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003027 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003028 if (cexe)
3029 Tcl_FindExecutable(PyBytes_AsString(cexe));
3030 Py_XDECREF(cexe);
3031 Py_DECREF(uexe);
3032 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 if (PyErr_Occurred()) {
3035 Py_DECREF(m);
3036 return NULL;
3037 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003038
Guido van Rossum43ff8681998-07-14 18:02:13 +00003039#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 /* This was not a good idea; through <Destroy> bindings,
3041 Tcl_Finalize() may invoke Python code but at that point the
3042 interpreter and thread state have already been destroyed! */
3043 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003044#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003046}