blob: edf0ca2c5fa626a7f0508c3a581c1fa48642e64a [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) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300339 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 }
Guido van Rossum18468821994-06-20 07:49:28 +0000341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
343 /* Not a list.
344 * Could be a quoted string containing funnies, e.g. {"}.
345 * Return the string itself.
346 */
347 return PyUnicode_FromString(list);
348 }
Guido van Rossum18468821994-06-20 07:49:28 +0000349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350 if (argc == 0)
351 v = PyUnicode_FromString("");
352 else if (argc == 1)
353 v = PyUnicode_FromString(argv[0]);
354 else if ((v = PyTuple_New(argc)) != NULL) {
355 int i;
356 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 for (i = 0; i < argc; i++) {
359 if ((w = Split(argv[i])) == NULL) {
360 Py_DECREF(v);
361 v = NULL;
362 break;
363 }
364 PyTuple_SetItem(v, i, w);
365 }
366 }
367 Tcl_Free(FREECAST argv);
368 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000369}
370
Martin v. Löwisffad6332002-11-26 09:28:05 +0000371/* In some cases, Tcl will still return strings that are supposed to be
372 lists. SplitObj walks through a nested tuple, finding string objects that
373 need to be split. */
374
Martin v. Löwis59683e82008-06-13 07:50:45 +0000375static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000376SplitObj(PyObject *arg)
377{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000378 if (PyTuple_Check(arg)) {
379 int i, size;
380 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 size = PyTuple_Size(arg);
383 result = NULL;
384 /* Recursively invoke SplitObj for all tuple items.
385 If this does not return a new object, no action is
386 needed. */
387 for(i = 0; i < size; i++) {
388 elem = PyTuple_GetItem(arg, i);
389 newelem = SplitObj(elem);
390 if (!newelem) {
391 Py_XDECREF(result);
392 return NULL;
393 }
394 if (!result) {
395 int k;
396 if (newelem == elem) {
397 Py_DECREF(newelem);
398 continue;
399 }
400 result = PyTuple_New(size);
401 if (!result)
402 return NULL;
403 for(k = 0; k < i; k++) {
404 elem = PyTuple_GetItem(arg, k);
405 Py_INCREF(elem);
406 PyTuple_SetItem(result, k, elem);
407 }
408 }
409 PyTuple_SetItem(result, i, newelem);
410 }
411 if (result)
412 return result;
413 /* Fall through, returning arg. */
414 }
415 else if (PyBytes_Check(arg)) {
416 int argc;
417 char **argv;
418 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
421 Py_INCREF(arg);
422 return arg;
423 }
424 Tcl_Free(FREECAST argv);
425 if (argc > 1)
426 return Split(PyBytes_AsString(arg));
427 /* Fall through, returning arg. */
428 }
429 Py_INCREF(arg);
430 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000431}
Barry Warsawfa701a81997-01-16 00:15:11 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433
Guido van Rossum18468821994-06-20 07:49:28 +0000434/**** Tkapp Object ****/
435
436#ifndef WITH_APPINIT
437int
Fred Drake509d79a2000-07-08 04:04:38 +0000438Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000442 if (Tcl_Init(interp) == TCL_ERROR) {
443 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
444 return TCL_ERROR;
445 }
Guilherme Polob681df42009-02-09 22:33:59 +0000446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000447 _tkinter_skip_tk_init = Tcl_GetVar(interp,
448 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
449 if (_tkinter_skip_tk_init != NULL &&
450 strcmp(_tkinter_skip_tk_init, "1") == 0) {
451 return TCL_OK;
452 }
Guilherme Polob681df42009-02-09 22:33:59 +0000453
454#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 if (tk_load_failed) {
456 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
457 return TCL_ERROR;
458 }
Guilherme Polob681df42009-02-09 22:33:59 +0000459#endif
460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000462#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000464#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
466 return TCL_ERROR;
467 }
Guilherme Polob681df42009-02-09 22:33:59 +0000468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000470}
471#endif /* !WITH_APPINIT */
472
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000474
Barry Warsawfa701a81997-01-16 00:15:11 +0000475
476/* Initialize the Tk application; see the `main' function in
477 * `tkMain.c'.
478 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000479
Thomas Wouters58d05102000-07-24 14:43:35 +0000480static void EnableEventHook(void); /* Forward */
481static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000482
Barry Warsawfa701a81997-01-16 00:15:11 +0000483static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000484Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000486{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000487 TkappObject *v;
488 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 v = PyObject_New(TkappObject, &Tkapp_Type);
491 if (v == NULL)
492 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 v->interp = Tcl_CreateInterp();
495 v->wantobjects = wantobjects;
496 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
497 TCL_GLOBAL_ONLY) != NULL;
498 v->thread_id = Tcl_GetCurrentThread();
499 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000500
501#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000502 if (v->threaded) {
503 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
504 Py_DECREF(v);
505 return 0;
506 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000507#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000508#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000509 if (v->threaded && tcl_lock) {
510 /* If Tcl is threaded, we don't need the lock. */
511 PyThread_free_lock(tcl_lock);
512 tcl_lock = NULL;
513 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000514#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000516 v->BooleanType = Tcl_GetObjType("boolean");
517 v->ByteArrayType = Tcl_GetObjType("bytearray");
518 v->DoubleType = Tcl_GetObjType("double");
519 v->IntType = Tcl_GetObjType("int");
520 v->ListType = Tcl_GetObjType("list");
521 v->ProcBodyType = Tcl_GetObjType("procbody");
522 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000524 /* Delete the 'exit' command, which can screw things up */
525 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000527 if (screenName != NULL)
528 Tcl_SetVar2(v->interp, "env", "DISPLAY",
529 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 if (interactive)
532 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
533 else
534 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 /* This is used to get the application class for Tk 4.1 and up */
537 argv0 = (char*)ckalloc(strlen(className) + 1);
538 if (!argv0) {
539 PyErr_NoMemory();
540 Py_DECREF(v);
541 return NULL;
542 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200545 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
546 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
548 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 if (! wantTk) {
551 Tcl_SetVar(v->interp,
552 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
553 }
Guilherme Polob681df42009-02-09 22:33:59 +0000554#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 else if (tk_load_failed) {
556 Tcl_SetVar(v->interp,
557 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
558 }
Guilherme Polob681df42009-02-09 22:33:59 +0000559#endif
David Aschere2b4b322004-02-18 05:59:53 +0000560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 /* some initial arguments need to be in argv */
562 if (sync || use) {
563 char *args;
564 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 if (sync)
567 len += sizeof "-sync";
568 if (use)
569 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 args = (char*)ckalloc(len);
572 if (!args) {
573 PyErr_NoMemory();
574 Py_DECREF(v);
575 return NULL;
576 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 args[0] = '\0';
579 if (sync)
580 strcat(args, "-sync");
581 if (use) {
582 if (sync)
583 strcat(args, " ");
584 strcat(args, "-use ");
585 strcat(args, use);
586 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
589 ckfree(args);
590 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 if (Tcl_AppInit(v->interp) != TCL_OK) {
593 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000594#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 if (wantTk) {
596 const char *_tkinter_tk_failed;
597 _tkinter_tk_failed = Tcl_GetVar(v->interp,
598 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 if ( _tkinter_tk_failed != NULL &&
601 strcmp(_tkinter_tk_failed, "1") == 0) {
602 tk_load_failed = 1;
603 }
604 }
Guilherme Polob681df42009-02-09 22:33:59 +0000605#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 Py_DECREF((PyObject *)v);
607 return (TkappObject *)result;
608 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000613}
614
Barry Warsawfa701a81997-01-16 00:15:11 +0000615
Benjamin Peterson5879d412009-03-30 14:51:56 +0000616#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000617static void
618Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000620{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 Py_BEGIN_ALLOW_THREADS;
622 Tcl_MutexLock(mutex);
623 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
624 Tcl_ThreadAlert(self->thread_id);
625 Tcl_ConditionWait(cond, mutex, NULL);
626 Tcl_MutexUnlock(mutex);
627 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000629#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631
Guido van Rossum18468821994-06-20 07:49:28 +0000632/** Tcl Eval **/
633
Martin v. Löwisffad6332002-11-26 09:28:05 +0000634typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 PyObject_HEAD
636 Tcl_Obj *value;
637 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000638} PyTclObject;
639
Neal Norwitz227b5332006-03-22 09:28:35 +0000640static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000642
643static PyObject *
644newPyTclObject(Tcl_Obj *arg)
645{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 PyTclObject *self;
647 self = PyObject_New(PyTclObject, &PyTclObject_Type);
648 if (self == NULL)
649 return NULL;
650 Tcl_IncrRefCount(arg);
651 self->value = arg;
652 self->string = NULL;
653 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000654}
655
656static void
657PyTclObject_dealloc(PyTclObject *self)
658{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 Tcl_DecrRefCount(self->value);
660 Py_XDECREF(self->string);
661 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000662}
663
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000664static char*
665PyTclObject_TclString(PyObject *self)
666{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000668}
669
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000670/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000671PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000672"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000673
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000674static PyObject *
675PyTclObject_string(PyTclObject *self, void *ignored)
676{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 char *s;
678 int len;
679 if (!self->string) {
680 s = Tcl_GetStringFromObj(self->value, &len);
681 self->string = PyUnicode_FromStringAndSize(s, len);
682 if (!self->string)
683 return NULL;
684 }
685 Py_INCREF(self->string);
686 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000687}
688
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000689static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000690PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000691{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 char *s;
693 int len;
694 if (self->string && PyUnicode_Check(self->string)) {
695 Py_INCREF(self->string);
696 return self->string;
697 }
698 /* XXX Could chache result if it is non-ASCII. */
699 s = Tcl_GetStringFromObj(self->value, &len);
700 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000701}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000702
Martin v. Löwisffad6332002-11-26 09:28:05 +0000703static PyObject *
704PyTclObject_repr(PyTclObject *self)
705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 return PyUnicode_FromFormat("<%s object at %p>",
707 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000708}
709
Mark Dickinson211c6252009-02-01 10:28:51 +0000710#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
711
712static PyObject *
713PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000714{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 int result;
716 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 /* neither argument should be NULL, unless something's gone wrong */
719 if (self == NULL || other == NULL) {
720 PyErr_BadInternalCall();
721 return NULL;
722 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 /* both arguments should be instances of PyTclObject */
725 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
726 v = Py_NotImplemented;
727 goto finished;
728 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000729
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 if (self == other)
731 /* fast path when self and other are identical */
732 result = 0;
733 else
734 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
735 Tcl_GetString(((PyTclObject *)other)->value));
736 /* Convert return value to a Boolean */
737 switch (op) {
738 case Py_EQ:
739 v = TEST_COND(result == 0);
740 break;
741 case Py_NE:
742 v = TEST_COND(result != 0);
743 break;
744 case Py_LE:
745 v = TEST_COND(result <= 0);
746 break;
747 case Py_GE:
748 v = TEST_COND(result >= 0);
749 break;
750 case Py_LT:
751 v = TEST_COND(result < 0);
752 break;
753 case Py_GT:
754 v = TEST_COND(result > 0);
755 break;
756 default:
757 PyErr_BadArgument();
758 return NULL;
759 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000760 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 Py_INCREF(v);
762 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000763}
764
Martin v. Löwis39195712003-01-04 00:33:13 +0000765PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
766
Martin v. Löwisffad6332002-11-26 09:28:05 +0000767static PyObject*
768get_typename(PyTclObject* obj, void* ignored)
769{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000771}
772
Martin v. Löwis39195712003-01-04 00:33:13 +0000773
Martin v. Löwisffad6332002-11-26 09:28:05 +0000774static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000775 {"typename", (getter)get_typename, NULL, get_typename__doc__},
776 {"string", (getter)PyTclObject_string, NULL,
777 PyTclObject_string__doc__},
778 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000779};
780
Neal Norwitz227b5332006-03-22 09:28:35 +0000781static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782 PyVarObject_HEAD_INIT(NULL, 0)
783 "_tkinter.Tcl_Obj", /*tp_name*/
784 sizeof(PyTclObject), /*tp_basicsize*/
785 0, /*tp_itemsize*/
786 /* methods */
787 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
788 0, /*tp_print*/
789 0, /*tp_getattr*/
790 0, /*tp_setattr*/
791 0, /*tp_reserved*/
792 (reprfunc)PyTclObject_repr, /*tp_repr*/
793 0, /*tp_as_number*/
794 0, /*tp_as_sequence*/
795 0, /*tp_as_mapping*/
796 0, /*tp_hash*/
797 0, /*tp_call*/
798 (reprfunc)PyTclObject_str, /*tp_str*/
799 PyObject_GenericGetAttr, /*tp_getattro*/
800 0, /*tp_setattro*/
801 0, /*tp_as_buffer*/
802 Py_TPFLAGS_DEFAULT, /*tp_flags*/
803 0, /*tp_doc*/
804 0, /*tp_traverse*/
805 0, /*tp_clear*/
806 PyTclObject_richcompare, /*tp_richcompare*/
807 0, /*tp_weaklistoffset*/
808 0, /*tp_iter*/
809 0, /*tp_iternext*/
810 0, /*tp_methods*/
811 0, /*tp_members*/
812 PyTclObject_getsetlist, /*tp_getset*/
813 0, /*tp_base*/
814 0, /*tp_dict*/
815 0, /*tp_descr_get*/
816 0, /*tp_descr_set*/
817 0, /*tp_dictoffset*/
818 0, /*tp_init*/
819 0, /*tp_alloc*/
820 0, /*tp_new*/
821 0, /*tp_free*/
822 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823};
824
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000825static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000826AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 Tcl_Obj *result;
829 long longVal;
830 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000832 if (PyBytes_Check(value))
833 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
834 PyBytes_GET_SIZE(value));
835 else if (PyBool_Check(value))
836 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
837 else if (PyLong_CheckExact(value) &&
838 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
839 !overflow)) {
840 /* If there is an overflow in the long conversion,
841 fall through to default object handling. */
842 return Tcl_NewLongObj(longVal);
843 }
844 else if (PyFloat_Check(value))
845 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
846 else if (PyTuple_Check(value)) {
847 Tcl_Obj **argv = (Tcl_Obj**)
848 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
849 int i;
850 if(!argv)
851 return 0;
852 for(i=0;i<PyTuple_Size(value);i++)
853 argv[i] = AsObj(PyTuple_GetItem(value,i));
854 result = Tcl_NewListObj(PyTuple_Size(value), argv);
855 ckfree(FREECAST argv);
856 return result;
857 }
858 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200859 void *inbuf;
860 Py_ssize_t size;
861 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000862 Tcl_UniChar *outbuf = NULL;
863 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200864 size_t allocsize;
865
866 if (PyUnicode_READY(value) == -1)
867 return NULL;
868
869 inbuf = PyUnicode_DATA(value);
870 size = PyUnicode_GET_LENGTH(value);
871 kind = PyUnicode_KIND(value);
872 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
873 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000874 /* Else overflow occurred, and we take the next exit */
875 if (!outbuf) {
876 PyErr_NoMemory();
877 return NULL;
878 }
879 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200880 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
881 /* We cannot test for sizeof(Tcl_UniChar) directly,
882 so we test for UTF-8 size instead. */
883#if TCL_UTF_MAX == 3
884 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 /* Tcl doesn't do UTF-16, yet. */
Victor Stinner7ab41922011-11-04 00:36:46 +0100886 PyErr_Format(PyExc_ValueError,
887 "character U+%x is above the range "
888 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +0100889 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000890 ckfree(FREECAST outbuf);
891 return NULL;
892 }
Andrew Svetlov80823d72012-07-22 13:56:54 +0300893#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200894 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000895 }
896 result = Tcl_NewUnicodeObj(outbuf, size);
897 ckfree(FREECAST outbuf);
898 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 }
900 else if(PyTclObject_Check(value)) {
901 Tcl_Obj *v = ((PyTclObject*)value)->value;
902 Tcl_IncrRefCount(v);
903 return v;
904 }
905 else {
906 PyObject *v = PyObject_Str(value);
907 if (!v)
908 return 0;
909 result = AsObj(v);
910 Py_DECREF(v);
911 return result;
912 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000913}
914
Martin v. Löwisffad6332002-11-26 09:28:05 +0000915static PyObject*
916FromObj(PyObject* tkapp, Tcl_Obj *value)
917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 PyObject *result = NULL;
919 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 if (value->typePtr == NULL) {
922 return PyUnicode_FromStringAndSize(value->bytes,
923 value->length);
924 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000926 if (value->typePtr == app->BooleanType) {
927 result = value->internalRep.longValue ? Py_True : Py_False;
928 Py_INCREF(result);
929 return result;
930 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 if (value->typePtr == app->ByteArrayType) {
933 int size;
934 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
935 return PyBytes_FromStringAndSize(data, size);
936 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 if (value->typePtr == app->DoubleType) {
939 return PyFloat_FromDouble(value->internalRep.doubleValue);
940 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 if (value->typePtr == app->IntType) {
943 return PyLong_FromLong(value->internalRep.longValue);
944 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000946 if (value->typePtr == app->ListType) {
947 int size;
948 int i, status;
949 PyObject *elem;
950 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
953 if (status == TCL_ERROR)
954 return Tkinter_Error(tkapp);
955 result = PyTuple_New(size);
956 if (!result)
957 return NULL;
958 for (i = 0; i < size; i++) {
959 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
960 value, i, &tcl_elem);
961 if (status == TCL_ERROR) {
962 Py_DECREF(result);
963 return Tkinter_Error(tkapp);
964 }
965 elem = FromObj(tkapp, tcl_elem);
966 if (!elem) {
967 Py_DECREF(result);
968 return NULL;
969 }
970 PyTuple_SetItem(result, i, elem);
971 }
972 return result;
973 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000974
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 if (value->typePtr == app->ProcBodyType) {
976 /* fall through: return tcl object. */
977 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000979 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200980#if TCL_UTF_MAX==3
981 return PyUnicode_FromKindAndData(
982 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
983 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000984#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200985 return PyUnicode_FromKindAndData(
986 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
987 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000990
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000992}
993
Benjamin Peterson5879d412009-03-30 14:51:56 +0000994#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000995/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000996TCL_DECLARE_MUTEX(call_mutex)
997
998typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 Tcl_Event ev; /* Must be first */
1000 TkappObject *self;
1001 PyObject *args;
1002 int flags;
1003 PyObject **res;
1004 PyObject **exc_type, **exc_value, **exc_tb;
1005 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001006} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001007#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001008
1009void
1010Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 int i;
1013 for (i = 0; i < objc; i++)
1014 Tcl_DecrRefCount(objv[i]);
1015 if (objv != objStore)
1016 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001017}
Guido van Rossum18468821994-06-20 07:49:28 +00001018
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001019/* Convert Python objects to Tcl objects. This must happen in the
1020 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001021
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001022static Tcl_Obj**
1023Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1024{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001025 Tcl_Obj **objv = objStore;
1026 int objc = 0, i;
1027 if (args == NULL)
1028 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001030 else if (!PyTuple_Check(args)) {
1031 objv[0] = AsObj(args);
1032 if (objv[0] == 0)
1033 goto finally;
1034 objc = 1;
1035 Tcl_IncrRefCount(objv[0]);
1036 }
1037 else {
1038 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001040 if (objc > ARGSZ) {
1041 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1042 if (objv == NULL) {
1043 PyErr_NoMemory();
1044 objc = 0;
1045 goto finally;
1046 }
1047 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 for (i = 0; i < objc; i++) {
1050 PyObject *v = PyTuple_GetItem(args, i);
1051 if (v == Py_None) {
1052 objc = i;
1053 break;
1054 }
1055 objv[i] = AsObj(v);
1056 if (!objv[i]) {
1057 /* Reset objc, so it attempts to clear
1058 objects only up to i. */
1059 objc = i;
1060 goto finally;
1061 }
1062 Tcl_IncrRefCount(objv[i]);
1063 }
1064 }
1065 *pobjc = objc;
1066 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001067finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 Tkapp_CallDeallocArgs(objv, objStore, objc);
1069 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001070}
Guido van Rossum212643f1998-04-29 16:22:14 +00001071
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001072/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001073
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001074static PyObject*
1075Tkapp_CallResult(TkappObject *self)
1076{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 PyObject *res = NULL;
1078 if(self->wantobjects) {
1079 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1080 /* Not sure whether the IncrRef is necessary, but something
1081 may overwrite the interpreter result while we are
1082 converting it. */
1083 Tcl_IncrRefCount(value);
1084 res = FromObj((PyObject*)self, value);
1085 Tcl_DecrRefCount(value);
1086 } else {
1087 const char *s = Tcl_GetStringResult(self->interp);
1088 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1091 }
1092 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001093}
Guido van Rossum632de272000-03-29 00:19:50 +00001094
Benjamin Peterson5879d412009-03-30 14:51:56 +00001095#ifdef WITH_THREAD
1096
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001097/* Tkapp_CallProc is the event procedure that is executed in the context of
1098 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1099 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001100
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101static int
1102Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1103{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001104 Tcl_Obj *objStore[ARGSZ];
1105 Tcl_Obj **objv;
1106 int objc;
1107 int i;
1108 ENTER_PYTHON
1109 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1110 if (!objv) {
1111 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1112 *(e->res) = NULL;
1113 }
1114 LEAVE_PYTHON
1115 if (!objv)
1116 goto done;
1117 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1118 ENTER_PYTHON
1119 if (i == TCL_ERROR) {
1120 *(e->res) = NULL;
1121 *(e->exc_type) = NULL;
1122 *(e->exc_tb) = NULL;
1123 *(e->exc_value) = PyObject_CallFunction(
1124 Tkinter_TclError, "s",
1125 Tcl_GetStringResult(e->self->interp));
1126 }
1127 else {
1128 *(e->res) = Tkapp_CallResult(e->self);
1129 }
1130 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001133done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 /* Wake up calling thread. */
1135 Tcl_MutexLock(&call_mutex);
1136 Tcl_ConditionNotify(e->done);
1137 Tcl_MutexUnlock(&call_mutex);
1138 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001139}
1140
Benjamin Peterson5879d412009-03-30 14:51:56 +00001141#endif
1142
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143/* This is the main entry point for calling a Tcl command.
1144 It supports three cases, with regard to threading:
1145 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1146 the context of the calling thread.
1147 2. Tcl is threaded, caller of the command is in the interpreter thread:
1148 Execute the command in the calling thread. Since the Tcl lock will
1149 not be used, we can merge that with case 1.
1150 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1151 the interpreter thread. Allocation of Tcl objects needs to occur in the
1152 interpreter thread, so we ship the PyObject* args to the target thread,
1153 and perform processing there. */
1154
1155static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001156Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001157{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001158 Tcl_Obj *objStore[ARGSZ];
1159 Tcl_Obj **objv = NULL;
1160 int objc, i;
1161 PyObject *res = NULL;
1162 TkappObject *self = (TkappObject*)selfptr;
1163 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001165 /* If args is a single tuple, replace with contents of tuple */
1166 if (1 == PyTuple_Size(args)){
1167 PyObject* item = PyTuple_GetItem(args, 0);
1168 if (PyTuple_Check(item))
1169 args = item;
1170 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001171#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1173 /* We cannot call the command directly. Instead, we must
1174 marshal the parameters to the interpreter thread. */
1175 Tkapp_CallEvent *ev;
1176 Tcl_Condition cond = NULL;
1177 PyObject *exc_type, *exc_value, *exc_tb;
1178 if (!WaitForMainloop(self))
1179 return NULL;
1180 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1181 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1182 ev->self = self;
1183 ev->args = args;
1184 ev->res = &res;
1185 ev->exc_type = &exc_type;
1186 ev->exc_value = &exc_value;
1187 ev->exc_tb = &exc_tb;
1188 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001192 if (res == NULL) {
1193 if (exc_type)
1194 PyErr_Restore(exc_type, exc_value, exc_tb);
1195 else
1196 PyErr_SetObject(Tkinter_TclError, exc_value);
1197 }
1198 Tcl_ConditionFinalize(&cond);
1199 }
1200 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001201#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001202 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001204 objv = Tkapp_CallArgs(args, objStore, &objc);
1205 if (!objv)
1206 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001210 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 if (i == TCL_ERROR)
1215 Tkinter_Error(selfptr);
1216 else
1217 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 Tkapp_CallDeallocArgs(objv, objStore, objc);
1222 }
1223 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001224}
1225
1226
1227static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001228Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001229{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001230 char *script;
1231 PyObject *res = NULL;
1232 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001234 if (!PyArg_ParseTuple(args, "s:eval", &script))
1235 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001236
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001237 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 ENTER_TCL
1240 err = Tcl_Eval(Tkapp_Interp(self), script);
1241 ENTER_OVERLAP
1242 if (err == TCL_ERROR)
1243 res = Tkinter_Error(self);
1244 else
1245 res = PyUnicode_FromString(Tkapp_Result(self));
1246 LEAVE_OVERLAP_TCL
1247 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001248}
1249
1250static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001251Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 char *fileName;
1254 PyObject *res = NULL;
1255 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1258 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001262 ENTER_TCL
1263 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1264 ENTER_OVERLAP
1265 if (err == TCL_ERROR)
1266 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 else
1269 res = PyUnicode_FromString(Tkapp_Result(self));
1270 LEAVE_OVERLAP_TCL
1271 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001272}
1273
1274static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001275Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001276{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001277 char *script;
1278 PyObject *res = NULL;
1279 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 if (!PyArg_ParseTuple(args, "s", &script))
1282 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 ENTER_TCL
1287 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1288 ENTER_OVERLAP
1289 if (err == TCL_ERROR)
1290 res = Tkinter_Error(self);
1291 else
1292 res = PyUnicode_FromString(Tkapp_Result(self));
1293 LEAVE_OVERLAP_TCL
1294 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001295}
1296
1297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001298Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001299{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001300 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001301
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001302 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1303 return NULL;
1304 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001306 ENTER_TCL
1307 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1308 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001309
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001310 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001311}
1312
Barry Warsawfa701a81997-01-16 00:15:11 +00001313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001314
Guido van Rossum18468821994-06-20 07:49:28 +00001315/** Tcl Variable **/
1316
Benjamin Peterson5879d412009-03-30 14:51:56 +00001317typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1318
1319#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320TCL_DECLARE_MUTEX(var_mutex)
1321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 Tcl_Event ev; /* must be first */
1324 PyObject *self;
1325 PyObject *args;
1326 int flags;
1327 EventFunc func;
1328 PyObject **res;
1329 PyObject **exc_type;
1330 PyObject **exc_val;
1331 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001333#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001335static int
1336varname_converter(PyObject *in, void *_out)
1337{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 char **out = (char**)_out;
1339 if (PyBytes_Check(in)) {
1340 *out = PyBytes_AsString(in);
1341 return 1;
1342 }
1343 if (PyUnicode_Check(in)) {
1344 *out = _PyUnicode_AsString(in);
1345 return 1;
1346 }
1347 if (PyTclObject_Check(in)) {
1348 *out = PyTclObject_TclString(in);
1349 return 1;
1350 }
1351 /* XXX: Should give diagnostics. */
1352 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001353}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001354
Benjamin Peterson5879d412009-03-30 14:51:56 +00001355#ifdef WITH_THREAD
1356
Martin v. Löwis59683e82008-06-13 07:50:45 +00001357static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001358var_perform(VarEvent *ev)
1359{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1361 if (!*(ev->res)) {
1362 PyObject *exc, *val, *tb;
1363 PyErr_Fetch(&exc, &val, &tb);
1364 PyErr_NormalizeException(&exc, &val, &tb);
1365 *(ev->exc_type) = exc;
1366 *(ev->exc_val) = val;
1367 Py_DECREF(tb);
1368 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001369
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001370}
1371
1372static int
1373var_proc(VarEvent* ev, int flags)
1374{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001375 ENTER_PYTHON
1376 var_perform(ev);
1377 Tcl_MutexLock(&var_mutex);
1378 Tcl_ConditionNotify(ev->cond);
1379 Tcl_MutexUnlock(&var_mutex);
1380 LEAVE_PYTHON
1381 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382}
1383
Benjamin Peterson5879d412009-03-30 14:51:56 +00001384#endif
1385
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001387var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001389#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 TkappObject *self = (TkappObject*)selfptr;
1391 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1392 TkappObject *self = (TkappObject*)selfptr;
1393 VarEvent *ev;
1394 PyObject *res, *exc_type, *exc_val;
1395 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 /* The current thread is not the interpreter thread. Marshal
1398 the call to the interpreter thread, then wait for
1399 completion. */
1400 if (!WaitForMainloop(self))
1401 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 ev->self = selfptr;
1406 ev->args = args;
1407 ev->flags = flags;
1408 ev->func = func;
1409 ev->res = &res;
1410 ev->exc_type = &exc_type;
1411 ev->exc_val = &exc_val;
1412 ev->cond = &cond;
1413 ev->ev.proc = (Tcl_EventProc*)var_proc;
1414 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1415 Tcl_ConditionFinalize(&cond);
1416 if (!res) {
1417 PyErr_SetObject(exc_type, exc_val);
1418 Py_DECREF(exc_type);
1419 Py_DECREF(exc_val);
1420 return NULL;
1421 }
1422 return res;
1423 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001424#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001425 /* Tcl is not threaded, or this is the interpreter thread. */
1426 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001427}
1428
Guido van Rossum18468821994-06-20 07:49:28 +00001429static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001430SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 char *name1, *name2;
1433 PyObject *newValue;
1434 PyObject *res = NULL;
1435 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 if (PyArg_ParseTuple(args, "O&O:setvar",
1438 varname_converter, &name1, &newValue)) {
1439 /* XXX Acquire tcl lock??? */
1440 newval = AsObj(newValue);
1441 if (newval == NULL)
1442 return NULL;
1443 ENTER_TCL
1444 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1445 newval, flags);
1446 ENTER_OVERLAP
1447 if (!ok)
1448 Tkinter_Error(self);
1449 else {
1450 res = Py_None;
1451 Py_INCREF(res);
1452 }
1453 LEAVE_OVERLAP_TCL
1454 }
1455 else {
1456 PyErr_Clear();
1457 if (PyArg_ParseTuple(args, "ssO:setvar",
1458 &name1, &name2, &newValue)) {
1459 /* XXX must hold tcl lock already??? */
1460 newval = AsObj(newValue);
1461 ENTER_TCL
1462 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1463 ENTER_OVERLAP
1464 if (!ok)
1465 Tkinter_Error(self);
1466 else {
1467 res = Py_None;
1468 Py_INCREF(res);
1469 }
1470 LEAVE_OVERLAP_TCL
1471 }
1472 else {
1473 return NULL;
1474 }
1475 }
1476 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001477}
1478
1479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001480Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001481{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001482 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001483}
1484
1485static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001486Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001487{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001489}
1490
Barry Warsawfa701a81997-01-16 00:15:11 +00001491
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001492
Guido van Rossum18468821994-06-20 07:49:28 +00001493static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001494GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001495{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 char *name1, *name2=NULL;
1497 PyObject *res = NULL;
1498 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1501 varname_converter, &name1, &name2))
1502 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 ENTER_TCL
1505 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1506 ENTER_OVERLAP
1507 if (tres == NULL) {
1508 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1509 } else {
1510 if (((TkappObject*)self)->wantobjects) {
1511 res = FromObj(self, tres);
1512 }
1513 else {
1514 res = PyUnicode_FromString(Tcl_GetString(tres));
1515 }
1516 }
1517 LEAVE_OVERLAP_TCL
1518 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001519}
1520
1521static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001522Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001523{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001525}
1526
1527static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001528Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001529{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001530 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001531}
1532
Barry Warsawfa701a81997-01-16 00:15:11 +00001533
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534
Guido van Rossum18468821994-06-20 07:49:28 +00001535static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001536UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001537{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 char *name1, *name2=NULL;
1539 int code;
1540 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001541
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1543 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 ENTER_TCL
1546 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1547 ENTER_OVERLAP
1548 if (code == TCL_ERROR)
1549 res = Tkinter_Error(self);
1550 else {
1551 Py_INCREF(Py_None);
1552 res = Py_None;
1553 }
1554 LEAVE_OVERLAP_TCL
1555 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001556}
1557
1558static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001559Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001560{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001561 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001562}
1563
1564static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001565Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001568}
1569
Barry Warsawfa701a81997-01-16 00:15:11 +00001570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571
Guido van Rossum18468821994-06-20 07:49:28 +00001572/** Tcl to Python **/
1573
1574static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001575Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001576{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001577 char *s;
1578 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001580 if (PyTuple_Size(args) == 1) {
1581 PyObject* o = PyTuple_GetItem(args, 0);
1582 if (PyLong_Check(o)) {
1583 Py_INCREF(o);
1584 return o;
1585 }
1586 }
1587 if (!PyArg_ParseTuple(args, "s:getint", &s))
1588 return NULL;
1589 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1590 return Tkinter_Error(self);
1591 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001592}
1593
1594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001595Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001596{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001597 char *s;
1598 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 if (PyTuple_Size(args) == 1) {
1601 PyObject *o = PyTuple_GetItem(args, 0);
1602 if (PyFloat_Check(o)) {
1603 Py_INCREF(o);
1604 return o;
1605 }
1606 }
1607 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1608 return NULL;
1609 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1610 return Tkinter_Error(self);
1611 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001612}
1613
1614static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001615Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001616{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001617 char *s;
1618 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620 if (PyTuple_Size(args) == 1) {
1621 PyObject *o = PyTuple_GetItem(args, 0);
1622 if (PyLong_Check(o)) {
1623 Py_INCREF(o);
1624 return o;
1625 }
1626 }
1627 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1628 return NULL;
1629 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1630 return Tkinter_Error(self);
1631 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001632}
1633
1634static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001635Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001636{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 char *s;
1638 PyObject *res = NULL;
1639 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001641 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1642 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001643
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001644 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001646 ENTER_TCL
1647 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1648 ENTER_OVERLAP
1649 if (retval == TCL_ERROR)
1650 res = Tkinter_Error(self);
1651 else
1652 res = Py_BuildValue("s", Tkapp_Result(self));
1653 LEAVE_OVERLAP_TCL
1654 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
1657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 char *s;
1661 PyObject *res = NULL;
1662 int retval;
1663 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001664
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1666 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001670 ENTER_TCL
1671 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1672 ENTER_OVERLAP
1673 if (retval == TCL_ERROR)
1674 res = Tkinter_Error(self);
1675 else
1676 res = Py_BuildValue("l", v);
1677 LEAVE_OVERLAP_TCL
1678 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001679}
1680
1681static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001682Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001683{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001684 char *s;
1685 PyObject *res = NULL;
1686 double v;
1687 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001689 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1690 return NULL;
1691 CHECK_TCL_APPARTMENT;
1692 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1693 ENTER_TCL
1694 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1695 ENTER_OVERLAP
1696 PyFPE_END_PROTECT(retval)
1697 if (retval == TCL_ERROR)
1698 res = Tkinter_Error(self);
1699 else
1700 res = Py_BuildValue("d", v);
1701 LEAVE_OVERLAP_TCL
1702 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
1705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001706Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001707{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 char *s;
1709 PyObject *res = NULL;
1710 int retval;
1711 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001713 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1714 return NULL;
1715 CHECK_TCL_APPARTMENT;
1716 ENTER_TCL
1717 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1718 ENTER_OVERLAP
1719 if (retval == TCL_ERROR)
1720 res = Tkinter_Error(self);
1721 else
1722 res = Py_BuildValue("i", v);
1723 LEAVE_OVERLAP_TCL
1724 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
Barry Warsawfa701a81997-01-16 00:15:11 +00001727
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001728
Guido van Rossum18468821994-06-20 07:49:28 +00001729static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001730Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001731{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001732 char *list;
1733 int argc;
1734 char **argv;
1735 PyObject *v;
1736 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001738 if (PyTuple_Size(args) == 1) {
1739 v = PyTuple_GetItem(args, 0);
1740 if (PyTuple_Check(v)) {
1741 Py_INCREF(v);
1742 return v;
1743 }
1744 }
1745 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1746 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001747
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001748 if (Tcl_SplitList(Tkapp_Interp(self), list,
1749 &argc, &argv) == TCL_ERROR) {
1750 PyMem_Free(list);
1751 return Tkinter_Error(self);
1752 }
Guido van Rossum18468821994-06-20 07:49:28 +00001753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001754 if (!(v = PyTuple_New(argc)))
1755 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001757 for (i = 0; i < argc; i++) {
1758 PyObject *s = PyUnicode_FromString(argv[i]);
1759 if (!s || PyTuple_SetItem(v, i, s)) {
1760 Py_DECREF(v);
1761 v = NULL;
1762 goto finally;
1763 }
1764 }
Guido van Rossum18468821994-06-20 07:49:28 +00001765
Barry Warsawfa701a81997-01-16 00:15:11 +00001766 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 ckfree(FREECAST argv);
1768 PyMem_Free(list);
1769 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 PyObject *v;
1776 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001778 if (PyTuple_Size(args) == 1) {
1779 PyObject* o = PyTuple_GetItem(args, 0);
1780 if (PyTuple_Check(o)) {
1781 o = SplitObj(o);
1782 return o;
1783 }
1784 }
1785 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1786 return NULL;
1787 v = Split(list);
1788 PyMem_Free(list);
1789 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001790}
1791
Barry Warsawfa701a81997-01-16 00:15:11 +00001792
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793
Guido van Rossum18468821994-06-20 07:49:28 +00001794/** Tcl Command **/
1795
Guido van Rossum00d93061998-05-28 23:06:38 +00001796/* Client data struct */
1797typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001798 PyObject *self;
1799 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001800} PythonCmd_ClientData;
1801
1802static int
Fred Drake509d79a2000-07-08 04:04:38 +00001803PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001804{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001805 errorInCmd = 1;
1806 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1807 LEAVE_PYTHON
1808 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001809}
1810
Guido van Rossum18468821994-06-20 07:49:28 +00001811/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001812 * function or method.
1813 */
Guido van Rossum18468821994-06-20 07:49:28 +00001814static int
Fred Drake509d79a2000-07-08 04:04:38 +00001815PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00001818 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 int i, rv;
1820 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 /* TBD: no error checking here since we know, via the
1825 * Tkapp_CreateCommand() that the client data is a two-tuple
1826 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001827 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 /* Create argument list (argv1, ..., argvN) */
1830 if (!(arg = PyTuple_New(argc - 1)))
1831 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001833 for (i = 0; i < (argc - 1); i++) {
1834 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04001835 if (!s) {
1836 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
1837 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
1838 !strcmp(argv[i + 1], "\xC0\x80")) {
1839 PyErr_Clear();
1840 /* Convert to "strict" utf-8 null */
1841 s = PyUnicode_FromString("\0");
1842 } else {
1843 Py_DECREF(arg);
1844 return PythonCmd_Error(interp);
1845 }
1846 }
1847 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848 Py_DECREF(arg);
1849 return PythonCmd_Error(interp);
1850 }
1851 }
1852 res = PyEval_CallObject(func, arg);
1853 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001854
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001855 if (res == NULL)
1856 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001857
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001858 obj_res = AsObj(res);
1859 if (obj_res == NULL) {
1860 Py_DECREF(res);
1861 return PythonCmd_Error(interp);
1862 }
1863 else {
1864 Tcl_SetObjResult(interp, obj_res);
1865 rv = TCL_OK;
1866 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001867
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001870 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001872 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001873}
1874
1875static void
Fred Drake509d79a2000-07-08 04:04:38 +00001876PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001877{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001878 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00001879
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 ENTER_PYTHON
1881 Py_XDECREF(data->self);
1882 Py_XDECREF(data->func);
1883 PyMem_DEL(data);
1884 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
Barry Warsawfa701a81997-01-16 00:15:11 +00001887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001889
Benjamin Peterson5879d412009-03-30 14:51:56 +00001890#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001891TCL_DECLARE_MUTEX(command_mutex)
1892
1893typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001894 Tcl_Event ev;
1895 Tcl_Interp* interp;
1896 char *name;
1897 int create;
1898 int *status;
1899 ClientData *data;
1900 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001901} CommandEvent;
1902
1903static int
1904Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001905{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906 if (ev->create)
1907 *ev->status = Tcl_CreateCommand(
1908 ev->interp, ev->name, PythonCmd,
1909 ev->data, PythonCmdDelete) == NULL;
1910 else
1911 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1912 Tcl_MutexLock(&command_mutex);
1913 Tcl_ConditionNotify(ev->done);
1914 Tcl_MutexUnlock(&command_mutex);
1915 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001916}
Benjamin Peterson5879d412009-03-30 14:51:56 +00001917#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001918
1919static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001920Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001921{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001922 TkappObject *self = (TkappObject*)selfptr;
1923 PythonCmd_ClientData *data;
1924 char *cmdName;
1925 PyObject *func;
1926 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00001927
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001928 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1929 return NULL;
1930 if (!PyCallable_Check(func)) {
1931 PyErr_SetString(PyExc_TypeError, "command not callable");
1932 return NULL;
1933 }
Guido van Rossum18468821994-06-20 07:49:28 +00001934
Martin v. Löwisa9656492003-03-30 08:44:58 +00001935#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001936 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1937 !WaitForMainloop(self))
1938 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001939#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001940
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001941 data = PyMem_NEW(PythonCmd_ClientData, 1);
1942 if (!data)
1943 return PyErr_NoMemory();
1944 Py_INCREF(self);
1945 Py_INCREF(func);
1946 data->self = selfptr;
1947 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001948#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001949 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1950 Tcl_Condition cond = NULL;
1951 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1952 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1953 ev->interp = self->interp;
1954 ev->create = 1;
1955 ev->name = cmdName;
1956 ev->data = (ClientData)data;
1957 ev->status = &err;
1958 ev->done = &cond;
1959 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
1960 Tcl_ConditionFinalize(&cond);
1961 }
1962 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00001963#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 {
1965 ENTER_TCL
1966 err = Tcl_CreateCommand(
1967 Tkapp_Interp(self), cmdName, PythonCmd,
1968 (ClientData)data, PythonCmdDelete) == NULL;
1969 LEAVE_TCL
1970 }
1971 if (err) {
1972 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1973 PyMem_DEL(data);
1974 return NULL;
1975 }
Guido van Rossum18468821994-06-20 07:49:28 +00001976
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001977 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001978}
1979
Barry Warsawfa701a81997-01-16 00:15:11 +00001980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981
Guido van Rossum18468821994-06-20 07:49:28 +00001982static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001983Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 TkappObject *self = (TkappObject*)selfptr;
1986 char *cmdName;
1987 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1990 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001991
1992#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1994 Tcl_Condition cond = NULL;
1995 CommandEvent *ev;
1996 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
1997 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
1998 ev->interp = self->interp;
1999 ev->create = 0;
2000 ev->name = cmdName;
2001 ev->status = &err;
2002 ev->done = &cond;
2003 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2004 &command_mutex);
2005 Tcl_ConditionFinalize(&cond);
2006 }
2007 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002008#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 {
2010 ENTER_TCL
2011 err = Tcl_DeleteCommand(self->interp, cmdName);
2012 LEAVE_TCL
2013 }
2014 if (err == -1) {
2015 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2016 return NULL;
2017 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002018 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002019}
2020
Barry Warsawfa701a81997-01-16 00:15:11 +00002021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022
Guido van Rossum00d93061998-05-28 23:06:38 +00002023#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002024/** File Handler **/
2025
Guido van Rossum00d93061998-05-28 23:06:38 +00002026typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002027 PyObject *func;
2028 PyObject *file;
2029 int id;
2030 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002031} FileHandler_ClientData;
2032
2033static FileHandler_ClientData *HeadFHCD;
2034
2035static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002036NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 FileHandler_ClientData *p;
2039 p = PyMem_NEW(FileHandler_ClientData, 1);
2040 if (p != NULL) {
2041 Py_XINCREF(func);
2042 Py_XINCREF(file);
2043 p->func = func;
2044 p->file = file;
2045 p->id = id;
2046 p->next = HeadFHCD;
2047 HeadFHCD = p;
2048 }
2049 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002050}
2051
2052static void
Fred Drake509d79a2000-07-08 04:04:38 +00002053DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002054{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002057 pp = &HeadFHCD;
2058 while ((p = *pp) != NULL) {
2059 if (p->id == id) {
2060 *pp = p->next;
2061 Py_XDECREF(p->func);
2062 Py_XDECREF(p->file);
2063 PyMem_DEL(p);
2064 }
2065 else
2066 pp = &p->next;
2067 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002068}
2069
Guido van Rossuma597dde1995-01-10 20:56:29 +00002070static void
Fred Drake509d79a2000-07-08 04:04:38 +00002071FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002072{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2074 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002076 ENTER_PYTHON
2077 func = data->func;
2078 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 arg = Py_BuildValue("(Oi)", file, (long) mask);
2081 res = PyEval_CallObject(func, arg);
2082 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002084 if (res == NULL) {
2085 errorInCmd = 1;
2086 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2087 }
2088 Py_XDECREF(res);
2089 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002090}
2091
Guido van Rossum18468821994-06-20 07:49:28 +00002092static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002093Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2094 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002095{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 FileHandler_ClientData *data;
2097 PyObject *file, *func;
2098 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002099
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002100 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2101 &file, &mask, &func))
2102 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002105
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 tfile = PyObject_AsFileDescriptor(file);
2107 if (tfile < 0)
2108 return NULL;
2109 if (!PyCallable_Check(func)) {
2110 PyErr_SetString(PyExc_TypeError, "bad argument list");
2111 return NULL;
2112 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 data = NewFHCD(func, file, tfile);
2115 if (data == NULL)
2116 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002118 /* Ought to check for null Tcl_File object... */
2119 ENTER_TCL
2120 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2121 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002122 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002123}
2124
2125static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002126Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002128 PyObject *file;
2129 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002131 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2132 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 tfile = PyObject_AsFileDescriptor(file);
2137 if (tfile < 0)
2138 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 /* Ought to check for null Tcl_File object... */
2143 ENTER_TCL
2144 Tcl_DeleteFileHandler(tfile);
2145 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002146 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002148#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002151/**** Tktt Object (timer token) ****/
2152
Jeremy Hylton938ace62002-07-17 16:30:39 +00002153static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002154
Guido van Rossum00d93061998-05-28 23:06:38 +00002155typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002156 PyObject_HEAD
2157 Tcl_TimerToken token;
2158 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002159} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002160
2161static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002162Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002163{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164 TkttObject *v = (TkttObject *)self;
2165 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002166
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002167 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2168 return NULL;
2169 if (v->token != NULL) {
2170 Tcl_DeleteTimerHandler(v->token);
2171 v->token = NULL;
2172 }
2173 if (func != NULL) {
2174 v->func = NULL;
2175 Py_DECREF(func);
2176 Py_DECREF(v); /* See Tktt_New() */
2177 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002178 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002179}
2180
2181static PyMethodDef Tktt_methods[] =
2182{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2184 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002185};
2186
2187static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002188Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002189{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 v = PyObject_New(TkttObject, &Tktt_Type);
2193 if (v == NULL)
2194 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002195
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002196 Py_INCREF(func);
2197 v->token = NULL;
2198 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 /* Extra reference, deleted when called or when handler is deleted */
2201 Py_INCREF(v);
2202 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002203}
2204
2205static void
Fred Drake509d79a2000-07-08 04:04:38 +00002206Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002207{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 TkttObject *v = (TkttObject *)self;
2209 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002211 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002213 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002214}
2215
Guido van Rossum597ac201998-05-12 14:36:19 +00002216static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002217Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002218{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002219 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002220 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2221 v,
2222 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002223}
2224
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002225static PyTypeObject Tktt_Type =
2226{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 PyVarObject_HEAD_INIT(NULL, 0)
2228 "tktimertoken", /*tp_name */
2229 sizeof(TkttObject), /*tp_basicsize */
2230 0, /*tp_itemsize */
2231 Tktt_Dealloc, /*tp_dealloc */
2232 0, /*tp_print */
2233 0, /*tp_getattr */
2234 0, /*tp_setattr */
2235 0, /*tp_reserved */
2236 Tktt_Repr, /*tp_repr */
2237 0, /*tp_as_number */
2238 0, /*tp_as_sequence */
2239 0, /*tp_as_mapping */
2240 0, /*tp_hash */
2241 0, /*tp_call*/
2242 0, /*tp_str*/
2243 0, /*tp_getattro*/
2244 0, /*tp_setattro*/
2245 0, /*tp_as_buffer*/
2246 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2247 0, /*tp_doc*/
2248 0, /*tp_traverse*/
2249 0, /*tp_clear*/
2250 0, /*tp_richcompare*/
2251 0, /*tp_weaklistoffset*/
2252 0, /*tp_iter*/
2253 0, /*tp_iternext*/
2254 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002255};
2256
Barry Warsawfa701a81997-01-16 00:15:11 +00002257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002258
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002259/** Timer Handler **/
2260
2261static void
Fred Drake509d79a2000-07-08 04:04:38 +00002262TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 TkttObject *v = (TkttObject *)clientData;
2265 PyObject *func = v->func;
2266 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 if (func == NULL)
2269 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 res = PyEval_CallObject(func, NULL);
2276 Py_DECREF(func);
2277 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 if (res == NULL) {
2280 errorInCmd = 1;
2281 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2282 }
2283 else
2284 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002287}
2288
2289static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002290Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002291{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002292 int milliseconds;
2293 PyObject *func;
2294 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2297 &milliseconds, &func))
2298 return NULL;
2299 if (!PyCallable_Check(func)) {
2300 PyErr_SetString(PyExc_TypeError, "bad argument list");
2301 return NULL;
2302 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002303
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002304 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002305
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002306 v = Tktt_New(func);
2307 if (v) {
2308 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2309 (ClientData)v);
2310 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002311
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002312 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002313}
2314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002315
Guido van Rossum18468821994-06-20 07:49:28 +00002316/** Event Loop **/
2317
Guido van Rossum18468821994-06-20 07:49:28 +00002318static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002319Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002320{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002321 int threshold = 0;
2322 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002323#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002325#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2328 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 CHECK_TCL_APPARTMENT;
2331 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 quitMainLoop = 0;
2334 while (Tk_GetNumMainWindows() > threshold &&
2335 !quitMainLoop &&
2336 !errorInCmd)
2337 {
2338 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002339
2340#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002341 if (self->threaded) {
2342 /* Allow other Python threads to run. */
2343 ENTER_TCL
2344 result = Tcl_DoOneEvent(0);
2345 LEAVE_TCL
2346 }
2347 else {
2348 Py_BEGIN_ALLOW_THREADS
2349 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2350 tcl_tstate = tstate;
2351 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2352 tcl_tstate = NULL;
2353 if(tcl_lock)PyThread_release_lock(tcl_lock);
2354 if (result == 0)
2355 Sleep(Tkinter_busywaitinterval);
2356 Py_END_ALLOW_THREADS
2357 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002358#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002360#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 if (PyErr_CheckSignals() != 0) {
2363 self->dispatching = 0;
2364 return NULL;
2365 }
2366 if (result < 0)
2367 break;
2368 }
2369 self->dispatching = 0;
2370 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002372 if (errorInCmd) {
2373 errorInCmd = 0;
2374 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2375 excInCmd = valInCmd = trbInCmd = NULL;
2376 return NULL;
2377 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002378 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002379}
2380
2381static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002382Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002384 int flags = 0;
2385 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2388 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 ENTER_TCL
2391 rv = Tcl_DoOneEvent(flags);
2392 LEAVE_TCL
2393 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002394}
2395
2396static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002397Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002398{
2399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002400 if (!PyArg_ParseTuple(args, ":quit"))
2401 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002403 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002404 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002405}
2406
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002407static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002408Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002409{
2410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 if (!PyArg_ParseTuple(args, ":interpaddr"))
2412 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002414 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002415}
2416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002418Tkapp_TkInit(PyObject *self, PyObject *args)
2419{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 Tcl_Interp *interp = Tkapp_Interp(self);
2421 const char * _tk_exists = NULL;
2422 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002423
Guilherme Polob681df42009-02-09 22:33:59 +00002424#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2426 * first call failed.
2427 * To avoid the deadlock, we just refuse the second call through
2428 * a static variable.
2429 */
2430 if (tk_load_failed) {
2431 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2432 return NULL;
2433 }
Guilherme Polob681df42009-02-09 22:33:59 +00002434#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 /* We want to guard against calling Tk_Init() multiple times */
2437 CHECK_TCL_APPARTMENT;
2438 ENTER_TCL
2439 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2440 ENTER_OVERLAP
2441 if (err == TCL_ERROR) {
2442 /* This sets an exception, but we cannot return right
2443 away because we need to exit the overlap first. */
2444 Tkinter_Error(self);
2445 } else {
2446 _tk_exists = Tkapp_Result(self);
2447 }
2448 LEAVE_OVERLAP_TCL
2449 if (err == TCL_ERROR) {
2450 return NULL;
2451 }
2452 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2453 if (Tk_Init(interp) == TCL_ERROR) {
2454 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002455#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002457#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458 return NULL;
2459 }
2460 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002461 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002462}
Barry Warsawfa701a81997-01-16 00:15:11 +00002463
Martin v. Löwisffad6332002-11-26 09:28:05 +00002464static PyObject *
2465Tkapp_WantObjects(PyObject *self, PyObject *args)
2466{
2467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 int wantobjects = -1;
2469 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2470 return NULL;
2471 if (wantobjects == -1)
2472 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2473 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002474
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002475 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002476}
2477
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002478static PyObject *
2479Tkapp_WillDispatch(PyObject *self, PyObject *args)
2480{
2481
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002482 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002483
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002484 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002485}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002487
Guido van Rossum18468821994-06-20 07:49:28 +00002488/**** Tkapp Method List ****/
2489
2490static PyMethodDef Tkapp_methods[] =
2491{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2493 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2494 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002495 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2497 {"record", Tkapp_Record, METH_VARARGS},
2498 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2499 {"setvar", Tkapp_SetVar, METH_VARARGS},
2500 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2501 {"getvar", Tkapp_GetVar, METH_VARARGS},
2502 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2503 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2504 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2505 {"getint", Tkapp_GetInt, METH_VARARGS},
2506 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2507 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2508 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2509 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2510 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2511 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2512 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2513 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002514 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2515 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002516#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2518 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002519#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2521 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2522 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2523 {"quit", Tkapp_Quit, METH_VARARGS},
2524 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2525 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2526 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002527};
2528
Barry Warsawfa701a81997-01-16 00:15:11 +00002529
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002530
Guido van Rossum18468821994-06-20 07:49:28 +00002531/**** Tkapp Type Methods ****/
2532
2533static void
Fred Drake509d79a2000-07-08 04:04:38 +00002534Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002535{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 /*CHECK_TCL_APPARTMENT;*/
2537 ENTER_TCL
2538 Tcl_DeleteInterp(Tkapp_Interp(self));
2539 LEAVE_TCL
2540 PyObject_Del(self);
2541 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002542}
2543
Guido van Rossum18468821994-06-20 07:49:28 +00002544static PyTypeObject Tkapp_Type =
2545{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002546 PyVarObject_HEAD_INIT(NULL, 0)
2547 "tkapp", /*tp_name */
2548 sizeof(TkappObject), /*tp_basicsize */
2549 0, /*tp_itemsize */
2550 Tkapp_Dealloc, /*tp_dealloc */
2551 0, /*tp_print */
2552 0, /*tp_getattr */
2553 0, /*tp_setattr */
2554 0, /*tp_reserved */
2555 0, /*tp_repr */
2556 0, /*tp_as_number */
2557 0, /*tp_as_sequence */
2558 0, /*tp_as_mapping */
2559 0, /*tp_hash */
2560 0, /*tp_call*/
2561 0, /*tp_str*/
2562 0, /*tp_getattro*/
2563 0, /*tp_setattro*/
2564 0, /*tp_as_buffer*/
2565 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2566 0, /*tp_doc*/
2567 0, /*tp_traverse*/
2568 0, /*tp_clear*/
2569 0, /*tp_richcompare*/
2570 0, /*tp_weaklistoffset*/
2571 0, /*tp_iter*/
2572 0, /*tp_iternext*/
2573 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002574};
2575
Barry Warsawfa701a81997-01-16 00:15:11 +00002576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577
Guido van Rossum18468821994-06-20 07:49:28 +00002578/**** Tkinter Module ****/
2579
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002580typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002581 PyObject* tuple;
2582 int size; /* current size */
2583 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002584} FlattenContext;
2585
2586static int
2587_bump(FlattenContext* context, int size)
2588{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 /* expand tuple to hold (at least) size new items.
2590 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 if (maxsize < context->size + size)
2595 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002596
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002597 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002600}
2601
2602static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002603_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002604{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002605 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002607 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002609 if (depth > 1000) {
2610 PyErr_SetString(PyExc_ValueError,
2611 "nesting too deep in _flatten");
2612 return 0;
2613 } else if (PyList_Check(item)) {
2614 size = PyList_GET_SIZE(item);
2615 /* preallocate (assume no nesting) */
2616 if (context->size + size > context->maxsize &&
2617 !_bump(context, size))
2618 return 0;
2619 /* copy items to output tuple */
2620 for (i = 0; i < size; i++) {
2621 PyObject *o = PyList_GET_ITEM(item, i);
2622 if (PyList_Check(o) || PyTuple_Check(o)) {
2623 if (!_flatten1(context, o, depth + 1))
2624 return 0;
2625 } else if (o != Py_None) {
2626 if (context->size + 1 > context->maxsize &&
2627 !_bump(context, 1))
2628 return 0;
2629 Py_INCREF(o);
2630 PyTuple_SET_ITEM(context->tuple,
2631 context->size++, o);
2632 }
2633 }
2634 } else if (PyTuple_Check(item)) {
2635 /* same, for tuples */
2636 size = PyTuple_GET_SIZE(item);
2637 if (context->size + size > context->maxsize &&
2638 !_bump(context, size))
2639 return 0;
2640 for (i = 0; i < size; i++) {
2641 PyObject *o = PyTuple_GET_ITEM(item, i);
2642 if (PyList_Check(o) || PyTuple_Check(o)) {
2643 if (!_flatten1(context, o, depth + 1))
2644 return 0;
2645 } else if (o != Py_None) {
2646 if (context->size + 1 > context->maxsize &&
2647 !_bump(context, 1))
2648 return 0;
2649 Py_INCREF(o);
2650 PyTuple_SET_ITEM(context->tuple,
2651 context->size++, o);
2652 }
2653 }
2654 } else {
2655 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2656 return 0;
2657 }
2658 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002659}
2660
2661static PyObject *
2662Tkinter_Flatten(PyObject* self, PyObject* args)
2663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002664 FlattenContext context;
2665 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2668 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670 context.maxsize = PySequence_Size(item);
2671 if (context.maxsize < 0)
2672 return NULL;
2673 if (context.maxsize == 0)
2674 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 context.tuple = PyTuple_New(context.maxsize);
2677 if (!context.tuple)
2678 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002680 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 if (!_flatten1(&context, item,0))
2683 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 if (_PyTuple_Resize(&context.tuple, context.size))
2686 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002689}
2690
Guido van Rossum18468821994-06-20 07:49:28 +00002691static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002692Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002693{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002694 char *screenName = NULL;
2695 char *baseName = NULL; /* XXX this is not used anymore;
2696 try getting rid of it. */
2697 char *className = NULL;
2698 int interactive = 0;
2699 int wantobjects = 0;
2700 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2701 int sync = 0; /* pass -sync to wish */
2702 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002704 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002706 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2707 &screenName, &baseName, &className,
2708 &interactive, &wantobjects, &wantTk,
2709 &sync, &use))
2710 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002712 return (PyObject *) Tkapp_New(screenName, className,
2713 interactive, wantobjects, wantTk,
2714 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002715}
2716
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002717static PyObject *
2718Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 int new_val;
2721 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2722 return NULL;
2723 if (new_val < 0) {
2724 PyErr_SetString(PyExc_ValueError,
2725 "busywaitinterval must be >= 0");
2726 return NULL;
2727 }
2728 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002729 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002730}
2731
2732static char setbusywaitinterval_doc[] =
2733"setbusywaitinterval(n) -> None\n\
2734\n\
2735Set the busy-wait interval in milliseconds between successive\n\
2736calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2737It should be set to a divisor of the maximum time between\n\
2738frames in an animation.";
2739
2740static PyObject *
2741Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002743 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002744}
2745
2746static char getbusywaitinterval_doc[] =
2747"getbusywaitinterval() -> int\n\
2748\n\
2749Return the current busy-wait interval between successive\n\
2750calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2751
Guido van Rossum18468821994-06-20 07:49:28 +00002752static PyMethodDef moduleMethods[] =
2753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2755 {"create", Tkinter_Create, METH_VARARGS},
2756 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2757 setbusywaitinterval_doc},
2758 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2759 METH_NOARGS, getbusywaitinterval_doc},
2760 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002761};
2762
Guido van Rossum7bf15641998-05-22 18:28:17 +00002763#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002764
2765static int stdin_ready = 0;
2766
Guido van Rossumad4db171998-06-13 13:56:28 +00002767#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002768static void
Fred Drake509d79a2000-07-08 04:04:38 +00002769MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002770{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002771 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002772}
Guido van Rossumad4db171998-06-13 13:56:28 +00002773#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002774
Martin v. Löwisa9656492003-03-30 08:44:58 +00002775#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002776static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002777#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002778
Guido van Rossum18468821994-06-20 07:49:28 +00002779static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002780EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002781{
Guido van Rossumad4db171998-06-13 13:56:28 +00002782#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002784#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002785#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002787#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002788 stdin_ready = 0;
2789 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002790#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 tfile = fileno(stdin);
2792 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002793#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002794 while (!errorInCmd && !stdin_ready) {
2795 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002796#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 if (_kbhit()) {
2798 stdin_ready = 1;
2799 break;
2800 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002801#endif
2802#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 Py_BEGIN_ALLOW_THREADS
2804 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2805 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002808
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002809 tcl_tstate = NULL;
2810 if(tcl_lock)PyThread_release_lock(tcl_lock);
2811 if (result == 0)
2812 Sleep(Tkinter_busywaitinterval);
2813 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00002814#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002816#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002817
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002818 if (result < 0)
2819 break;
2820 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002821#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002822 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002823#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 if (errorInCmd) {
2825 errorInCmd = 0;
2826 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2827 excInCmd = valInCmd = trbInCmd = NULL;
2828 PyErr_Print();
2829 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002830#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002831 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002832#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002833 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002834}
Guido van Rossum18468821994-06-20 07:49:28 +00002835
Guido van Rossum00d93061998-05-28 23:06:38 +00002836#endif
2837
Guido van Rossum7bf15641998-05-22 18:28:17 +00002838static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002839EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002840{
Guido van Rossum00d93061998-05-28 23:06:38 +00002841#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002843#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002844 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002845#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 PyOS_InputHook = EventHook;
2847 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002848#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002849}
2850
2851static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002852DisableEventHook(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 (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2856 PyOS_InputHook = NULL;
2857 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002858#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002859}
2860
Barry Warsawfa701a81997-01-16 00:15:11 +00002861
Martin v. Löwis1a214512008-06-11 05:26:20 +00002862static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 PyModuleDef_HEAD_INIT,
2864 "_tkinter",
2865 NULL,
2866 -1,
2867 moduleMethods,
2868 NULL,
2869 NULL,
2870 NULL,
2871 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00002872};
2873
Mark Hammond62b1ab12002-07-23 06:31:15 +00002874PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00002875PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002876{
Andrew Svetlov885dc282012-10-07 12:30:51 +03002877 PyObject *m, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00002878
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002879 if (PyType_Ready(&Tkapp_Type) < 0)
2880 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002881
2882#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00002884#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00002885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886 m = PyModule_Create(&_tkintermodule);
2887 if (m == NULL)
2888 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Andrew Svetlov885dc282012-10-07 12:30:51 +03002891 Py_INCREF(Tkinter_TclError);
2892 PyModule_AddObject(m, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00002893
Andrew Svetlov885dc282012-10-07 12:30:51 +03002894 PyModule_AddIntConstant(m, "READABLE", TCL_READABLE);
2895 PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE);
2896 PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION);
2897 PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2898 PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS);
2899 PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2900 PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2901 PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS);
2902 PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT);
2903 PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION);
2904 PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00002905
Andrew Svetlov885dc282012-10-07 12:30:51 +03002906 PyModule_AddObject(m, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00002907
Jesus Ceaef86d122012-07-19 21:18:07 +02002908 if (PyType_Ready(&Tktt_Type) < 0) {
2909 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02002911 }
Andrew Svetlov885dc282012-10-07 12:30:51 +03002912 PyModule_AddObject(m, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00002913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
Andrew Svetlov885dc282012-10-07 12:30:51 +03002915 PyModule_AddObject(m, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00002916
2917#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2919 * start waking up. Note that Tcl_FindExecutable will do this, this
2920 * code must be above it! The original warning from
2921 * tkMacOSXAppInit.c is copied below.
2922 *
2923 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2924 * Tcl interpreter for now. It probably should work to do this
2925 * in the other order, but for now it doesn't seem to.
2926 *
2927 */
2928 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00002929#endif
2930
2931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 /* This helps the dynamic loader; in Unicode aware Tcl versions
2933 it also helps Tcl find its encodings. */
2934 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
2935 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00002936 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 if (cexe)
2938 Tcl_FindExecutable(PyBytes_AsString(cexe));
2939 Py_XDECREF(cexe);
2940 Py_DECREF(uexe);
2941 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00002942
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002943 if (PyErr_Occurred()) {
2944 Py_DECREF(m);
2945 return NULL;
2946 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00002947
Guido van Rossum43ff8681998-07-14 18:02:13 +00002948#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002949 /* This was not a good idea; through <Destroy> bindings,
2950 Tcl_Finalize() may invoke Python code but at that point the
2951 interpreter and thread state have already been destroyed! */
2952 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00002953#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002954 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00002955}