blob: 761557fd3492ac5b5135eecd5cdd5082a687a36c [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
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
Christian Heimes217cfd12007-12-02 14:31:20 +000047#define PyBool_FromLong PyLong_FromLong
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000048#endif
49
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Guilherme Polo2d87e422009-04-10 22:19:09 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Polo66917722009-02-09 22:35:27 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Jack Janseneddc1442003-11-20 01:44:59 +000083#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000084#define HAVE_CREATEFILEHANDLER
85#endif
86
Guido van Rossum00d93061998-05-28 23:06:38 +000087#ifdef HAVE_CREATEFILEHANDLER
88
Neal Norwitzd948a432006-01-08 01:08:55 +000089/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
90 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
91#ifndef TCL_UNIX_FD
92# ifdef TCL_WIN_SOCKET
93# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
94# else
95# define TCL_UNIX_FD 1
96# endif
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* Tcl_CreateFileHandler() changed several times; these macros deal with the
100 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
101 Unix, only because Jack added it back); when available on Windows, it only
102 applies to sockets. */
103
Guido van Rossum7bf15641998-05-22 18:28:17 +0000104#ifdef MS_WINDOWS
105#define FHANDLETYPE TCL_WIN_SOCKET
106#else
107#define FHANDLETYPE TCL_UNIX_FD
108#endif
109
Guido van Rossum00d93061998-05-28 23:06:38 +0000110/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
111 which uses this to handle Tcl events while the user is typing commands. */
112
113#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000114#define WAIT_FOR_STDIN
115#endif
116
Guido van Rossum00d93061998-05-28 23:06:38 +0000117#endif /* HAVE_CREATEFILEHANDLER */
118
Guido van Rossumad4db171998-06-13 13:56:28 +0000119#ifdef MS_WINDOWS
120#include <conio.h>
121#define WAIT_FOR_STDIN
122#endif
123
Guido van Rossum00d93061998-05-28 23:06:38 +0000124#ifdef WITH_THREAD
125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000126/* The threading situation is complicated. Tcl is not thread-safe, except
127 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000128 So we need to use a lock around all uses of Tcl. Previously, the Python
129 interpreter lock was used for this. However, this causes problems when
130 other Python threads need to run while Tcl is blocked waiting for events.
131
132 To solve this problem, a separate lock for Tcl is introduced. Holding it
133 is incompatible with holding Python's interpreter lock. The following four
134 macros manipulate both locks together.
135
136 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
137 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
138 that could call an event handler, or otherwise affect the state of a Tcl
139 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000140 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000141 released and the lock for Tcl has been acquired.
142
Guido van Rossum5e977831998-06-15 14:03:52 +0000143 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
144 (For example, when transferring data from the Tcl interpreter result to a
145 Python string object.) This can be done by using different macros to close
146 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
147 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
148 releases the Tcl lock.
149
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000150 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000151 handlers when the handler needs to use Python. Such event handlers are
152 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000153 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000154 the Python interpreter lock, restoring the appropriate thread state, and
155 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
156 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000157 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000158
159 These locks expand to several statements and brackets; they should not be
160 used in branches of if statements and the like.
161
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
163 only valid in the thread that created it, and all Tk activity must happen in this
164 thread, also. That means that the mainloop must be invoked in the thread that
165 created the interpreter. Invoking commands from other threads is possible;
166 _tkinter will queue an event for the interpreter thread, which will then
167 execute the command and pass back the result. If the main thread is not in the
168 mainloop, and invoking commands causes an exception; if the main loop is running
169 but not processing events, the command invocation will block.
170
171 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
172 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
173 threads. So we use the Tcl TLS API.
174
Guido van Rossum00d93061998-05-28 23:06:38 +0000175*/
176
Guido van Rossum65d5b571998-12-21 19:32:43 +0000177static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178
179#ifdef TCL_THREADS
180static Tcl_ThreadDataKey state_key;
181typedef PyThreadState *ThreadSpecificData;
182#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
183#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000184static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000185#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000186
187#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000188 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
189 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000190
191#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000192 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000193
Guido van Rossum62320c91998-06-15 04:36:09 +0000194#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000196
197#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000199
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000201 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
202 if(tcl_lock)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()) { \
211 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
212 return 0; \
213 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000214
215#else
216
217#define ENTER_TCL
218#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000219#define ENTER_OVERLAP
220#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000221#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000222#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000224
225#endif
226
Guido van Rossum97867b21996-08-08 19:09:53 +0000227#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000228#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000229#endif
230
Guido van Rossum18468821994-06-20 07:49:28 +0000231/**** Tkapp Object Declaration ****/
232
Jeremy Hylton938ace62002-07-17 16:30:39 +0000233static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000234
Guido van Rossum00d93061998-05-28 23:06:38 +0000235typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 PyObject_HEAD
237 Tcl_Interp *interp;
238 int wantobjects;
239 int threaded; /* True if tcl_platform[threaded] */
240 Tcl_ThreadId thread_id;
241 int dispatching;
242 /* We cannot include tclInt.h, as this is internal.
243 So we cache interesting types here. */
244 Tcl_ObjType *BooleanType;
245 Tcl_ObjType *ByteArrayType;
246 Tcl_ObjType *DoubleType;
247 Tcl_ObjType *IntType;
248 Tcl_ObjType *ListType;
249 Tcl_ObjType *ProcBodyType;
250 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000251} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000252
Christian Heimes90aa7642007-12-19 02:45:37 +0000253#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
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) {
339 Py_INCREF(Py_None);
340 return Py_None;
341 }
Guido van Rossum18468821994-06-20 07:49:28 +0000342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
344 /* Not a list.
345 * Could be a quoted string containing funnies, e.g. {"}.
346 * Return the string itself.
347 */
348 return PyUnicode_FromString(list);
349 }
Guido van Rossum18468821994-06-20 07:49:28 +0000350
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000351 if (argc == 0)
352 v = PyUnicode_FromString("");
353 else if (argc == 1)
354 v = PyUnicode_FromString(argv[0]);
355 else if ((v = PyTuple_New(argc)) != NULL) {
356 int i;
357 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000359 for (i = 0; i < argc; i++) {
360 if ((w = Split(argv[i])) == NULL) {
361 Py_DECREF(v);
362 v = NULL;
363 break;
364 }
365 PyTuple_SetItem(v, i, w);
366 }
367 }
368 Tcl_Free(FREECAST argv);
369 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000370}
371
Martin v. Löwisffad6332002-11-26 09:28:05 +0000372/* In some cases, Tcl will still return strings that are supposed to be
373 lists. SplitObj walks through a nested tuple, finding string objects that
374 need to be split. */
375
Martin v. Löwis59683e82008-06-13 07:50:45 +0000376static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000377SplitObj(PyObject *arg)
378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379 if (PyTuple_Check(arg)) {
380 int i, size;
381 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000383 size = PyTuple_Size(arg);
384 result = NULL;
385 /* Recursively invoke SplitObj for all tuple items.
386 If this does not return a new object, no action is
387 needed. */
388 for(i = 0; i < size; i++) {
389 elem = PyTuple_GetItem(arg, i);
390 newelem = SplitObj(elem);
391 if (!newelem) {
392 Py_XDECREF(result);
393 return NULL;
394 }
395 if (!result) {
396 int k;
397 if (newelem == elem) {
398 Py_DECREF(newelem);
399 continue;
400 }
401 result = PyTuple_New(size);
402 if (!result)
403 return NULL;
404 for(k = 0; k < i; k++) {
405 elem = PyTuple_GetItem(arg, k);
406 Py_INCREF(elem);
407 PyTuple_SetItem(result, k, elem);
408 }
409 }
410 PyTuple_SetItem(result, i, newelem);
411 }
412 if (result)
413 return result;
414 /* Fall through, returning arg. */
415 }
416 else if (PyBytes_Check(arg)) {
417 int argc;
418 char **argv;
419 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000421 if (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(PyBytes_AsString(arg));
428 /* Fall through, returning arg. */
429 }
430 Py_INCREF(arg);
431 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000432}
Barry Warsawfa701a81997-01-16 00:15:11 +0000433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434
Guido van Rossum18468821994-06-20 07:49:28 +0000435/**** Tkapp Object ****/
436
437#ifndef WITH_APPINIT
438int
Fred Drake509d79a2000-07-08 04:04:38 +0000439Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000440{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 if (Tcl_Init(interp) == TCL_ERROR) {
444 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
445 return TCL_ERROR;
446 }
Guilherme Polob681df42009-02-09 22:33:59 +0000447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448 _tkinter_skip_tk_init = Tcl_GetVar(interp,
449 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
450 if (_tkinter_skip_tk_init != NULL &&
451 strcmp(_tkinter_skip_tk_init, "1") == 0) {
452 return TCL_OK;
453 }
Guilherme Polob681df42009-02-09 22:33:59 +0000454
455#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 if (tk_load_failed) {
457 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
458 return TCL_ERROR;
459 }
Guilherme Polob681df42009-02-09 22:33:59 +0000460#endif
461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000463#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000465#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
467 return TCL_ERROR;
468 }
Guilherme Polob681df42009-02-09 22:33:59 +0000469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000471}
472#endif /* !WITH_APPINIT */
473
Guido van Rossum18468821994-06-20 07:49:28 +0000474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475
Barry Warsawfa701a81997-01-16 00:15:11 +0000476
477/* Initialize the Tk application; see the `main' function in
478 * `tkMain.c'.
479 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000480
Thomas Wouters58d05102000-07-24 14:43:35 +0000481static void EnableEventHook(void); /* Forward */
482static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000483
Barry Warsawfa701a81997-01-16 00:15:11 +0000484static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000485Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000487{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488 TkappObject *v;
489 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 v = PyObject_New(TkappObject, &Tkapp_Type);
492 if (v == NULL)
493 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000495 v->interp = Tcl_CreateInterp();
496 v->wantobjects = wantobjects;
497 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
498 TCL_GLOBAL_ONLY) != NULL;
499 v->thread_id = Tcl_GetCurrentThread();
500 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000501
502#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503 if (v->threaded) {
504 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
505 Py_DECREF(v);
506 return 0;
507 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000508#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000509#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 if (v->threaded && tcl_lock) {
511 /* If Tcl is threaded, we don't need the lock. */
512 PyThread_free_lock(tcl_lock);
513 tcl_lock = NULL;
514 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000515#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 v->BooleanType = Tcl_GetObjType("boolean");
518 v->ByteArrayType = Tcl_GetObjType("bytearray");
519 v->DoubleType = Tcl_GetObjType("double");
520 v->IntType = Tcl_GetObjType("int");
521 v->ListType = Tcl_GetObjType("list");
522 v->ProcBodyType = Tcl_GetObjType("procbody");
523 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 /* Delete the 'exit' command, which can screw things up */
526 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000528 if (screenName != NULL)
529 Tcl_SetVar2(v->interp, "env", "DISPLAY",
530 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 if (interactive)
533 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
534 else
535 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000537 /* This is used to get the application class for Tk 4.1 and up */
538 argv0 = (char*)ckalloc(strlen(className) + 1);
539 if (!argv0) {
540 PyErr_NoMemory();
541 Py_DECREF(v);
542 return NULL;
543 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200546 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
547 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
549 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000550
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000551 if (! wantTk) {
552 Tcl_SetVar(v->interp,
553 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
554 }
Guilherme Polob681df42009-02-09 22:33:59 +0000555#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 else if (tk_load_failed) {
557 Tcl_SetVar(v->interp,
558 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
559 }
Guilherme Polob681df42009-02-09 22:33:59 +0000560#endif
David Aschere2b4b322004-02-18 05:59:53 +0000561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 /* some initial arguments need to be in argv */
563 if (sync || use) {
564 char *args;
565 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 if (sync)
568 len += sizeof "-sync";
569 if (use)
570 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000572 args = (char*)ckalloc(len);
573 if (!args) {
574 PyErr_NoMemory();
575 Py_DECREF(v);
576 return NULL;
577 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 args[0] = '\0';
580 if (sync)
581 strcat(args, "-sync");
582 if (use) {
583 if (sync)
584 strcat(args, " ");
585 strcat(args, "-use ");
586 strcat(args, use);
587 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
590 ckfree(args);
591 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (Tcl_AppInit(v->interp) != TCL_OK) {
594 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000595#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 if (wantTk) {
597 const char *_tkinter_tk_failed;
598 _tkinter_tk_failed = Tcl_GetVar(v->interp,
599 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 if ( _tkinter_tk_failed != NULL &&
602 strcmp(_tkinter_tk_failed, "1") == 0) {
603 tk_load_failed = 1;
604 }
605 }
Guilherme Polob681df42009-02-09 22:33:59 +0000606#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 Py_DECREF((PyObject *)v);
608 return (TkappObject *)result;
609 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000614}
615
Barry Warsawfa701a81997-01-16 00:15:11 +0000616
Benjamin Peterson5879d412009-03-30 14:51:56 +0000617#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000618static void
619Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000621{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 Py_BEGIN_ALLOW_THREADS;
623 Tcl_MutexLock(mutex);
624 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
625 Tcl_ThreadAlert(self->thread_id);
626 Tcl_ConditionWait(cond, mutex, NULL);
627 Tcl_MutexUnlock(mutex);
628 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000629}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000630#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000631
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000632
Guido van Rossum18468821994-06-20 07:49:28 +0000633/** Tcl Eval **/
634
Martin v. Löwisffad6332002-11-26 09:28:05 +0000635typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 PyObject_HEAD
637 Tcl_Obj *value;
638 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000639} PyTclObject;
640
Neal Norwitz227b5332006-03-22 09:28:35 +0000641static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000643
644static PyObject *
645newPyTclObject(Tcl_Obj *arg)
646{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 PyTclObject *self;
648 self = PyObject_New(PyTclObject, &PyTclObject_Type);
649 if (self == NULL)
650 return NULL;
651 Tcl_IncrRefCount(arg);
652 self->value = arg;
653 self->string = NULL;
654 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000655}
656
657static void
658PyTclObject_dealloc(PyTclObject *self)
659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 Tcl_DecrRefCount(self->value);
661 Py_XDECREF(self->string);
662 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000663}
664
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000665static char*
666PyTclObject_TclString(PyObject *self)
667{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000669}
670
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000671/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000672PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000673"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000674
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000675static PyObject *
676PyTclObject_string(PyTclObject *self, void *ignored)
677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 char *s;
679 int len;
680 if (!self->string) {
681 s = Tcl_GetStringFromObj(self->value, &len);
682 self->string = PyUnicode_FromStringAndSize(s, len);
683 if (!self->string)
684 return NULL;
685 }
686 Py_INCREF(self->string);
687 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000688}
689
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000690static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000691PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000692{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 char *s;
694 int len;
695 if (self->string && PyUnicode_Check(self->string)) {
696 Py_INCREF(self->string);
697 return self->string;
698 }
699 /* XXX Could chache result if it is non-ASCII. */
700 s = Tcl_GetStringFromObj(self->value, &len);
701 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000702}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000703
Martin v. Löwisffad6332002-11-26 09:28:05 +0000704static PyObject *
705PyTclObject_repr(PyTclObject *self)
706{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 return PyUnicode_FromFormat("<%s object at %p>",
708 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000709}
710
Mark Dickinson211c6252009-02-01 10:28:51 +0000711#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
712
713static PyObject *
714PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000715{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 int result;
717 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 /* neither argument should be NULL, unless something's gone wrong */
720 if (self == NULL || other == NULL) {
721 PyErr_BadInternalCall();
722 return NULL;
723 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 /* both arguments should be instances of PyTclObject */
726 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
727 v = Py_NotImplemented;
728 goto finished;
729 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 if (self == other)
732 /* fast path when self and other are identical */
733 result = 0;
734 else
735 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
736 Tcl_GetString(((PyTclObject *)other)->value));
737 /* Convert return value to a Boolean */
738 switch (op) {
739 case Py_EQ:
740 v = TEST_COND(result == 0);
741 break;
742 case Py_NE:
743 v = TEST_COND(result != 0);
744 break;
745 case Py_LE:
746 v = TEST_COND(result <= 0);
747 break;
748 case Py_GE:
749 v = TEST_COND(result >= 0);
750 break;
751 case Py_LT:
752 v = TEST_COND(result < 0);
753 break;
754 case Py_GT:
755 v = TEST_COND(result > 0);
756 break;
757 default:
758 PyErr_BadArgument();
759 return NULL;
760 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000761 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 Py_INCREF(v);
763 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000764}
765
Martin v. Löwis39195712003-01-04 00:33:13 +0000766PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
767
Martin v. Löwisffad6332002-11-26 09:28:05 +0000768static PyObject*
769get_typename(PyTclObject* obj, void* ignored)
770{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000771 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000772}
773
Martin v. Löwis39195712003-01-04 00:33:13 +0000774
Martin v. Löwisffad6332002-11-26 09:28:05 +0000775static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 {"typename", (getter)get_typename, NULL, get_typename__doc__},
777 {"string", (getter)PyTclObject_string, NULL,
778 PyTclObject_string__doc__},
779 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000780};
781
Neal Norwitz227b5332006-03-22 09:28:35 +0000782static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000783 PyVarObject_HEAD_INIT(NULL, 0)
784 "_tkinter.Tcl_Obj", /*tp_name*/
785 sizeof(PyTclObject), /*tp_basicsize*/
786 0, /*tp_itemsize*/
787 /* methods */
788 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
789 0, /*tp_print*/
790 0, /*tp_getattr*/
791 0, /*tp_setattr*/
792 0, /*tp_reserved*/
793 (reprfunc)PyTclObject_repr, /*tp_repr*/
794 0, /*tp_as_number*/
795 0, /*tp_as_sequence*/
796 0, /*tp_as_mapping*/
797 0, /*tp_hash*/
798 0, /*tp_call*/
799 (reprfunc)PyTclObject_str, /*tp_str*/
800 PyObject_GenericGetAttr, /*tp_getattro*/
801 0, /*tp_setattro*/
802 0, /*tp_as_buffer*/
803 Py_TPFLAGS_DEFAULT, /*tp_flags*/
804 0, /*tp_doc*/
805 0, /*tp_traverse*/
806 0, /*tp_clear*/
807 PyTclObject_richcompare, /*tp_richcompare*/
808 0, /*tp_weaklistoffset*/
809 0, /*tp_iter*/
810 0, /*tp_iternext*/
811 0, /*tp_methods*/
812 0, /*tp_members*/
813 PyTclObject_getsetlist, /*tp_getset*/
814 0, /*tp_base*/
815 0, /*tp_dict*/
816 0, /*tp_descr_get*/
817 0, /*tp_descr_set*/
818 0, /*tp_dictoffset*/
819 0, /*tp_init*/
820 0, /*tp_alloc*/
821 0, /*tp_new*/
822 0, /*tp_free*/
823 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000824};
825
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000826static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000827AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000828{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 Tcl_Obj *result;
830 long longVal;
831 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000833 if (PyBytes_Check(value))
834 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
835 PyBytes_GET_SIZE(value));
836 else if (PyBool_Check(value))
837 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
838 else if (PyLong_CheckExact(value) &&
839 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
840 !overflow)) {
841 /* If there is an overflow in the long conversion,
842 fall through to default object handling. */
843 return Tcl_NewLongObj(longVal);
844 }
845 else if (PyFloat_Check(value))
846 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
847 else if (PyTuple_Check(value)) {
848 Tcl_Obj **argv = (Tcl_Obj**)
849 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
850 int i;
851 if(!argv)
852 return 0;
853 for(i=0;i<PyTuple_Size(value);i++)
854 argv[i] = AsObj(PyTuple_GetItem(value,i));
855 result = Tcl_NewListObj(PyTuple_Size(value), argv);
856 ckfree(FREECAST argv);
857 return result;
858 }
859 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200860 void *inbuf;
861 Py_ssize_t size;
862 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000863 Tcl_UniChar *outbuf = NULL;
864 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200865 size_t allocsize;
866
867 if (PyUnicode_READY(value) == -1)
868 return NULL;
869
870 inbuf = PyUnicode_DATA(value);
871 size = PyUnicode_GET_LENGTH(value);
872 kind = PyUnicode_KIND(value);
873 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
874 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 /* Else overflow occurred, and we take the next exit */
876 if (!outbuf) {
877 PyErr_NoMemory();
878 return NULL;
879 }
880 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200881 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
882 /* We cannot test for sizeof(Tcl_UniChar) directly,
883 so we test for UTF-8 size instead. */
884#if TCL_UTF_MAX == 3
885 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000886 /* Tcl doesn't do UTF-16, yet. */
Victor Stinner7ab41922011-11-04 00:36:46 +0100887 PyErr_Format(PyExc_ValueError,
888 "character U+%x is above the range "
889 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100890 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000891 ckfree(FREECAST outbuf);
892 return NULL;
893 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300894#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200895 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 }
897 result = Tcl_NewUnicodeObj(outbuf, size);
898 ckfree(FREECAST outbuf);
899 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000900 }
901 else if(PyTclObject_Check(value)) {
902 Tcl_Obj *v = ((PyTclObject*)value)->value;
903 Tcl_IncrRefCount(v);
904 return v;
905 }
906 else {
907 PyObject *v = PyObject_Str(value);
908 if (!v)
909 return 0;
910 result = AsObj(v);
911 Py_DECREF(v);
912 return result;
913 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000914}
915
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916static PyObject*
917FromObj(PyObject* tkapp, Tcl_Obj *value)
918{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000919 PyObject *result = NULL;
920 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000921
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922 if (value->typePtr == NULL) {
923 return PyUnicode_FromStringAndSize(value->bytes,
924 value->length);
925 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 if (value->typePtr == app->BooleanType) {
928 result = value->internalRep.longValue ? Py_True : Py_False;
929 Py_INCREF(result);
930 return result;
931 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 if (value->typePtr == app->ByteArrayType) {
934 int size;
935 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
936 return PyBytes_FromStringAndSize(data, size);
937 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000939 if (value->typePtr == app->DoubleType) {
940 return PyFloat_FromDouble(value->internalRep.doubleValue);
941 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000943 if (value->typePtr == app->IntType) {
944 return PyLong_FromLong(value->internalRep.longValue);
945 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000947 if (value->typePtr == app->ListType) {
948 int size;
949 int i, status;
950 PyObject *elem;
951 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000953 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
954 if (status == TCL_ERROR)
955 return Tkinter_Error(tkapp);
956 result = PyTuple_New(size);
957 if (!result)
958 return NULL;
959 for (i = 0; i < size; i++) {
960 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
961 value, i, &tcl_elem);
962 if (status == TCL_ERROR) {
963 Py_DECREF(result);
964 return Tkinter_Error(tkapp);
965 }
966 elem = FromObj(tkapp, tcl_elem);
967 if (!elem) {
968 Py_DECREF(result);
969 return NULL;
970 }
971 PyTuple_SetItem(result, i, elem);
972 }
973 return result;
974 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000976 if (value->typePtr == app->ProcBodyType) {
977 /* fall through: return tcl object. */
978 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000979
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200981#if TCL_UTF_MAX==3
982 return PyUnicode_FromKindAndData(
983 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
984 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200986 return PyUnicode_FromKindAndData(
987 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
988 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000989#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000992 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993}
994
Benjamin Peterson5879d412009-03-30 14:51:56 +0000995#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000996/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000997TCL_DECLARE_MUTEX(call_mutex)
998
999typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 Tcl_Event ev; /* Must be first */
1001 TkappObject *self;
1002 PyObject *args;
1003 int flags;
1004 PyObject **res;
1005 PyObject **exc_type, **exc_value, **exc_tb;
1006 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001007} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001008#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001009
1010void
1011Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001012{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 int i;
1014 for (i = 0; i < objc; i++)
1015 Tcl_DecrRefCount(objv[i]);
1016 if (objv != objStore)
1017 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001018}
Guido van Rossum18468821994-06-20 07:49:28 +00001019
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001020/* Convert Python objects to Tcl objects. This must happen in the
1021 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001022
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001023static Tcl_Obj**
1024Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1025{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001026 Tcl_Obj **objv = objStore;
1027 int objc = 0, i;
1028 if (args == NULL)
1029 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 else if (!PyTuple_Check(args)) {
1032 objv[0] = AsObj(args);
1033 if (objv[0] == 0)
1034 goto finally;
1035 objc = 1;
1036 Tcl_IncrRefCount(objv[0]);
1037 }
1038 else {
1039 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001040
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001041 if (objc > ARGSZ) {
1042 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1043 if (objv == NULL) {
1044 PyErr_NoMemory();
1045 objc = 0;
1046 goto finally;
1047 }
1048 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001049
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001050 for (i = 0; i < objc; i++) {
1051 PyObject *v = PyTuple_GetItem(args, i);
1052 if (v == Py_None) {
1053 objc = i;
1054 break;
1055 }
1056 objv[i] = AsObj(v);
1057 if (!objv[i]) {
1058 /* Reset objc, so it attempts to clear
1059 objects only up to i. */
1060 objc = i;
1061 goto finally;
1062 }
1063 Tcl_IncrRefCount(objv[i]);
1064 }
1065 }
1066 *pobjc = objc;
1067 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001068finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 Tkapp_CallDeallocArgs(objv, objStore, objc);
1070 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001071}
Guido van Rossum212643f1998-04-29 16:22:14 +00001072
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001073/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001074
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001075static PyObject*
1076Tkapp_CallResult(TkappObject *self)
1077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 PyObject *res = NULL;
1079 if(self->wantobjects) {
1080 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1081 /* Not sure whether the IncrRef is necessary, but something
1082 may overwrite the interpreter result while we are
1083 converting it. */
1084 Tcl_IncrRefCount(value);
1085 res = FromObj((PyObject*)self, value);
1086 Tcl_DecrRefCount(value);
1087 } else {
1088 const char *s = Tcl_GetStringResult(self->interp);
1089 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1092 }
1093 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001094}
Guido van Rossum632de272000-03-29 00:19:50 +00001095
Benjamin Peterson5879d412009-03-30 14:51:56 +00001096#ifdef WITH_THREAD
1097
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001098/* Tkapp_CallProc is the event procedure that is executed in the context of
1099 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1100 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001101
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001102static int
1103Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 Tcl_Obj *objStore[ARGSZ];
1106 Tcl_Obj **objv;
1107 int objc;
1108 int i;
1109 ENTER_PYTHON
1110 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1111 if (!objv) {
1112 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1113 *(e->res) = NULL;
1114 }
1115 LEAVE_PYTHON
1116 if (!objv)
1117 goto done;
1118 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1119 ENTER_PYTHON
1120 if (i == TCL_ERROR) {
1121 *(e->res) = NULL;
1122 *(e->exc_type) = NULL;
1123 *(e->exc_tb) = NULL;
1124 *(e->exc_value) = PyObject_CallFunction(
1125 Tkinter_TclError, "s",
1126 Tcl_GetStringResult(e->self->interp));
1127 }
1128 else {
1129 *(e->res) = Tkapp_CallResult(e->self);
1130 }
1131 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001134done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 /* Wake up calling thread. */
1136 Tcl_MutexLock(&call_mutex);
1137 Tcl_ConditionNotify(e->done);
1138 Tcl_MutexUnlock(&call_mutex);
1139 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001140}
1141
Benjamin Peterson5879d412009-03-30 14:51:56 +00001142#endif
1143
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001144/* This is the main entry point for calling a Tcl command.
1145 It supports three cases, with regard to threading:
1146 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1147 the context of the calling thread.
1148 2. Tcl is threaded, caller of the command is in the interpreter thread:
1149 Execute the command in the calling thread. Since the Tcl lock will
1150 not be used, we can merge that with case 1.
1151 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1152 the interpreter thread. Allocation of Tcl objects needs to occur in the
1153 interpreter thread, so we ship the PyObject* args to the target thread,
1154 and perform processing there. */
1155
1156static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001157Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 Tcl_Obj *objStore[ARGSZ];
1160 Tcl_Obj **objv = NULL;
1161 int objc, i;
1162 PyObject *res = NULL;
1163 TkappObject *self = (TkappObject*)selfptr;
1164 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001166 /* If args is a single tuple, replace with contents of tuple */
1167 if (1 == PyTuple_Size(args)){
1168 PyObject* item = PyTuple_GetItem(args, 0);
1169 if (PyTuple_Check(item))
1170 args = item;
1171 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001172#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001173 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1174 /* We cannot call the command directly. Instead, we must
1175 marshal the parameters to the interpreter thread. */
1176 Tkapp_CallEvent *ev;
1177 Tcl_Condition cond = NULL;
1178 PyObject *exc_type, *exc_value, *exc_tb;
1179 if (!WaitForMainloop(self))
1180 return NULL;
1181 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1182 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1183 ev->self = self;
1184 ev->args = args;
1185 ev->res = &res;
1186 ev->exc_type = &exc_type;
1187 ev->exc_value = &exc_value;
1188 ev->exc_tb = &exc_tb;
1189 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 if (res == NULL) {
1194 if (exc_type)
1195 PyErr_Restore(exc_type, exc_value, exc_tb);
1196 else
1197 PyErr_SetObject(Tkinter_TclError, exc_value);
1198 }
1199 Tcl_ConditionFinalize(&cond);
1200 }
1201 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001202#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001205 objv = Tkapp_CallArgs(args, objStore, &objc);
1206 if (!objv)
1207 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 if (i == TCL_ERROR)
1216 Tkinter_Error(selfptr);
1217 else
1218 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001220 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 Tkapp_CallDeallocArgs(objv, objStore, objc);
1223 }
1224 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001225}
1226
1227
1228static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001229Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 char *script;
1232 PyObject *res = NULL;
1233 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 if (!PyArg_ParseTuple(args, "s:eval", &script))
1236 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001238 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001240 ENTER_TCL
1241 err = Tcl_Eval(Tkapp_Interp(self), script);
1242 ENTER_OVERLAP
1243 if (err == TCL_ERROR)
1244 res = Tkinter_Error(self);
1245 else
1246 res = PyUnicode_FromString(Tkapp_Result(self));
1247 LEAVE_OVERLAP_TCL
1248 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001249}
1250
1251static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001252Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001253{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001254 char *fileName;
1255 PyObject *res = NULL;
1256 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001258 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1259 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001260
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001261 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001263 ENTER_TCL
1264 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1265 ENTER_OVERLAP
1266 if (err == TCL_ERROR)
1267 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 else
1270 res = PyUnicode_FromString(Tkapp_Result(self));
1271 LEAVE_OVERLAP_TCL
1272 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001273}
1274
1275static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001276Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001277{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001278 char *script;
1279 PyObject *res = NULL;
1280 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 if (!PyArg_ParseTuple(args, "s", &script))
1283 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001287 ENTER_TCL
1288 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1289 ENTER_OVERLAP
1290 if (err == TCL_ERROR)
1291 res = Tkinter_Error(self);
1292 else
1293 res = PyUnicode_FromString(Tkapp_Result(self));
1294 LEAVE_OVERLAP_TCL
1295 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001296}
1297
1298static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001299Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001300{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001301 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1304 return NULL;
1305 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 ENTER_TCL
1308 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1309 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 Py_INCREF(Py_None);
1312 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001313}
1314
Barry Warsawfa701a81997-01-16 00:15:11 +00001315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316
Guido van Rossum18468821994-06-20 07:49:28 +00001317/** Tcl Variable **/
1318
Benjamin Peterson5879d412009-03-30 14:51:56 +00001319typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1320
1321#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322TCL_DECLARE_MUTEX(var_mutex)
1323
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 Tcl_Event ev; /* must be first */
1326 PyObject *self;
1327 PyObject *args;
1328 int flags;
1329 EventFunc func;
1330 PyObject **res;
1331 PyObject **exc_type;
1332 PyObject **exc_val;
1333 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001335#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001337static int
1338varname_converter(PyObject *in, void *_out)
1339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 char **out = (char**)_out;
1341 if (PyBytes_Check(in)) {
1342 *out = PyBytes_AsString(in);
1343 return 1;
1344 }
1345 if (PyUnicode_Check(in)) {
1346 *out = _PyUnicode_AsString(in);
1347 return 1;
1348 }
1349 if (PyTclObject_Check(in)) {
1350 *out = PyTclObject_TclString(in);
1351 return 1;
1352 }
1353 /* XXX: Should give diagnostics. */
1354 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001355}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001356
Benjamin Peterson5879d412009-03-30 14:51:56 +00001357#ifdef WITH_THREAD
1358
Martin v. Löwis59683e82008-06-13 07:50:45 +00001359static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360var_perform(VarEvent *ev)
1361{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1363 if (!*(ev->res)) {
1364 PyObject *exc, *val, *tb;
1365 PyErr_Fetch(&exc, &val, &tb);
1366 PyErr_NormalizeException(&exc, &val, &tb);
1367 *(ev->exc_type) = exc;
1368 *(ev->exc_val) = val;
1369 Py_DECREF(tb);
1370 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001371
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372}
1373
1374static int
1375var_proc(VarEvent* ev, int flags)
1376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 ENTER_PYTHON
1378 var_perform(ev);
1379 Tcl_MutexLock(&var_mutex);
1380 Tcl_ConditionNotify(ev->cond);
1381 Tcl_MutexUnlock(&var_mutex);
1382 LEAVE_PYTHON
1383 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001384}
1385
Benjamin Peterson5879d412009-03-30 14:51:56 +00001386#endif
1387
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001389var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001391#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 TkappObject *self = (TkappObject*)selfptr;
1393 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1394 TkappObject *self = (TkappObject*)selfptr;
1395 VarEvent *ev;
1396 PyObject *res, *exc_type, *exc_val;
1397 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001399 /* The current thread is not the interpreter thread. Marshal
1400 the call to the interpreter thread, then wait for
1401 completion. */
1402 if (!WaitForMainloop(self))
1403 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 ev->self = selfptr;
1408 ev->args = args;
1409 ev->flags = flags;
1410 ev->func = func;
1411 ev->res = &res;
1412 ev->exc_type = &exc_type;
1413 ev->exc_val = &exc_val;
1414 ev->cond = &cond;
1415 ev->ev.proc = (Tcl_EventProc*)var_proc;
1416 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1417 Tcl_ConditionFinalize(&cond);
1418 if (!res) {
1419 PyErr_SetObject(exc_type, exc_val);
1420 Py_DECREF(exc_type);
1421 Py_DECREF(exc_val);
1422 return NULL;
1423 }
1424 return res;
1425 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001426#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001427 /* Tcl is not threaded, or this is the interpreter thread. */
1428 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001429}
1430
Guido van Rossum18468821994-06-20 07:49:28 +00001431static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001432SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 char *name1, *name2;
1435 PyObject *newValue;
1436 PyObject *res = NULL;
1437 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 if (PyArg_ParseTuple(args, "O&O:setvar",
1440 varname_converter, &name1, &newValue)) {
1441 /* XXX Acquire tcl lock??? */
1442 newval = AsObj(newValue);
1443 if (newval == NULL)
1444 return NULL;
1445 ENTER_TCL
1446 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1447 newval, flags);
1448 ENTER_OVERLAP
1449 if (!ok)
1450 Tkinter_Error(self);
1451 else {
1452 res = Py_None;
1453 Py_INCREF(res);
1454 }
1455 LEAVE_OVERLAP_TCL
1456 }
1457 else {
1458 PyErr_Clear();
1459 if (PyArg_ParseTuple(args, "ssO:setvar",
1460 &name1, &name2, &newValue)) {
1461 /* XXX must hold tcl lock already??? */
1462 newval = AsObj(newValue);
1463 ENTER_TCL
1464 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1465 ENTER_OVERLAP
1466 if (!ok)
1467 Tkinter_Error(self);
1468 else {
1469 res = Py_None;
1470 Py_INCREF(res);
1471 }
1472 LEAVE_OVERLAP_TCL
1473 }
1474 else {
1475 return NULL;
1476 }
1477 }
1478 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001479}
1480
1481static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001482Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001483{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001485}
1486
1487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001488Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001489{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001491}
1492
Barry Warsawfa701a81997-01-16 00:15:11 +00001493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001494
Guido van Rossum18468821994-06-20 07:49:28 +00001495static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001496GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001497{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 char *name1, *name2=NULL;
1499 PyObject *res = NULL;
1500 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1503 varname_converter, &name1, &name2))
1504 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001506 ENTER_TCL
1507 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1508 ENTER_OVERLAP
1509 if (tres == NULL) {
1510 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1511 } else {
1512 if (((TkappObject*)self)->wantobjects) {
1513 res = FromObj(self, tres);
1514 }
1515 else {
1516 res = PyUnicode_FromString(Tcl_GetString(tres));
1517 }
1518 }
1519 LEAVE_OVERLAP_TCL
1520 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001521}
1522
1523static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001524Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001525{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001526 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001527}
1528
1529static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001530Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001531{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001533}
1534
Barry Warsawfa701a81997-01-16 00:15:11 +00001535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536
Guido van Rossum18468821994-06-20 07:49:28 +00001537static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001538UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001539{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001540 char *name1, *name2=NULL;
1541 int code;
1542 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1545 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001546
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 ENTER_TCL
1548 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1549 ENTER_OVERLAP
1550 if (code == TCL_ERROR)
1551 res = Tkinter_Error(self);
1552 else {
1553 Py_INCREF(Py_None);
1554 res = Py_None;
1555 }
1556 LEAVE_OVERLAP_TCL
1557 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001558}
1559
1560static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001561Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001562{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001564}
1565
1566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001567Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001568{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001570}
1571
Barry Warsawfa701a81997-01-16 00:15:11 +00001572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573
Guido van Rossum18468821994-06-20 07:49:28 +00001574/** Tcl to Python **/
1575
1576static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001577Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 char *s;
1580 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001582 if (PyTuple_Size(args) == 1) {
1583 PyObject* o = PyTuple_GetItem(args, 0);
1584 if (PyLong_Check(o)) {
1585 Py_INCREF(o);
1586 return o;
1587 }
1588 }
1589 if (!PyArg_ParseTuple(args, "s:getint", &s))
1590 return NULL;
1591 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1592 return Tkinter_Error(self);
1593 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001594}
1595
1596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001597Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001598{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001599 char *s;
1600 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001602 if (PyTuple_Size(args) == 1) {
1603 PyObject *o = PyTuple_GetItem(args, 0);
1604 if (PyFloat_Check(o)) {
1605 Py_INCREF(o);
1606 return o;
1607 }
1608 }
1609 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1610 return NULL;
1611 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1612 return Tkinter_Error(self);
1613 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001614}
1615
1616static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001617Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 char *s;
1620 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001622 if (PyTuple_Size(args) == 1) {
1623 PyObject *o = PyTuple_GetItem(args, 0);
1624 if (PyLong_Check(o)) {
1625 Py_INCREF(o);
1626 return o;
1627 }
1628 }
1629 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1630 return NULL;
1631 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1632 return Tkinter_Error(self);
1633 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001634}
1635
1636static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001637Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001638{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001639 char *s;
1640 PyObject *res = NULL;
1641 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001643 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1644 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001647
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001648 ENTER_TCL
1649 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1650 ENTER_OVERLAP
1651 if (retval == TCL_ERROR)
1652 res = Tkinter_Error(self);
1653 else
1654 res = Py_BuildValue("s", Tkapp_Result(self));
1655 LEAVE_OVERLAP_TCL
1656 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001657}
1658
1659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001662 char *s;
1663 PyObject *res = NULL;
1664 int retval;
1665 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1668 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001670 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 ENTER_TCL
1673 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1674 ENTER_OVERLAP
1675 if (retval == TCL_ERROR)
1676 res = Tkinter_Error(self);
1677 else
1678 res = Py_BuildValue("l", v);
1679 LEAVE_OVERLAP_TCL
1680 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001681}
1682
1683static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001684Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001685{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001686 char *s;
1687 PyObject *res = NULL;
1688 double v;
1689 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001691 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1692 return NULL;
1693 CHECK_TCL_APPARTMENT;
1694 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1695 ENTER_TCL
1696 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1697 ENTER_OVERLAP
1698 PyFPE_END_PROTECT(retval)
1699 if (retval == TCL_ERROR)
1700 res = Tkinter_Error(self);
1701 else
1702 res = Py_BuildValue("d", v);
1703 LEAVE_OVERLAP_TCL
1704 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001705}
1706
1707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001708Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710 char *s;
1711 PyObject *res = NULL;
1712 int retval;
1713 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001715 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1716 return NULL;
1717 CHECK_TCL_APPARTMENT;
1718 ENTER_TCL
1719 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1720 ENTER_OVERLAP
1721 if (retval == TCL_ERROR)
1722 res = Tkinter_Error(self);
1723 else
1724 res = Py_BuildValue("i", v);
1725 LEAVE_OVERLAP_TCL
1726 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001727}
1728
Barry Warsawfa701a81997-01-16 00:15:11 +00001729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001730
Guido van Rossum18468821994-06-20 07:49:28 +00001731static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001732Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001733{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001734 char *list;
1735 int argc;
1736 char **argv;
1737 PyObject *v;
1738 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001739
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001740 if (PyTuple_Size(args) == 1) {
1741 v = PyTuple_GetItem(args, 0);
1742 if (PyTuple_Check(v)) {
1743 Py_INCREF(v);
1744 return v;
1745 }
1746 }
1747 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1748 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001750 if (Tcl_SplitList(Tkapp_Interp(self), list,
1751 &argc, &argv) == TCL_ERROR) {
1752 PyMem_Free(list);
1753 return Tkinter_Error(self);
1754 }
Guido van Rossum18468821994-06-20 07:49:28 +00001755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 if (!(v = PyTuple_New(argc)))
1757 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 for (i = 0; i < argc; i++) {
1760 PyObject *s = PyUnicode_FromString(argv[i]);
1761 if (!s || PyTuple_SetItem(v, i, s)) {
1762 Py_DECREF(v);
1763 v = NULL;
1764 goto finally;
1765 }
1766 }
Guido van Rossum18468821994-06-20 07:49:28 +00001767
Barry Warsawfa701a81997-01-16 00:15:11 +00001768 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001769 ckfree(FREECAST argv);
1770 PyMem_Free(list);
1771 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001772}
1773
1774static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001775Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001776{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777 PyObject *v;
1778 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001780 if (PyTuple_Size(args) == 1) {
1781 PyObject* o = PyTuple_GetItem(args, 0);
1782 if (PyTuple_Check(o)) {
1783 o = SplitObj(o);
1784 return o;
1785 }
1786 }
1787 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1788 return NULL;
1789 v = Split(list);
1790 PyMem_Free(list);
1791 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001792}
1793
Barry Warsawfa701a81997-01-16 00:15:11 +00001794
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001795
Guido van Rossum18468821994-06-20 07:49:28 +00001796/** Tcl Command **/
1797
Guido van Rossum00d93061998-05-28 23:06:38 +00001798/* Client data struct */
1799typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001800 PyObject *self;
1801 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001802} PythonCmd_ClientData;
1803
1804static int
Fred Drake509d79a2000-07-08 04:04:38 +00001805PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001807 errorInCmd = 1;
1808 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1809 LEAVE_PYTHON
1810 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001811}
1812
Guido van Rossum18468821994-06-20 07:49:28 +00001813/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001814 * function or method.
1815 */
Guido van Rossum18468821994-06-20 07:49:28 +00001816static int
Fred Drake509d79a2000-07-08 04:04:38 +00001817PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001820 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821 int i, rv;
1822 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 /* TBD: no error checking here since we know, via the
1827 * Tkapp_CreateCommand() that the client data is a two-tuple
1828 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001831 /* Create argument list (argv1, ..., argvN) */
1832 if (!(arg = PyTuple_New(argc - 1)))
1833 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001835 for (i = 0; i < (argc - 1); i++) {
1836 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001837 if (!s) {
1838 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1839 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1840 !strcmp(argv[i + 1], "\xC0\x80")) {
1841 PyErr_Clear();
1842 /* Convert to "strict" utf-8 null */
1843 s = PyUnicode_FromString("\0");
1844 } else {
1845 Py_DECREF(arg);
1846 return PythonCmd_Error(interp);
1847 }
1848 }
1849 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 Py_DECREF(arg);
1851 return PythonCmd_Error(interp);
1852 }
1853 }
1854 res = PyEval_CallObject(func, arg);
1855 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001856
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001857 if (res == NULL)
1858 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001859
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 obj_res = AsObj(res);
1861 if (obj_res == NULL) {
1862 Py_DECREF(res);
1863 return PythonCmd_Error(interp);
1864 }
1865 else {
1866 Tcl_SetObjResult(interp, obj_res);
1867 rv = TCL_OK;
1868 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001870 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001872 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001873
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001874 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
1877static void
Fred Drake509d79a2000-07-08 04:04:38 +00001878PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001882 ENTER_PYTHON
1883 Py_XDECREF(data->self);
1884 Py_XDECREF(data->func);
1885 PyMem_DEL(data);
1886 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001887}
1888
Barry Warsawfa701a81997-01-16 00:15:11 +00001889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001891
Benjamin Peterson5879d412009-03-30 14:51:56 +00001892#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001893TCL_DECLARE_MUTEX(command_mutex)
1894
1895typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 Tcl_Event ev;
1897 Tcl_Interp* interp;
1898 char *name;
1899 int create;
1900 int *status;
1901 ClientData *data;
1902 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001903} CommandEvent;
1904
1905static int
1906Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (ev->create)
1909 *ev->status = Tcl_CreateCommand(
1910 ev->interp, ev->name, PythonCmd,
1911 ev->data, PythonCmdDelete) == NULL;
1912 else
1913 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1914 Tcl_MutexLock(&command_mutex);
1915 Tcl_ConditionNotify(ev->done);
1916 Tcl_MutexUnlock(&command_mutex);
1917 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001918}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001919#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001920
1921static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001922Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001923{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924 TkappObject *self = (TkappObject*)selfptr;
1925 PythonCmd_ClientData *data;
1926 char *cmdName;
1927 PyObject *func;
1928 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1931 return NULL;
1932 if (!PyCallable_Check(func)) {
1933 PyErr_SetString(PyExc_TypeError, "command not callable");
1934 return NULL;
1935 }
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Martin v. Löwisa9656492003-03-30 08:44:58 +00001937#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001938 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1939 !WaitForMainloop(self))
1940 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001941#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 data = PyMem_NEW(PythonCmd_ClientData, 1);
1944 if (!data)
1945 return PyErr_NoMemory();
1946 Py_INCREF(self);
1947 Py_INCREF(func);
1948 data->self = selfptr;
1949 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001950#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1952 Tcl_Condition cond = NULL;
1953 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1954 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1955 ev->interp = self->interp;
1956 ev->create = 1;
1957 ev->name = cmdName;
1958 ev->data = (ClientData)data;
1959 ev->status = &err;
1960 ev->done = &cond;
1961 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
1962 Tcl_ConditionFinalize(&cond);
1963 }
1964 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001965#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001966 {
1967 ENTER_TCL
1968 err = Tcl_CreateCommand(
1969 Tkapp_Interp(self), cmdName, PythonCmd,
1970 (ClientData)data, PythonCmdDelete) == NULL;
1971 LEAVE_TCL
1972 }
1973 if (err) {
1974 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1975 PyMem_DEL(data);
1976 return NULL;
1977 }
Guido van Rossum18468821994-06-20 07:49:28 +00001978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 Py_INCREF(Py_None);
1980 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001981}
1982
Barry Warsawfa701a81997-01-16 00:15:11 +00001983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984
Guido van Rossum18468821994-06-20 07:49:28 +00001985static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001986Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001987{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 TkappObject *self = (TkappObject*)selfptr;
1989 char *cmdName;
1990 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001991
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001992 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1993 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001994
1995#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1997 Tcl_Condition cond = NULL;
1998 CommandEvent *ev;
1999 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2000 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2001 ev->interp = self->interp;
2002 ev->create = 0;
2003 ev->name = cmdName;
2004 ev->status = &err;
2005 ev->done = &cond;
2006 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2007 &command_mutex);
2008 Tcl_ConditionFinalize(&cond);
2009 }
2010 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002011#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002012 {
2013 ENTER_TCL
2014 err = Tcl_DeleteCommand(self->interp, cmdName);
2015 LEAVE_TCL
2016 }
2017 if (err == -1) {
2018 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2019 return NULL;
2020 }
2021 Py_INCREF(Py_None);
2022 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002023}
2024
Barry Warsawfa701a81997-01-16 00:15:11 +00002025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002026
Guido van Rossum00d93061998-05-28 23:06:38 +00002027#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002028/** File Handler **/
2029
Guido van Rossum00d93061998-05-28 23:06:38 +00002030typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002031 PyObject *func;
2032 PyObject *file;
2033 int id;
2034 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002035} FileHandler_ClientData;
2036
2037static FileHandler_ClientData *HeadFHCD;
2038
2039static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002040NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002041{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 FileHandler_ClientData *p;
2043 p = PyMem_NEW(FileHandler_ClientData, 1);
2044 if (p != NULL) {
2045 Py_XINCREF(func);
2046 Py_XINCREF(file);
2047 p->func = func;
2048 p->file = file;
2049 p->id = id;
2050 p->next = HeadFHCD;
2051 HeadFHCD = p;
2052 }
2053 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002054}
2055
2056static void
Fred Drake509d79a2000-07-08 04:04:38 +00002057DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 pp = &HeadFHCD;
2062 while ((p = *pp) != NULL) {
2063 if (p->id == id) {
2064 *pp = p->next;
2065 Py_XDECREF(p->func);
2066 Py_XDECREF(p->file);
2067 PyMem_DEL(p);
2068 }
2069 else
2070 pp = &p->next;
2071 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002072}
2073
Guido van Rossuma597dde1995-01-10 20:56:29 +00002074static void
Fred Drake509d79a2000-07-08 04:04:38 +00002075FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2078 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 ENTER_PYTHON
2081 func = data->func;
2082 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 arg = Py_BuildValue("(Oi)", file, (long) mask);
2085 res = PyEval_CallObject(func, arg);
2086 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002088 if (res == NULL) {
2089 errorInCmd = 1;
2090 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2091 }
2092 Py_XDECREF(res);
2093 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002094}
2095
Guido van Rossum18468821994-06-20 07:49:28 +00002096static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002097Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2098 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002099{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 FileHandler_ClientData *data;
2101 PyObject *file, *func;
2102 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2105 &file, &mask, &func))
2106 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002108 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002109
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 tfile = PyObject_AsFileDescriptor(file);
2111 if (tfile < 0)
2112 return NULL;
2113 if (!PyCallable_Check(func)) {
2114 PyErr_SetString(PyExc_TypeError, "bad argument list");
2115 return NULL;
2116 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002118 data = NewFHCD(func, file, tfile);
2119 if (data == NULL)
2120 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 /* Ought to check for null Tcl_File object... */
2123 ENTER_TCL
2124 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2125 LEAVE_TCL
2126 Py_INCREF(Py_None);
2127 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002128}
2129
2130static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002131Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002133 PyObject *file;
2134 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2137 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002138
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002139 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002141 tfile = PyObject_AsFileDescriptor(file);
2142 if (tfile < 0)
2143 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002144
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002145 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002147 /* Ought to check for null Tcl_File object... */
2148 ENTER_TCL
2149 Tcl_DeleteFileHandler(tfile);
2150 LEAVE_TCL
2151 Py_INCREF(Py_None);
2152 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002153}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002154#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002157/**** Tktt Object (timer token) ****/
2158
Jeremy Hylton938ace62002-07-17 16:30:39 +00002159static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002160
Guido van Rossum00d93061998-05-28 23:06:38 +00002161typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002162 PyObject_HEAD
2163 Tcl_TimerToken token;
2164 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002165} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002166
2167static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002168Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 TkttObject *v = (TkttObject *)self;
2171 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2174 return NULL;
2175 if (v->token != NULL) {
2176 Tcl_DeleteTimerHandler(v->token);
2177 v->token = NULL;
2178 }
2179 if (func != NULL) {
2180 v->func = NULL;
2181 Py_DECREF(func);
2182 Py_DECREF(v); /* See Tktt_New() */
2183 }
2184 Py_INCREF(Py_None);
2185 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002186}
2187
2188static PyMethodDef Tktt_methods[] =
2189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2191 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002192};
2193
2194static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002195Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002196{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 v = PyObject_New(TkttObject, &Tktt_Type);
2200 if (v == NULL)
2201 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 Py_INCREF(func);
2204 v->token = NULL;
2205 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 /* Extra reference, deleted when called or when handler is deleted */
2208 Py_INCREF(v);
2209 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002210}
2211
2212static void
Fred Drake509d79a2000-07-08 04:04:38 +00002213Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 TkttObject *v = (TkttObject *)self;
2216 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002218 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002219
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002220 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002221}
2222
Guido van Rossum597ac201998-05-12 14:36:19 +00002223static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002224Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002227 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2228 v,
2229 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002230}
2231
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002232static PyTypeObject Tktt_Type =
2233{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 PyVarObject_HEAD_INIT(NULL, 0)
2235 "tktimertoken", /*tp_name */
2236 sizeof(TkttObject), /*tp_basicsize */
2237 0, /*tp_itemsize */
2238 Tktt_Dealloc, /*tp_dealloc */
2239 0, /*tp_print */
2240 0, /*tp_getattr */
2241 0, /*tp_setattr */
2242 0, /*tp_reserved */
2243 Tktt_Repr, /*tp_repr */
2244 0, /*tp_as_number */
2245 0, /*tp_as_sequence */
2246 0, /*tp_as_mapping */
2247 0, /*tp_hash */
2248 0, /*tp_call*/
2249 0, /*tp_str*/
2250 0, /*tp_getattro*/
2251 0, /*tp_setattro*/
2252 0, /*tp_as_buffer*/
2253 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2254 0, /*tp_doc*/
2255 0, /*tp_traverse*/
2256 0, /*tp_clear*/
2257 0, /*tp_richcompare*/
2258 0, /*tp_weaklistoffset*/
2259 0, /*tp_iter*/
2260 0, /*tp_iternext*/
2261 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002262};
2263
Barry Warsawfa701a81997-01-16 00:15:11 +00002264
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266/** Timer Handler **/
2267
2268static void
Fred Drake509d79a2000-07-08 04:04:38 +00002269TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002270{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 TkttObject *v = (TkttObject *)clientData;
2272 PyObject *func = v->func;
2273 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 if (func == NULL)
2276 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002278 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002279
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002282 res = PyEval_CallObject(func, NULL);
2283 Py_DECREF(func);
2284 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 if (res == NULL) {
2287 errorInCmd = 1;
2288 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2289 }
2290 else
2291 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002294}
2295
2296static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002297Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 int milliseconds;
2300 PyObject *func;
2301 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2304 &milliseconds, &func))
2305 return NULL;
2306 if (!PyCallable_Check(func)) {
2307 PyErr_SetString(PyExc_TypeError, "bad argument list");
2308 return NULL;
2309 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 v = Tktt_New(func);
2314 if (v) {
2315 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2316 (ClientData)v);
2317 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002318
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002320}
2321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322
Guido van Rossum18468821994-06-20 07:49:28 +00002323/** Event Loop **/
2324
Guido van Rossum18468821994-06-20 07:49:28 +00002325static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002326Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002327{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 int threshold = 0;
2329 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002330#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002331 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002332#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2335 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002337 CHECK_TCL_APPARTMENT;
2338 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002340 quitMainLoop = 0;
2341 while (Tk_GetNumMainWindows() > threshold &&
2342 !quitMainLoop &&
2343 !errorInCmd)
2344 {
2345 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002346
2347#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002348 if (self->threaded) {
2349 /* Allow other Python threads to run. */
2350 ENTER_TCL
2351 result = Tcl_DoOneEvent(0);
2352 LEAVE_TCL
2353 }
2354 else {
2355 Py_BEGIN_ALLOW_THREADS
2356 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2357 tcl_tstate = tstate;
2358 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2359 tcl_tstate = NULL;
2360 if(tcl_lock)PyThread_release_lock(tcl_lock);
2361 if (result == 0)
2362 Sleep(Tkinter_busywaitinterval);
2363 Py_END_ALLOW_THREADS
2364 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002365#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002367#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002369 if (PyErr_CheckSignals() != 0) {
2370 self->dispatching = 0;
2371 return NULL;
2372 }
2373 if (result < 0)
2374 break;
2375 }
2376 self->dispatching = 0;
2377 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 if (errorInCmd) {
2380 errorInCmd = 0;
2381 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2382 excInCmd = valInCmd = trbInCmd = NULL;
2383 return NULL;
2384 }
2385 Py_INCREF(Py_None);
2386 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002387}
2388
2389static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002390Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002391{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 int flags = 0;
2393 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2396 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 ENTER_TCL
2399 rv = Tcl_DoOneEvent(flags);
2400 LEAVE_TCL
2401 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002402}
2403
2404static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002405Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002406{
2407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 if (!PyArg_ParseTuple(args, ":quit"))
2409 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 quitMainLoop = 1;
2412 Py_INCREF(Py_None);
2413 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002414}
2415
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002416static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002417Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002418{
2419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 if (!PyArg_ParseTuple(args, ":interpaddr"))
2421 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002422
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002423 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002424}
2425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002427Tkapp_TkInit(PyObject *self, PyObject *args)
2428{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002429 Tcl_Interp *interp = Tkapp_Interp(self);
2430 const char * _tk_exists = NULL;
2431 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002432
Guilherme Polob681df42009-02-09 22:33:59 +00002433#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002434 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2435 * first call failed.
2436 * To avoid the deadlock, we just refuse the second call through
2437 * a static variable.
2438 */
2439 if (tk_load_failed) {
2440 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2441 return NULL;
2442 }
Guilherme Polob681df42009-02-09 22:33:59 +00002443#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 /* We want to guard against calling Tk_Init() multiple times */
2446 CHECK_TCL_APPARTMENT;
2447 ENTER_TCL
2448 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2449 ENTER_OVERLAP
2450 if (err == TCL_ERROR) {
2451 /* This sets an exception, but we cannot return right
2452 away because we need to exit the overlap first. */
2453 Tkinter_Error(self);
2454 } else {
2455 _tk_exists = Tkapp_Result(self);
2456 }
2457 LEAVE_OVERLAP_TCL
2458 if (err == TCL_ERROR) {
2459 return NULL;
2460 }
2461 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2462 if (Tk_Init(interp) == TCL_ERROR) {
2463 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002464#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002466#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002467 return NULL;
2468 }
2469 }
2470 Py_INCREF(Py_None);
2471 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002472}
Barry Warsawfa701a81997-01-16 00:15:11 +00002473
Martin v. Löwisffad6332002-11-26 09:28:05 +00002474static PyObject *
2475Tkapp_WantObjects(PyObject *self, PyObject *args)
2476{
2477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002478 int wantobjects = -1;
2479 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2480 return NULL;
2481 if (wantobjects == -1)
2482 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2483 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002485 Py_INCREF(Py_None);
2486 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002487}
2488
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002489static PyObject *
2490Tkapp_WillDispatch(PyObject *self, PyObject *args)
2491{
2492
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002493 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 Py_INCREF(Py_None);
2496 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002497}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002498
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002499
Guido van Rossum18468821994-06-20 07:49:28 +00002500/**** Tkapp Method List ****/
2501
2502static PyMethodDef Tkapp_methods[] =
2503{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2505 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2506 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002508 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2509 {"record", Tkapp_Record, METH_VARARGS},
2510 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2511 {"setvar", Tkapp_SetVar, METH_VARARGS},
2512 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2513 {"getvar", Tkapp_GetVar, METH_VARARGS},
2514 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2515 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2516 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2517 {"getint", Tkapp_GetInt, METH_VARARGS},
2518 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2519 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2520 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2521 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2522 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2523 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2524 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2525 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2527 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002528#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002529 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2530 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002531#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002532 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2533 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2534 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2535 {"quit", Tkapp_Quit, METH_VARARGS},
2536 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2537 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2538 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002539};
2540
Barry Warsawfa701a81997-01-16 00:15:11 +00002541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002542
Guido van Rossum18468821994-06-20 07:49:28 +00002543/**** Tkapp Type Methods ****/
2544
2545static void
Fred Drake509d79a2000-07-08 04:04:38 +00002546Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002547{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002548 /*CHECK_TCL_APPARTMENT;*/
2549 ENTER_TCL
2550 Tcl_DeleteInterp(Tkapp_Interp(self));
2551 LEAVE_TCL
2552 PyObject_Del(self);
2553 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002554}
2555
Guido van Rossum18468821994-06-20 07:49:28 +00002556static PyTypeObject Tkapp_Type =
2557{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002558 PyVarObject_HEAD_INIT(NULL, 0)
2559 "tkapp", /*tp_name */
2560 sizeof(TkappObject), /*tp_basicsize */
2561 0, /*tp_itemsize */
2562 Tkapp_Dealloc, /*tp_dealloc */
2563 0, /*tp_print */
2564 0, /*tp_getattr */
2565 0, /*tp_setattr */
2566 0, /*tp_reserved */
2567 0, /*tp_repr */
2568 0, /*tp_as_number */
2569 0, /*tp_as_sequence */
2570 0, /*tp_as_mapping */
2571 0, /*tp_hash */
2572 0, /*tp_call*/
2573 0, /*tp_str*/
2574 0, /*tp_getattro*/
2575 0, /*tp_setattro*/
2576 0, /*tp_as_buffer*/
2577 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2578 0, /*tp_doc*/
2579 0, /*tp_traverse*/
2580 0, /*tp_clear*/
2581 0, /*tp_richcompare*/
2582 0, /*tp_weaklistoffset*/
2583 0, /*tp_iter*/
2584 0, /*tp_iternext*/
2585 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002586};
2587
Barry Warsawfa701a81997-01-16 00:15:11 +00002588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589
Guido van Rossum18468821994-06-20 07:49:28 +00002590/**** Tkinter Module ****/
2591
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002592typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002593 PyObject* tuple;
2594 int size; /* current size */
2595 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002596} FlattenContext;
2597
2598static int
2599_bump(FlattenContext* context, int size)
2600{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 /* expand tuple to hold (at least) size new items.
2602 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002606 if (maxsize < context->size + size)
2607 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002612}
2613
2614static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002615_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002616{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002621 if (depth > 1000) {
2622 PyErr_SetString(PyExc_ValueError,
2623 "nesting too deep in _flatten");
2624 return 0;
2625 } else if (PyList_Check(item)) {
2626 size = PyList_GET_SIZE(item);
2627 /* preallocate (assume no nesting) */
2628 if (context->size + size > context->maxsize &&
2629 !_bump(context, size))
2630 return 0;
2631 /* copy items to output tuple */
2632 for (i = 0; i < size; i++) {
2633 PyObject *o = PyList_GET_ITEM(item, i);
2634 if (PyList_Check(o) || PyTuple_Check(o)) {
2635 if (!_flatten1(context, o, depth + 1))
2636 return 0;
2637 } else if (o != Py_None) {
2638 if (context->size + 1 > context->maxsize &&
2639 !_bump(context, 1))
2640 return 0;
2641 Py_INCREF(o);
2642 PyTuple_SET_ITEM(context->tuple,
2643 context->size++, o);
2644 }
2645 }
2646 } else if (PyTuple_Check(item)) {
2647 /* same, for tuples */
2648 size = PyTuple_GET_SIZE(item);
2649 if (context->size + size > context->maxsize &&
2650 !_bump(context, size))
2651 return 0;
2652 for (i = 0; i < size; i++) {
2653 PyObject *o = PyTuple_GET_ITEM(item, i);
2654 if (PyList_Check(o) || PyTuple_Check(o)) {
2655 if (!_flatten1(context, o, depth + 1))
2656 return 0;
2657 } else if (o != Py_None) {
2658 if (context->size + 1 > context->maxsize &&
2659 !_bump(context, 1))
2660 return 0;
2661 Py_INCREF(o);
2662 PyTuple_SET_ITEM(context->tuple,
2663 context->size++, o);
2664 }
2665 }
2666 } else {
2667 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2668 return 0;
2669 }
2670 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002671}
2672
2673static PyObject *
2674Tkinter_Flatten(PyObject* self, PyObject* args)
2675{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 FlattenContext context;
2677 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002678
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2680 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 context.maxsize = PySequence_Size(item);
2683 if (context.maxsize < 0)
2684 return NULL;
2685 if (context.maxsize == 0)
2686 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 context.tuple = PyTuple_New(context.maxsize);
2689 if (!context.tuple)
2690 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694 if (!_flatten1(&context, item,0))
2695 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 if (_PyTuple_Resize(&context.tuple, context.size))
2698 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002699
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002700 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002701}
2702
Guido van Rossum18468821994-06-20 07:49:28 +00002703static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002704Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 char *screenName = NULL;
2707 char *baseName = NULL; /* XXX this is not used anymore;
2708 try getting rid of it. */
2709 char *className = NULL;
2710 int interactive = 0;
2711 int wantobjects = 0;
2712 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2713 int sync = 0; /* pass -sync to wish */
2714 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002718 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2719 &screenName, &baseName, &className,
2720 &interactive, &wantobjects, &wantTk,
2721 &sync, &use))
2722 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002724 return (PyObject *) Tkapp_New(screenName, className,
2725 interactive, wantobjects, wantTk,
2726 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002727}
2728
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002729static PyObject *
2730Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2731{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002732 int new_val;
2733 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2734 return NULL;
2735 if (new_val < 0) {
2736 PyErr_SetString(PyExc_ValueError,
2737 "busywaitinterval must be >= 0");
2738 return NULL;
2739 }
2740 Tkinter_busywaitinterval = new_val;
2741 Py_INCREF(Py_None);
2742 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002743}
2744
2745static char setbusywaitinterval_doc[] =
2746"setbusywaitinterval(n) -> None\n\
2747\n\
2748Set the busy-wait interval in milliseconds between successive\n\
2749calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2750It should be set to a divisor of the maximum time between\n\
2751frames in an animation.";
2752
2753static PyObject *
2754Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2755{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002757}
2758
2759static char getbusywaitinterval_doc[] =
2760"getbusywaitinterval() -> int\n\
2761\n\
2762Return the current busy-wait interval between successive\n\
2763calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2764
Guido van Rossum18468821994-06-20 07:49:28 +00002765static PyMethodDef moduleMethods[] =
2766{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002767 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2768 {"create", Tkinter_Create, METH_VARARGS},
2769 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2770 setbusywaitinterval_doc},
2771 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2772 METH_NOARGS, getbusywaitinterval_doc},
2773 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002774};
2775
Guido van Rossum7bf15641998-05-22 18:28:17 +00002776#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002777
2778static int stdin_ready = 0;
2779
Guido van Rossumad4db171998-06-13 13:56:28 +00002780#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002781static void
Fred Drake509d79a2000-07-08 04:04:38 +00002782MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002783{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002784 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002785}
Guido van Rossumad4db171998-06-13 13:56:28 +00002786#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002787
Martin v. Löwisa9656492003-03-30 08:44:58 +00002788#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002789static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002790#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002791
Guido van Rossum18468821994-06-20 07:49:28 +00002792static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002793EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002794{
Guido van Rossumad4db171998-06-13 13:56:28 +00002795#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002796 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002797#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002798#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002799 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002800#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002801 stdin_ready = 0;
2802 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002803#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002804 tfile = fileno(stdin);
2805 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002806#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 while (!errorInCmd && !stdin_ready) {
2808 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002809#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002810 if (_kbhit()) {
2811 stdin_ready = 1;
2812 break;
2813 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002814#endif
2815#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002816 Py_BEGIN_ALLOW_THREADS
2817 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2818 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002819
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002820 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 tcl_tstate = NULL;
2823 if(tcl_lock)PyThread_release_lock(tcl_lock);
2824 if (result == 0)
2825 Sleep(Tkinter_busywaitinterval);
2826 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002827#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002828 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002829#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002830
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 if (result < 0)
2832 break;
2833 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002834#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002835 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002836#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 if (errorInCmd) {
2838 errorInCmd = 0;
2839 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2840 excInCmd = valInCmd = trbInCmd = NULL;
2841 PyErr_Print();
2842 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002843#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002845#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002847}
Guido van Rossum18468821994-06-20 07:49:28 +00002848
Guido van Rossum00d93061998-05-28 23:06:38 +00002849#endif
2850
Guido van Rossum7bf15641998-05-22 18:28:17 +00002851static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002852EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002853{
Guido van Rossum00d93061998-05-28 23:06:38 +00002854#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002855 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002856#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002857 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002858#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002859 PyOS_InputHook = EventHook;
2860 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002861#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002862}
2863
2864static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002865DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002866{
Guido van Rossum00d93061998-05-28 23:06:38 +00002867#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002868 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2869 PyOS_InputHook = NULL;
2870 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002871#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002872}
2873
Barry Warsawfa701a81997-01-16 00:15:11 +00002874
2875/* all errors will be checked in one fell swoop in init_tkinter() */
2876static void
Fred Drake509d79a2000-07-08 04:04:38 +00002877ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002878{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002879 PyObject *v = PyLong_FromLong(val);
2880 if (v) {
2881 PyDict_SetItemString(d, name, v);
2882 Py_DECREF(v);
2883 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002884}
2885static void
Fred Drake509d79a2000-07-08 04:04:38 +00002886ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002887{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 PyObject *v = PyUnicode_FromString(val);
2889 if (v) {
2890 PyDict_SetItemString(d, name, v);
2891 Py_DECREF(v);
2892 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002893}
2894
2895
Martin v. Löwis1a214512008-06-11 05:26:20 +00002896static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002897 PyModuleDef_HEAD_INIT,
2898 "_tkinter",
2899 NULL,
2900 -1,
2901 moduleMethods,
2902 NULL,
2903 NULL,
2904 NULL,
2905 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002906};
2907
Mark Hammond62b1ab12002-07-23 06:31:15 +00002908PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002909PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002910{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00002912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002913 if (PyType_Ready(&Tkapp_Type) < 0)
2914 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002915
2916#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002918#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002919
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 m = PyModule_Create(&_tkintermodule);
2921 if (m == NULL)
2922 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 d = PyModule_GetDict(m);
2925 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
2926 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 ins_long(d, "READABLE", TCL_READABLE);
2929 ins_long(d, "WRITABLE", TCL_WRITABLE);
2930 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2931 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2932 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2933 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2934 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2935 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2936 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
2937 ins_string(d, "TK_VERSION", TK_VERSION);
2938 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002941
Jesus Ceaef86d122012-07-19 21:18:07 +02002942 if (PyType_Ready(&Tktt_Type) < 0) {
2943 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002944 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002945 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00002947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
2949 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002950
2951#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2953 * start waking up. Note that Tcl_FindExecutable will do this, this
2954 * code must be above it! The original warning from
2955 * tkMacOSXAppInit.c is copied below.
2956 *
2957 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2958 * Tcl interpreter for now. It probably should work to do this
2959 * in the other order, but for now it doesn't seem to.
2960 *
2961 */
2962 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00002963#endif
2964
2965
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002966 /* This helps the dynamic loader; in Unicode aware Tcl versions
2967 it also helps Tcl find its encodings. */
2968 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
2969 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00002970 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002971 if (cexe)
2972 Tcl_FindExecutable(PyBytes_AsString(cexe));
2973 Py_XDECREF(cexe);
2974 Py_DECREF(uexe);
2975 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00002976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 if (PyErr_Occurred()) {
2978 Py_DECREF(m);
2979 return NULL;
2980 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002981
Guido van Rossum43ff8681998-07-14 18:02:13 +00002982#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002983 /* This was not a good idea; through <Destroy> bindings,
2984 Tcl_Finalize() may invoke Python code but at that point the
2985 interpreter and thread state have already been destroyed! */
2986 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002987#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002988 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00002989}