blob: 3608e2d993a26d72dd1ddadd1048018cb2521796 [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
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Guido van Rossum82c0dfa2007-11-21 20:09:18 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000088 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000208
209#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219
220#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Christian Heimes90aa7642007-12-19 02:45:37 +0000265#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000270(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Guilherme Polob681df42009-02-09 22:33:59 +0000283#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000284static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000285#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287
Guido van Rossum18468821994-06-20 07:49:28 +0000288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000289Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000293}
294
Barry Warsawfa701a81997-01-16 00:15:11 +0000295
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000296
Guido van Rossum18468821994-06-20 07:49:28 +0000297/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000298
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000299static int Tkinter_busywaitinterval = 20;
300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000303
Guido van Rossum00d93061998-05-28 23:06:38 +0000304/* Millisecond sleep() for Unix platforms. */
305
306static void
Fred Drake509d79a2000-07-08 04:04:38 +0000307Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000308{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
311 t.tv_sec = milli/1000;
312 t.tv_usec = (milli%1000) * 1000;
313 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000314}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000315#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000316
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000317/* Wait up to 1s for the mainloop to come up. */
318
319static int
320WaitForMainloop(TkappObject* self)
321{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
329 }
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000334}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000335#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337
Guido van Rossum18468821994-06-20 07:49:28 +0000338static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000339AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 if (PyBytes_Check(value))
342 return PyBytes_AsString(value);
343 else if (PyUnicode_Check(value)) {
344 PyObject *v = PyUnicode_AsUTF8String(value);
345 if (v == NULL)
346 return NULL;
347 if (PyList_Append(tmp, v) != 0) {
348 Py_DECREF(v);
349 return NULL;
350 }
351 Py_DECREF(v);
352 return PyBytes_AsString(v);
353 }
354 else {
355 PyObject *v = PyObject_Str(value);
356 if (v == NULL)
357 return NULL;
358 if (PyList_Append(tmp, v) != 0) {
359 Py_DECREF(v);
360 return NULL;
361 }
362 Py_DECREF(v);
363 return PyBytes_AsString(v);
364 }
Guido van Rossum18468821994-06-20 07:49:28 +0000365}
366
Barry Warsawfa701a81997-01-16 00:15:11 +0000367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368
Guido van Rossum18468821994-06-20 07:49:28 +0000369#define ARGSZ 64
370
371static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000372Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000373{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 PyObject *tmp = NULL;
375 char *argvStore[ARGSZ];
376 char **argv = NULL;
377 int fvStore[ARGSZ];
378 int *fv = NULL;
379 int argc = 0, fvc = 0, i;
380 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000382 if (!(tmp = PyList_New(0)))
383 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 argv = argvStore;
386 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 if (args == NULL)
389 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000391 else if (!PyTuple_Check(args)) {
392 argc = 1;
393 fv[0] = 0;
394 if (!(argv[0] = AsString(args, tmp)))
395 goto finally;
396 }
397 else {
398 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000399
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 if (argc > ARGSZ) {
401 argv = (char **)ckalloc(argc * sizeof(char *));
402 fv = (int *)ckalloc(argc * sizeof(int));
403 if (argv == NULL || fv == NULL) {
404 PyErr_NoMemory();
405 goto finally;
406 }
407 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 for (i = 0; i < argc; i++) {
410 PyObject *v = PyTuple_GetItem(args, i);
411 if (PyTuple_Check(v)) {
412 fv[i] = 1;
413 if (!(argv[i] = Merge(v)))
414 goto finally;
415 fvc++;
416 }
417 else if (v == Py_None) {
418 argc = i;
419 break;
420 }
421 else {
422 fv[i] = 0;
423 if (!(argv[i] = AsString(v, tmp)))
424 goto finally;
425 fvc++;
426 }
427 }
428 }
429 res = Tcl_Merge(argc, argv);
430 if (res == NULL)
431 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000432
Barry Warsawfa701a81997-01-16 00:15:11 +0000433 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 for (i = 0; i < fvc; i++)
435 if (fv[i]) {
436 ckfree(argv[i]);
437 }
438 if (argv != argvStore)
439 ckfree(FREECAST argv);
440 if (fv != fvStore)
441 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 Py_DECREF(tmp);
444 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000445}
446
Barry Warsawfa701a81997-01-16 00:15:11 +0000447
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000448
Guido van Rossum18468821994-06-20 07:49:28 +0000449static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000450Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000451{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000452 int argc;
453 char **argv;
454 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000456 if (list == NULL) {
457 Py_INCREF(Py_None);
458 return Py_None;
459 }
Guido van Rossum18468821994-06-20 07:49:28 +0000460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
462 /* Not a list.
463 * Could be a quoted string containing funnies, e.g. {"}.
464 * Return the string itself.
465 */
466 return PyUnicode_FromString(list);
467 }
Guido van Rossum18468821994-06-20 07:49:28 +0000468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 if (argc == 0)
470 v = PyUnicode_FromString("");
471 else if (argc == 1)
472 v = PyUnicode_FromString(argv[0]);
473 else if ((v = PyTuple_New(argc)) != NULL) {
474 int i;
475 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000477 for (i = 0; i < argc; i++) {
478 if ((w = Split(argv[i])) == NULL) {
479 Py_DECREF(v);
480 v = NULL;
481 break;
482 }
483 PyTuple_SetItem(v, i, w);
484 }
485 }
486 Tcl_Free(FREECAST argv);
487 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000488}
489
Martin v. Löwisffad6332002-11-26 09:28:05 +0000490/* In some cases, Tcl will still return strings that are supposed to be
491 lists. SplitObj walks through a nested tuple, finding string objects that
492 need to be split. */
493
Martin v. Löwis59683e82008-06-13 07:50:45 +0000494static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000495SplitObj(PyObject *arg)
496{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 if (PyTuple_Check(arg)) {
498 int i, size;
499 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000501 size = PyTuple_Size(arg);
502 result = NULL;
503 /* Recursively invoke SplitObj for all tuple items.
504 If this does not return a new object, no action is
505 needed. */
506 for(i = 0; i < size; i++) {
507 elem = PyTuple_GetItem(arg, i);
508 newelem = SplitObj(elem);
509 if (!newelem) {
510 Py_XDECREF(result);
511 return NULL;
512 }
513 if (!result) {
514 int k;
515 if (newelem == elem) {
516 Py_DECREF(newelem);
517 continue;
518 }
519 result = PyTuple_New(size);
520 if (!result)
521 return NULL;
522 for(k = 0; k < i; k++) {
523 elem = PyTuple_GetItem(arg, k);
524 Py_INCREF(elem);
525 PyTuple_SetItem(result, k, elem);
526 }
527 }
528 PyTuple_SetItem(result, i, newelem);
529 }
530 if (result)
531 return result;
532 /* Fall through, returning arg. */
533 }
534 else if (PyBytes_Check(arg)) {
535 int argc;
536 char **argv;
537 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
540 Py_INCREF(arg);
541 return arg;
542 }
543 Tcl_Free(FREECAST argv);
544 if (argc > 1)
545 return Split(PyBytes_AsString(arg));
546 /* Fall through, returning arg. */
547 }
548 Py_INCREF(arg);
549 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000550}
Barry Warsawfa701a81997-01-16 00:15:11 +0000551
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552
Guido van Rossum18468821994-06-20 07:49:28 +0000553/**** Tkapp Object ****/
554
555#ifndef WITH_APPINIT
556int
Fred Drake509d79a2000-07-08 04:04:38 +0000557Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000558{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 if (Tcl_Init(interp) == TCL_ERROR) {
562 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
563 return TCL_ERROR;
564 }
Guilherme Polob681df42009-02-09 22:33:59 +0000565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 _tkinter_skip_tk_init = Tcl_GetVar(interp,
567 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
568 if (_tkinter_skip_tk_init != NULL &&
569 strcmp(_tkinter_skip_tk_init, "1") == 0) {
570 return TCL_OK;
571 }
Guilherme Polob681df42009-02-09 22:33:59 +0000572
573#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 if (tk_load_failed) {
575 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
576 return TCL_ERROR;
577 }
Guilherme Polob681df42009-02-09 22:33:59 +0000578#endif
579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000581#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000583#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
585 return TCL_ERROR;
586 }
Guilherme Polob681df42009-02-09 22:33:59 +0000587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000588 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000589}
590#endif /* !WITH_APPINIT */
591
Guido van Rossum18468821994-06-20 07:49:28 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593
Barry Warsawfa701a81997-01-16 00:15:11 +0000594
595/* Initialize the Tk application; see the `main' function in
596 * `tkMain.c'.
597 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000598
Thomas Wouters58d05102000-07-24 14:43:35 +0000599static void EnableEventHook(void); /* Forward */
600static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000601
Barry Warsawfa701a81997-01-16 00:15:11 +0000602static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000603Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000604 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000605{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 TkappObject *v;
607 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000608
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 v = PyObject_New(TkappObject, &Tkapp_Type);
610 if (v == NULL)
611 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 v->interp = Tcl_CreateInterp();
614 v->wantobjects = wantobjects;
615 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
616 TCL_GLOBAL_ONLY) != NULL;
617 v->thread_id = Tcl_GetCurrentThread();
618 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000619
620#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000621 if (v->threaded) {
622 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
623 Py_DECREF(v);
624 return 0;
625 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000626#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000627#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000628 if (v->threaded && tcl_lock) {
629 /* If Tcl is threaded, we don't need the lock. */
630 PyThread_free_lock(tcl_lock);
631 tcl_lock = NULL;
632 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000633#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000634
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000635 v->BooleanType = Tcl_GetObjType("boolean");
636 v->ByteArrayType = Tcl_GetObjType("bytearray");
637 v->DoubleType = Tcl_GetObjType("double");
638 v->IntType = Tcl_GetObjType("int");
639 v->ListType = Tcl_GetObjType("list");
640 v->ProcBodyType = Tcl_GetObjType("procbody");
641 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000643 /* Delete the 'exit' command, which can screw things up */
644 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000645
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000646 if (screenName != NULL)
647 Tcl_SetVar2(v->interp, "env", "DISPLAY",
648 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 if (interactive)
651 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
652 else
653 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000654
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000655 /* This is used to get the application class for Tk 4.1 and up */
656 argv0 = (char*)ckalloc(strlen(className) + 1);
657 if (!argv0) {
658 PyErr_NoMemory();
659 Py_DECREF(v);
660 return NULL;
661 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200664 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
665 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000666 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
667 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000669 if (! wantTk) {
670 Tcl_SetVar(v->interp,
671 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
672 }
Guilherme Polob681df42009-02-09 22:33:59 +0000673#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000674 else if (tk_load_failed) {
675 Tcl_SetVar(v->interp,
676 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
677 }
Guilherme Polob681df42009-02-09 22:33:59 +0000678#endif
David Aschere2b4b322004-02-18 05:59:53 +0000679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000680 /* some initial arguments need to be in argv */
681 if (sync || use) {
682 char *args;
683 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 if (sync)
686 len += sizeof "-sync";
687 if (use)
688 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 args = (char*)ckalloc(len);
691 if (!args) {
692 PyErr_NoMemory();
693 Py_DECREF(v);
694 return NULL;
695 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000696
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 args[0] = '\0';
698 if (sync)
699 strcat(args, "-sync");
700 if (use) {
701 if (sync)
702 strcat(args, " ");
703 strcat(args, "-use ");
704 strcat(args, use);
705 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
708 ckfree(args);
709 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 if (Tcl_AppInit(v->interp) != TCL_OK) {
712 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000713#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000714 if (wantTk) {
715 const char *_tkinter_tk_failed;
716 _tkinter_tk_failed = Tcl_GetVar(v->interp,
717 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000718
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000719 if ( _tkinter_tk_failed != NULL &&
720 strcmp(_tkinter_tk_failed, "1") == 0) {
721 tk_load_failed = 1;
722 }
723 }
Guilherme Polob681df42009-02-09 22:33:59 +0000724#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 Py_DECREF((PyObject *)v);
726 return (TkappObject *)result;
727 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000730
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000731 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000732}
733
Barry Warsawfa701a81997-01-16 00:15:11 +0000734
Benjamin Peterson5879d412009-03-30 14:51:56 +0000735#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000736static void
737Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000739{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000740 Py_BEGIN_ALLOW_THREADS;
741 Tcl_MutexLock(mutex);
742 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
743 Tcl_ThreadAlert(self->thread_id);
744 Tcl_ConditionWait(cond, mutex, NULL);
745 Tcl_MutexUnlock(mutex);
746 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000747}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000748#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750
Guido van Rossum18468821994-06-20 07:49:28 +0000751/** Tcl Eval **/
752
Martin v. Löwisffad6332002-11-26 09:28:05 +0000753typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 PyObject_HEAD
755 Tcl_Obj *value;
756 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000757} PyTclObject;
758
Neal Norwitz227b5332006-03-22 09:28:35 +0000759static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000760#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000761
762static PyObject *
763newPyTclObject(Tcl_Obj *arg)
764{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 PyTclObject *self;
766 self = PyObject_New(PyTclObject, &PyTclObject_Type);
767 if (self == NULL)
768 return NULL;
769 Tcl_IncrRefCount(arg);
770 self->value = arg;
771 self->string = NULL;
772 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000773}
774
775static void
776PyTclObject_dealloc(PyTclObject *self)
777{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000778 Tcl_DecrRefCount(self->value);
779 Py_XDECREF(self->string);
780 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000781}
782
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000783static char*
784PyTclObject_TclString(PyObject *self)
785{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000787}
788
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000789/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000790PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000791"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000792
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000793static PyObject *
794PyTclObject_string(PyTclObject *self, void *ignored)
795{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 char *s;
797 int len;
798 if (!self->string) {
799 s = Tcl_GetStringFromObj(self->value, &len);
800 self->string = PyUnicode_FromStringAndSize(s, len);
801 if (!self->string)
802 return NULL;
803 }
804 Py_INCREF(self->string);
805 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000806}
807
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000808static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000809PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000810{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 char *s;
812 int len;
813 if (self->string && PyUnicode_Check(self->string)) {
814 Py_INCREF(self->string);
815 return self->string;
816 }
817 /* XXX Could chache result if it is non-ASCII. */
818 s = Tcl_GetStringFromObj(self->value, &len);
819 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000820}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000821
Martin v. Löwisffad6332002-11-26 09:28:05 +0000822static PyObject *
823PyTclObject_repr(PyTclObject *self)
824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000825 return PyUnicode_FromFormat("<%s object at %p>",
826 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000827}
828
Mark Dickinson211c6252009-02-01 10:28:51 +0000829#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
830
831static PyObject *
832PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000833{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 int result;
835 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 /* neither argument should be NULL, unless something's gone wrong */
838 if (self == NULL || other == NULL) {
839 PyErr_BadInternalCall();
840 return NULL;
841 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 /* both arguments should be instances of PyTclObject */
844 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
845 v = Py_NotImplemented;
846 goto finished;
847 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000849 if (self == other)
850 /* fast path when self and other are identical */
851 result = 0;
852 else
853 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
854 Tcl_GetString(((PyTclObject *)other)->value));
855 /* Convert return value to a Boolean */
856 switch (op) {
857 case Py_EQ:
858 v = TEST_COND(result == 0);
859 break;
860 case Py_NE:
861 v = TEST_COND(result != 0);
862 break;
863 case Py_LE:
864 v = TEST_COND(result <= 0);
865 break;
866 case Py_GE:
867 v = TEST_COND(result >= 0);
868 break;
869 case Py_LT:
870 v = TEST_COND(result < 0);
871 break;
872 case Py_GT:
873 v = TEST_COND(result > 0);
874 break;
875 default:
876 PyErr_BadArgument();
877 return NULL;
878 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000879 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000880 Py_INCREF(v);
881 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000882}
883
Martin v. Löwis39195712003-01-04 00:33:13 +0000884PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
885
Martin v. Löwisffad6332002-11-26 09:28:05 +0000886static PyObject*
887get_typename(PyTclObject* obj, void* ignored)
888{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000889 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000890}
891
Martin v. Löwis39195712003-01-04 00:33:13 +0000892
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000894 {"typename", (getter)get_typename, NULL, get_typename__doc__},
895 {"string", (getter)PyTclObject_string, NULL,
896 PyTclObject_string__doc__},
897 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000898};
899
Neal Norwitz227b5332006-03-22 09:28:35 +0000900static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 PyVarObject_HEAD_INIT(NULL, 0)
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject), /*tp_basicsize*/
904 0, /*tp_itemsize*/
905 /* methods */
906 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
907 0, /*tp_print*/
908 0, /*tp_getattr*/
909 0, /*tp_setattr*/
910 0, /*tp_reserved*/
911 (reprfunc)PyTclObject_repr, /*tp_repr*/
912 0, /*tp_as_number*/
913 0, /*tp_as_sequence*/
914 0, /*tp_as_mapping*/
915 0, /*tp_hash*/
916 0, /*tp_call*/
917 (reprfunc)PyTclObject_str, /*tp_str*/
918 PyObject_GenericGetAttr, /*tp_getattro*/
919 0, /*tp_setattro*/
920 0, /*tp_as_buffer*/
921 Py_TPFLAGS_DEFAULT, /*tp_flags*/
922 0, /*tp_doc*/
923 0, /*tp_traverse*/
924 0, /*tp_clear*/
925 PyTclObject_richcompare, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
927 0, /*tp_iter*/
928 0, /*tp_iternext*/
929 0, /*tp_methods*/
930 0, /*tp_members*/
931 PyTclObject_getsetlist, /*tp_getset*/
932 0, /*tp_base*/
933 0, /*tp_dict*/
934 0, /*tp_descr_get*/
935 0, /*tp_descr_set*/
936 0, /*tp_dictoffset*/
937 0, /*tp_init*/
938 0, /*tp_alloc*/
939 0, /*tp_new*/
940 0, /*tp_free*/
941 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942};
943
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000944static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000945AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000946{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000947 Tcl_Obj *result;
948 long longVal;
949 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000950
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000951 if (PyBytes_Check(value))
952 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
953 PyBytes_GET_SIZE(value));
954 else if (PyBool_Check(value))
955 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
956 else if (PyLong_CheckExact(value) &&
957 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
958 !overflow)) {
959 /* If there is an overflow in the long conversion,
960 fall through to default object handling. */
961 return Tcl_NewLongObj(longVal);
962 }
963 else if (PyFloat_Check(value))
964 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
965 else if (PyTuple_Check(value)) {
966 Tcl_Obj **argv = (Tcl_Obj**)
967 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
968 int i;
969 if(!argv)
970 return 0;
971 for(i=0;i<PyTuple_Size(value);i++)
972 argv[i] = AsObj(PyTuple_GetItem(value,i));
973 result = Tcl_NewListObj(PyTuple_Size(value), argv);
974 ckfree(FREECAST argv);
975 return result;
976 }
977 else if (PyUnicode_Check(value)) {
978 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
979 Py_ssize_t size = PyUnicode_GET_SIZE(value);
980 /* This #ifdef assumes that Tcl uses UCS-2.
981 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000982#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000983 Tcl_UniChar *outbuf = NULL;
984 Py_ssize_t i;
985 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
986 if (allocsize >= size)
987 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
988 /* Else overflow occurred, and we take the next exit */
989 if (!outbuf) {
990 PyErr_NoMemory();
991 return NULL;
992 }
993 for (i = 0; i < size; i++) {
994 if (inbuf[i] >= 0x10000) {
995 /* Tcl doesn't do UTF-16, yet. */
Victor Stinner7ab41922011-11-04 00:36:46 +0100996 PyErr_Format(PyExc_ValueError,
997 "character U+%x is above the range "
998 "(U+0000-U+FFFF) allowed by Tcl",
999 inbuf[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 ckfree(FREECAST outbuf);
1001 return NULL;
1002 }
1003 outbuf[i] = inbuf[i];
1004 }
1005 result = Tcl_NewUnicodeObj(outbuf, size);
1006 ckfree(FREECAST outbuf);
1007 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001008#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001010#endif
1011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 }
1013 else if(PyTclObject_Check(value)) {
1014 Tcl_Obj *v = ((PyTclObject*)value)->value;
1015 Tcl_IncrRefCount(v);
1016 return v;
1017 }
1018 else {
1019 PyObject *v = PyObject_Str(value);
1020 if (!v)
1021 return 0;
1022 result = AsObj(v);
1023 Py_DECREF(v);
1024 return result;
1025 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001026}
1027
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028static PyObject*
1029FromObj(PyObject* tkapp, Tcl_Obj *value)
1030{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 PyObject *result = NULL;
1032 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001033
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 if (value->typePtr == NULL) {
1035 return PyUnicode_FromStringAndSize(value->bytes,
1036 value->length);
1037 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 if (value->typePtr == app->BooleanType) {
1040 result = value->internalRep.longValue ? Py_True : Py_False;
1041 Py_INCREF(result);
1042 return result;
1043 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 if (value->typePtr == app->ByteArrayType) {
1046 int size;
1047 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1048 return PyBytes_FromStringAndSize(data, size);
1049 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 if (value->typePtr == app->DoubleType) {
1052 return PyFloat_FromDouble(value->internalRep.doubleValue);
1053 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001055 if (value->typePtr == app->IntType) {
1056 return PyLong_FromLong(value->internalRep.longValue);
1057 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 if (value->typePtr == app->ListType) {
1060 int size;
1061 int i, status;
1062 PyObject *elem;
1063 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001065 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1066 if (status == TCL_ERROR)
1067 return Tkinter_Error(tkapp);
1068 result = PyTuple_New(size);
1069 if (!result)
1070 return NULL;
1071 for (i = 0; i < size; i++) {
1072 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1073 value, i, &tcl_elem);
1074 if (status == TCL_ERROR) {
1075 Py_DECREF(result);
1076 return Tkinter_Error(tkapp);
1077 }
1078 elem = FromObj(tkapp, tcl_elem);
1079 if (!elem) {
1080 Py_DECREF(result);
1081 return NULL;
1082 }
1083 PyTuple_SetItem(result, i, elem);
1084 }
1085 return result;
1086 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 if (value->typePtr == app->ProcBodyType) {
1089 /* fall through: return tcl object. */
1090 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001093#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 PyObject *result;
1095 int size;
1096 Tcl_UniChar *input;
1097 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001099 size = Tcl_GetCharLength(value);
1100 result = PyUnicode_FromUnicode(NULL, size);
1101 if (!result)
1102 return NULL;
1103 input = Tcl_GetUnicode(value);
1104 output = PyUnicode_AS_UNICODE(result);
1105 while (size--)
1106 *output++ = *input++;
1107 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001108#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001109 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1110 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001111#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001112 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001115}
1116
Benjamin Peterson5879d412009-03-30 14:51:56 +00001117#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001118/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001119TCL_DECLARE_MUTEX(call_mutex)
1120
1121typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001122 Tcl_Event ev; /* Must be first */
1123 TkappObject *self;
1124 PyObject *args;
1125 int flags;
1126 PyObject **res;
1127 PyObject **exc_type, **exc_value, **exc_tb;
1128 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001129} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001130#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001131
1132void
1133Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 int i;
1136 for (i = 0; i < objc; i++)
1137 Tcl_DecrRefCount(objv[i]);
1138 if (objv != objStore)
1139 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001140}
Guido van Rossum18468821994-06-20 07:49:28 +00001141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001142/* Convert Python objects to Tcl objects. This must happen in the
1143 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001144
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145static Tcl_Obj**
1146Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1147{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 Tcl_Obj **objv = objStore;
1149 int objc = 0, i;
1150 if (args == NULL)
1151 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153 else if (!PyTuple_Check(args)) {
1154 objv[0] = AsObj(args);
1155 if (objv[0] == 0)
1156 goto finally;
1157 objc = 1;
1158 Tcl_IncrRefCount(objv[0]);
1159 }
1160 else {
1161 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 if (objc > ARGSZ) {
1164 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1165 if (objv == NULL) {
1166 PyErr_NoMemory();
1167 objc = 0;
1168 goto finally;
1169 }
1170 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001172 for (i = 0; i < objc; i++) {
1173 PyObject *v = PyTuple_GetItem(args, i);
1174 if (v == Py_None) {
1175 objc = i;
1176 break;
1177 }
1178 objv[i] = AsObj(v);
1179 if (!objv[i]) {
1180 /* Reset objc, so it attempts to clear
1181 objects only up to i. */
1182 objc = i;
1183 goto finally;
1184 }
1185 Tcl_IncrRefCount(objv[i]);
1186 }
1187 }
1188 *pobjc = objc;
1189 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001191 Tkapp_CallDeallocArgs(objv, objStore, objc);
1192 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193}
Guido van Rossum212643f1998-04-29 16:22:14 +00001194
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001195/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001196
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197static PyObject*
1198Tkapp_CallResult(TkappObject *self)
1199{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001200 PyObject *res = NULL;
1201 if(self->wantobjects) {
1202 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1203 /* Not sure whether the IncrRef is necessary, but something
1204 may overwrite the interpreter result while we are
1205 converting it. */
1206 Tcl_IncrRefCount(value);
1207 res = FromObj((PyObject*)self, value);
1208 Tcl_DecrRefCount(value);
1209 } else {
1210 const char *s = Tcl_GetStringResult(self->interp);
1211 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001213 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1214 }
1215 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216}
Guido van Rossum632de272000-03-29 00:19:50 +00001217
Benjamin Peterson5879d412009-03-30 14:51:56 +00001218#ifdef WITH_THREAD
1219
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220/* Tkapp_CallProc is the event procedure that is executed in the context of
1221 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1222 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001223
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224static int
1225Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1226{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 Tcl_Obj *objStore[ARGSZ];
1228 Tcl_Obj **objv;
1229 int objc;
1230 int i;
1231 ENTER_PYTHON
1232 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1233 if (!objv) {
1234 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1235 *(e->res) = NULL;
1236 }
1237 LEAVE_PYTHON
1238 if (!objv)
1239 goto done;
1240 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1241 ENTER_PYTHON
1242 if (i == TCL_ERROR) {
1243 *(e->res) = NULL;
1244 *(e->exc_type) = NULL;
1245 *(e->exc_tb) = NULL;
1246 *(e->exc_value) = PyObject_CallFunction(
1247 Tkinter_TclError, "s",
1248 Tcl_GetStringResult(e->self->interp));
1249 }
1250 else {
1251 *(e->res) = Tkapp_CallResult(e->self);
1252 }
1253 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001256done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 /* Wake up calling thread. */
1258 Tcl_MutexLock(&call_mutex);
1259 Tcl_ConditionNotify(e->done);
1260 Tcl_MutexUnlock(&call_mutex);
1261 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262}
1263
Benjamin Peterson5879d412009-03-30 14:51:56 +00001264#endif
1265
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266/* This is the main entry point for calling a Tcl command.
1267 It supports three cases, with regard to threading:
1268 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1269 the context of the calling thread.
1270 2. Tcl is threaded, caller of the command is in the interpreter thread:
1271 Execute the command in the calling thread. Since the Tcl lock will
1272 not be used, we can merge that with case 1.
1273 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1274 the interpreter thread. Allocation of Tcl objects needs to occur in the
1275 interpreter thread, so we ship the PyObject* args to the target thread,
1276 and perform processing there. */
1277
1278static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001279Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001280{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 Tcl_Obj *objStore[ARGSZ];
1282 Tcl_Obj **objv = NULL;
1283 int objc, i;
1284 PyObject *res = NULL;
1285 TkappObject *self = (TkappObject*)selfptr;
1286 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001288 /* If args is a single tuple, replace with contents of tuple */
1289 if (1 == PyTuple_Size(args)){
1290 PyObject* item = PyTuple_GetItem(args, 0);
1291 if (PyTuple_Check(item))
1292 args = item;
1293 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001294#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001295 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1296 /* We cannot call the command directly. Instead, we must
1297 marshal the parameters to the interpreter thread. */
1298 Tkapp_CallEvent *ev;
1299 Tcl_Condition cond = NULL;
1300 PyObject *exc_type, *exc_value, *exc_tb;
1301 if (!WaitForMainloop(self))
1302 return NULL;
1303 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1304 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1305 ev->self = self;
1306 ev->args = args;
1307 ev->res = &res;
1308 ev->exc_type = &exc_type;
1309 ev->exc_value = &exc_value;
1310 ev->exc_tb = &exc_tb;
1311 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 if (res == NULL) {
1316 if (exc_type)
1317 PyErr_Restore(exc_type, exc_value, exc_tb);
1318 else
1319 PyErr_SetObject(Tkinter_TclError, exc_value);
1320 }
1321 Tcl_ConditionFinalize(&cond);
1322 }
1323 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001324#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 objv = Tkapp_CallArgs(args, objStore, &objc);
1328 if (!objv)
1329 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 if (i == TCL_ERROR)
1338 Tkinter_Error(selfptr);
1339 else
1340 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 Tkapp_CallDeallocArgs(objv, objStore, objc);
1345 }
1346 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001347}
1348
1349
1350static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001351Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001352{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 /* Could do the same here as for Tkapp_Call(), but this is not used
1354 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1355 way for the user to do what all its Global* variants do (save and
1356 reset the scope pointer, call the local version, restore the saved
1357 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 char *cmd;
1360 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 cmd = Merge(args);
1365 if (cmd) {
1366 int err;
1367 ENTER_TCL
1368 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1369 ENTER_OVERLAP
1370 if (err == TCL_ERROR)
1371 res = Tkinter_Error(self);
1372 else
1373 res = PyUnicode_FromString(Tkapp_Result(self));
1374 LEAVE_OVERLAP_TCL
1375 ckfree(cmd);
1376 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001379}
1380
1381static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001382Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001383{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001384 char *script;
1385 PyObject *res = NULL;
1386 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001388 if (!PyArg_ParseTuple(args, "s:eval", &script))
1389 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001393 ENTER_TCL
1394 err = Tcl_Eval(Tkapp_Interp(self), script);
1395 ENTER_OVERLAP
1396 if (err == TCL_ERROR)
1397 res = Tkinter_Error(self);
1398 else
1399 res = PyUnicode_FromString(Tkapp_Result(self));
1400 LEAVE_OVERLAP_TCL
1401 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001402}
1403
1404static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001405Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001406{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001407 char *script;
1408 PyObject *res = NULL;
1409 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1412 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001415
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001416 ENTER_TCL
1417 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1418 ENTER_OVERLAP
1419 if (err == TCL_ERROR)
1420 res = Tkinter_Error(self);
1421 else
1422 res = PyUnicode_FromString(Tkapp_Result(self));
1423 LEAVE_OVERLAP_TCL
1424 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001425}
1426
1427static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001428Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001429{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 char *fileName;
1431 PyObject *res = NULL;
1432 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1435 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 ENTER_TCL
1440 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1441 ENTER_OVERLAP
1442 if (err == TCL_ERROR)
1443 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001445 else
1446 res = PyUnicode_FromString(Tkapp_Result(self));
1447 LEAVE_OVERLAP_TCL
1448 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001449}
1450
1451static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001452Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001453{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 char *script;
1455 PyObject *res = NULL;
1456 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 if (!PyArg_ParseTuple(args, "s", &script))
1459 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 ENTER_TCL
1464 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1465 ENTER_OVERLAP
1466 if (err == TCL_ERROR)
1467 res = Tkinter_Error(self);
1468 else
1469 res = PyUnicode_FromString(Tkapp_Result(self));
1470 LEAVE_OVERLAP_TCL
1471 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001472}
1473
1474static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001475Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001476{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1480 return NULL;
1481 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 ENTER_TCL
1484 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1485 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 Py_INCREF(Py_None);
1488 return Py_None;
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 +00001493/** Tcl Variable **/
1494
Benjamin Peterson5879d412009-03-30 14:51:56 +00001495typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1496
1497#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498TCL_DECLARE_MUTEX(var_mutex)
1499
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001501 Tcl_Event ev; /* must be first */
1502 PyObject *self;
1503 PyObject *args;
1504 int flags;
1505 EventFunc func;
1506 PyObject **res;
1507 PyObject **exc_type;
1508 PyObject **exc_val;
1509 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001511#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001513static int
1514varname_converter(PyObject *in, void *_out)
1515{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001516 char **out = (char**)_out;
1517 if (PyBytes_Check(in)) {
1518 *out = PyBytes_AsString(in);
1519 return 1;
1520 }
1521 if (PyUnicode_Check(in)) {
1522 *out = _PyUnicode_AsString(in);
1523 return 1;
1524 }
1525 if (PyTclObject_Check(in)) {
1526 *out = PyTclObject_TclString(in);
1527 return 1;
1528 }
1529 /* XXX: Should give diagnostics. */
1530 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001531}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001532
Benjamin Peterson5879d412009-03-30 14:51:56 +00001533#ifdef WITH_THREAD
1534
Martin v. Löwis59683e82008-06-13 07:50:45 +00001535static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536var_perform(VarEvent *ev)
1537{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1539 if (!*(ev->res)) {
1540 PyObject *exc, *val, *tb;
1541 PyErr_Fetch(&exc, &val, &tb);
1542 PyErr_NormalizeException(&exc, &val, &tb);
1543 *(ev->exc_type) = exc;
1544 *(ev->exc_val) = val;
1545 Py_DECREF(tb);
1546 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001547
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548}
1549
1550static int
1551var_proc(VarEvent* ev, int flags)
1552{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 ENTER_PYTHON
1554 var_perform(ev);
1555 Tcl_MutexLock(&var_mutex);
1556 Tcl_ConditionNotify(ev->cond);
1557 Tcl_MutexUnlock(&var_mutex);
1558 LEAVE_PYTHON
1559 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001560}
1561
Benjamin Peterson5879d412009-03-30 14:51:56 +00001562#endif
1563
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001565var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001567#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001568 TkappObject *self = (TkappObject*)selfptr;
1569 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1570 TkappObject *self = (TkappObject*)selfptr;
1571 VarEvent *ev;
1572 PyObject *res, *exc_type, *exc_val;
1573 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 /* The current thread is not the interpreter thread. Marshal
1576 the call to the interpreter thread, then wait for
1577 completion. */
1578 if (!WaitForMainloop(self))
1579 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 ev->self = selfptr;
1584 ev->args = args;
1585 ev->flags = flags;
1586 ev->func = func;
1587 ev->res = &res;
1588 ev->exc_type = &exc_type;
1589 ev->exc_val = &exc_val;
1590 ev->cond = &cond;
1591 ev->ev.proc = (Tcl_EventProc*)var_proc;
1592 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1593 Tcl_ConditionFinalize(&cond);
1594 if (!res) {
1595 PyErr_SetObject(exc_type, exc_val);
1596 Py_DECREF(exc_type);
1597 Py_DECREF(exc_val);
1598 return NULL;
1599 }
1600 return res;
1601 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001602#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 /* Tcl is not threaded, or this is the interpreter thread. */
1604 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001605}
1606
Guido van Rossum18468821994-06-20 07:49:28 +00001607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001608SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001609{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001610 char *name1, *name2;
1611 PyObject *newValue;
1612 PyObject *res = NULL;
1613 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001614
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 if (PyArg_ParseTuple(args, "O&O:setvar",
1616 varname_converter, &name1, &newValue)) {
1617 /* XXX Acquire tcl lock??? */
1618 newval = AsObj(newValue);
1619 if (newval == NULL)
1620 return NULL;
1621 ENTER_TCL
1622 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1623 newval, flags);
1624 ENTER_OVERLAP
1625 if (!ok)
1626 Tkinter_Error(self);
1627 else {
1628 res = Py_None;
1629 Py_INCREF(res);
1630 }
1631 LEAVE_OVERLAP_TCL
1632 }
1633 else {
1634 PyErr_Clear();
1635 if (PyArg_ParseTuple(args, "ssO:setvar",
1636 &name1, &name2, &newValue)) {
1637 /* XXX must hold tcl lock already??? */
1638 newval = AsObj(newValue);
1639 ENTER_TCL
1640 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1641 ENTER_OVERLAP
1642 if (!ok)
1643 Tkinter_Error(self);
1644 else {
1645 res = Py_None;
1646 Py_INCREF(res);
1647 }
1648 LEAVE_OVERLAP_TCL
1649 }
1650 else {
1651 return NULL;
1652 }
1653 }
1654 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
1657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001658Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001659{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001660 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001661}
1662
1663static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001664Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001665{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001666 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001667}
1668
Barry Warsawfa701a81997-01-16 00:15:11 +00001669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001670
Guido van Rossum18468821994-06-20 07:49:28 +00001671static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001672GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001673{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 char *name1, *name2=NULL;
1675 PyObject *res = NULL;
1676 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1679 varname_converter, &name1, &name2))
1680 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 ENTER_TCL
1683 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1684 ENTER_OVERLAP
1685 if (tres == NULL) {
1686 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1687 } else {
1688 if (((TkappObject*)self)->wantobjects) {
1689 res = FromObj(self, tres);
1690 }
1691 else {
1692 res = PyUnicode_FromString(Tcl_GetString(tres));
1693 }
1694 }
1695 LEAVE_OVERLAP_TCL
1696 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
1699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001701{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001702 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
1705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001706Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001707{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001708 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
Barry Warsawfa701a81997-01-16 00:15:11 +00001711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712
Guido van Rossum18468821994-06-20 07:49:28 +00001713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001716 char *name1, *name2=NULL;
1717 int code;
1718 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1721 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 ENTER_TCL
1724 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1725 ENTER_OVERLAP
1726 if (code == TCL_ERROR)
1727 res = Tkinter_Error(self);
1728 else {
1729 Py_INCREF(Py_None);
1730 res = Py_None;
1731 }
1732 LEAVE_OVERLAP_TCL
1733 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001734}
1735
1736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001740}
1741
1742static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001743Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001745 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001746}
1747
Barry Warsawfa701a81997-01-16 00:15:11 +00001748
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749
Guido van Rossum18468821994-06-20 07:49:28 +00001750/** Tcl to Python **/
1751
1752static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001753Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001754{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 char *s;
1756 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 if (PyTuple_Size(args) == 1) {
1759 PyObject* o = PyTuple_GetItem(args, 0);
1760 if (PyLong_Check(o)) {
1761 Py_INCREF(o);
1762 return o;
1763 }
1764 }
1765 if (!PyArg_ParseTuple(args, "s:getint", &s))
1766 return NULL;
1767 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1768 return Tkinter_Error(self);
1769 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001775 char *s;
1776 double v;
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 (PyFloat_Check(o)) {
1781 Py_INCREF(o);
1782 return o;
1783 }
1784 }
1785 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1786 return NULL;
1787 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1788 return Tkinter_Error(self);
1789 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001790}
1791
1792static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001793Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001795 char *s;
1796 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001798 if (PyTuple_Size(args) == 1) {
1799 PyObject *o = PyTuple_GetItem(args, 0);
1800 if (PyLong_Check(o)) {
1801 Py_INCREF(o);
1802 return o;
1803 }
1804 }
1805 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1806 return NULL;
1807 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1808 return Tkinter_Error(self);
1809 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001810}
1811
1812static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001813Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001814{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001815 char *s;
1816 PyObject *res = NULL;
1817 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1820 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001824 ENTER_TCL
1825 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1826 ENTER_OVERLAP
1827 if (retval == TCL_ERROR)
1828 res = Tkinter_Error(self);
1829 else
1830 res = Py_BuildValue("s", Tkapp_Result(self));
1831 LEAVE_OVERLAP_TCL
1832 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001833}
1834
1835static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001836Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001837{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001838 char *s;
1839 PyObject *res = NULL;
1840 int retval;
1841 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001843 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1844 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001847
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001848 ENTER_TCL
1849 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1850 ENTER_OVERLAP
1851 if (retval == TCL_ERROR)
1852 res = Tkinter_Error(self);
1853 else
1854 res = Py_BuildValue("l", v);
1855 LEAVE_OVERLAP_TCL
1856 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001857}
1858
1859static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001860Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001861{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862 char *s;
1863 PyObject *res = NULL;
1864 double v;
1865 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001866
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1868 return NULL;
1869 CHECK_TCL_APPARTMENT;
1870 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1871 ENTER_TCL
1872 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1873 ENTER_OVERLAP
1874 PyFPE_END_PROTECT(retval)
1875 if (retval == TCL_ERROR)
1876 res = Tkinter_Error(self);
1877 else
1878 res = Py_BuildValue("d", v);
1879 LEAVE_OVERLAP_TCL
1880 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
1883static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001884Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001885{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001886 char *s;
1887 PyObject *res = NULL;
1888 int retval;
1889 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001891 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1892 return NULL;
1893 CHECK_TCL_APPARTMENT;
1894 ENTER_TCL
1895 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1896 ENTER_OVERLAP
1897 if (retval == TCL_ERROR)
1898 res = Tkinter_Error(self);
1899 else
1900 res = Py_BuildValue("i", v);
1901 LEAVE_OVERLAP_TCL
1902 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
Barry Warsawfa701a81997-01-16 00:15:11 +00001905
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001906
Guido van Rossum18468821994-06-20 07:49:28 +00001907static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001908Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001909{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910 char *list;
1911 int argc;
1912 char **argv;
1913 PyObject *v;
1914 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 if (PyTuple_Size(args) == 1) {
1917 v = PyTuple_GetItem(args, 0);
1918 if (PyTuple_Check(v)) {
1919 Py_INCREF(v);
1920 return v;
1921 }
1922 }
1923 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1924 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001925
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 if (Tcl_SplitList(Tkapp_Interp(self), list,
1927 &argc, &argv) == TCL_ERROR) {
1928 PyMem_Free(list);
1929 return Tkinter_Error(self);
1930 }
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (!(v = PyTuple_New(argc)))
1933 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 for (i = 0; i < argc; i++) {
1936 PyObject *s = PyUnicode_FromString(argv[i]);
1937 if (!s || PyTuple_SetItem(v, i, s)) {
1938 Py_DECREF(v);
1939 v = NULL;
1940 goto finally;
1941 }
1942 }
Guido van Rossum18468821994-06-20 07:49:28 +00001943
Barry Warsawfa701a81997-01-16 00:15:11 +00001944 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001945 ckfree(FREECAST argv);
1946 PyMem_Free(list);
1947 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001948}
1949
1950static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001951Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001952{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 PyObject *v;
1954 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 if (PyTuple_Size(args) == 1) {
1957 PyObject* o = PyTuple_GetItem(args, 0);
1958 if (PyTuple_Check(o)) {
1959 o = SplitObj(o);
1960 return o;
1961 }
1962 }
1963 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1964 return NULL;
1965 v = Split(list);
1966 PyMem_Free(list);
1967 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001968}
1969
1970static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001971Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001972{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001973 char *s = Merge(args);
1974 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001976 if (s) {
1977 res = PyUnicode_FromString(s);
1978 ckfree(s);
1979 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001980
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001981 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001982}
1983
Barry Warsawfa701a81997-01-16 00:15:11 +00001984
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985
Guido van Rossum18468821994-06-20 07:49:28 +00001986/** Tcl Command **/
1987
Guido van Rossum00d93061998-05-28 23:06:38 +00001988/* Client data struct */
1989typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 PyObject *self;
1991 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001992} PythonCmd_ClientData;
1993
1994static int
Fred Drake509d79a2000-07-08 04:04:38 +00001995PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001996{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001997 errorInCmd = 1;
1998 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1999 LEAVE_PYTHON
2000 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002001}
2002
Guido van Rossum18468821994-06-20 07:49:28 +00002003/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002004 * function or method.
2005 */
Guido van Rossum18468821994-06-20 07:49:28 +00002006static int
Fred Drake509d79a2000-07-08 04:04:38 +00002007PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2010 PyObject *self, *func, *arg, *res;
2011 int i, rv;
2012 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 /* TBD: no error checking here since we know, via the
2017 * Tkapp_CreateCommand() that the client data is a two-tuple
2018 */
2019 self = data->self;
2020 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002022 /* Create argument list (argv1, ..., argvN) */
2023 if (!(arg = PyTuple_New(argc - 1)))
2024 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002026 for (i = 0; i < (argc - 1); i++) {
2027 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002028 if (!s) {
2029 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2030 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2031 !strcmp(argv[i + 1], "\xC0\x80")) {
2032 PyErr_Clear();
2033 /* Convert to "strict" utf-8 null */
2034 s = PyUnicode_FromString("\0");
2035 } else {
2036 Py_DECREF(arg);
2037 return PythonCmd_Error(interp);
2038 }
2039 }
2040 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002041 Py_DECREF(arg);
2042 return PythonCmd_Error(interp);
2043 }
2044 }
2045 res = PyEval_CallObject(func, arg);
2046 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002048 if (res == NULL)
2049 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002051 obj_res = AsObj(res);
2052 if (obj_res == NULL) {
2053 Py_DECREF(res);
2054 return PythonCmd_Error(interp);
2055 }
2056 else {
2057 Tcl_SetObjResult(interp, obj_res);
2058 rv = TCL_OK;
2059 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002066}
2067
2068static void
Fred Drake509d79a2000-07-08 04:04:38 +00002069PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002070{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 ENTER_PYTHON
2074 Py_XDECREF(data->self);
2075 Py_XDECREF(data->func);
2076 PyMem_DEL(data);
2077 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002078}
2079
Barry Warsawfa701a81997-01-16 00:15:11 +00002080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002081
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002082
Benjamin Peterson5879d412009-03-30 14:51:56 +00002083#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084TCL_DECLARE_MUTEX(command_mutex)
2085
2086typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002087 Tcl_Event ev;
2088 Tcl_Interp* interp;
2089 char *name;
2090 int create;
2091 int *status;
2092 ClientData *data;
2093 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002094} CommandEvent;
2095
2096static int
2097Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 if (ev->create)
2100 *ev->status = Tcl_CreateCommand(
2101 ev->interp, ev->name, PythonCmd,
2102 ev->data, PythonCmdDelete) == NULL;
2103 else
2104 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2105 Tcl_MutexLock(&command_mutex);
2106 Tcl_ConditionNotify(ev->done);
2107 Tcl_MutexUnlock(&command_mutex);
2108 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002110#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111
2112static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002113Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 TkappObject *self = (TkappObject*)selfptr;
2116 PythonCmd_ClientData *data;
2117 char *cmdName;
2118 PyObject *func;
2119 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002120
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002121 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2122 return NULL;
2123 if (!PyCallable_Check(func)) {
2124 PyErr_SetString(PyExc_TypeError, "command not callable");
2125 return NULL;
2126 }
Guido van Rossum18468821994-06-20 07:49:28 +00002127
Martin v. Löwisa9656492003-03-30 08:44:58 +00002128#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2130 !WaitForMainloop(self))
2131 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002132#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 data = PyMem_NEW(PythonCmd_ClientData, 1);
2135 if (!data)
2136 return PyErr_NoMemory();
2137 Py_INCREF(self);
2138 Py_INCREF(func);
2139 data->self = selfptr;
2140 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002141#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002142 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2143 Tcl_Condition cond = NULL;
2144 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2145 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2146 ev->interp = self->interp;
2147 ev->create = 1;
2148 ev->name = cmdName;
2149 ev->data = (ClientData)data;
2150 ev->status = &err;
2151 ev->done = &cond;
2152 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2153 Tcl_ConditionFinalize(&cond);
2154 }
2155 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002156#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 {
2158 ENTER_TCL
2159 err = Tcl_CreateCommand(
2160 Tkapp_Interp(self), cmdName, PythonCmd,
2161 (ClientData)data, PythonCmdDelete) == NULL;
2162 LEAVE_TCL
2163 }
2164 if (err) {
2165 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2166 PyMem_DEL(data);
2167 return NULL;
2168 }
Guido van Rossum18468821994-06-20 07:49:28 +00002169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002170 Py_INCREF(Py_None);
2171 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002172}
2173
Barry Warsawfa701a81997-01-16 00:15:11 +00002174
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002175
Guido van Rossum18468821994-06-20 07:49:28 +00002176static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002177Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002179 TkappObject *self = (TkappObject*)selfptr;
2180 char *cmdName;
2181 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002182
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002183 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2184 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002185
2186#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2188 Tcl_Condition cond = NULL;
2189 CommandEvent *ev;
2190 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2191 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2192 ev->interp = self->interp;
2193 ev->create = 0;
2194 ev->name = cmdName;
2195 ev->status = &err;
2196 ev->done = &cond;
2197 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2198 &command_mutex);
2199 Tcl_ConditionFinalize(&cond);
2200 }
2201 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002202#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 {
2204 ENTER_TCL
2205 err = Tcl_DeleteCommand(self->interp, cmdName);
2206 LEAVE_TCL
2207 }
2208 if (err == -1) {
2209 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2210 return NULL;
2211 }
2212 Py_INCREF(Py_None);
2213 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002214}
2215
Barry Warsawfa701a81997-01-16 00:15:11 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217
Guido van Rossum00d93061998-05-28 23:06:38 +00002218#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002219/** File Handler **/
2220
Guido van Rossum00d93061998-05-28 23:06:38 +00002221typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002222 PyObject *func;
2223 PyObject *file;
2224 int id;
2225 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002226} FileHandler_ClientData;
2227
2228static FileHandler_ClientData *HeadFHCD;
2229
2230static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002231NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002232{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002233 FileHandler_ClientData *p;
2234 p = PyMem_NEW(FileHandler_ClientData, 1);
2235 if (p != NULL) {
2236 Py_XINCREF(func);
2237 Py_XINCREF(file);
2238 p->func = func;
2239 p->file = file;
2240 p->id = id;
2241 p->next = HeadFHCD;
2242 HeadFHCD = p;
2243 }
2244 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002245}
2246
2247static void
Fred Drake509d79a2000-07-08 04:04:38 +00002248DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002249{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002251
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 pp = &HeadFHCD;
2253 while ((p = *pp) != NULL) {
2254 if (p->id == id) {
2255 *pp = p->next;
2256 Py_XDECREF(p->func);
2257 Py_XDECREF(p->file);
2258 PyMem_DEL(p);
2259 }
2260 else
2261 pp = &p->next;
2262 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002263}
2264
Guido van Rossuma597dde1995-01-10 20:56:29 +00002265static void
Fred Drake509d79a2000-07-08 04:04:38 +00002266FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002267{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2269 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002271 ENTER_PYTHON
2272 func = data->func;
2273 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275 arg = Py_BuildValue("(Oi)", file, (long) mask);
2276 res = PyEval_CallObject(func, arg);
2277 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002278
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 if (res == NULL) {
2280 errorInCmd = 1;
2281 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2282 }
2283 Py_XDECREF(res);
2284 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002285}
2286
Guido van Rossum18468821994-06-20 07:49:28 +00002287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002288Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2289 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002290{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002291 FileHandler_ClientData *data;
2292 PyObject *file, *func;
2293 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002294
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2296 &file, &mask, &func))
2297 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 tfile = PyObject_AsFileDescriptor(file);
2302 if (tfile < 0)
2303 return NULL;
2304 if (!PyCallable_Check(func)) {
2305 PyErr_SetString(PyExc_TypeError, "bad argument list");
2306 return NULL;
2307 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 data = NewFHCD(func, file, tfile);
2310 if (data == NULL)
2311 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002313 /* Ought to check for null Tcl_File object... */
2314 ENTER_TCL
2315 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2316 LEAVE_TCL
2317 Py_INCREF(Py_None);
2318 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002319}
2320
2321static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002322Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002323{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002324 PyObject *file;
2325 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002327 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2328 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002331
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002332 tfile = PyObject_AsFileDescriptor(file);
2333 if (tfile < 0)
2334 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002338 /* Ought to check for null Tcl_File object... */
2339 ENTER_TCL
2340 Tcl_DeleteFileHandler(tfile);
2341 LEAVE_TCL
2342 Py_INCREF(Py_None);
2343 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002344}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002345#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002347
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348/**** Tktt Object (timer token) ****/
2349
Jeremy Hylton938ace62002-07-17 16:30:39 +00002350static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351
Guido van Rossum00d93061998-05-28 23:06:38 +00002352typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 PyObject_HEAD
2354 Tcl_TimerToken token;
2355 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002356} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357
2358static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002359Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002361 TkttObject *v = (TkttObject *)self;
2362 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2365 return NULL;
2366 if (v->token != NULL) {
2367 Tcl_DeleteTimerHandler(v->token);
2368 v->token = NULL;
2369 }
2370 if (func != NULL) {
2371 v->func = NULL;
2372 Py_DECREF(func);
2373 Py_DECREF(v); /* See Tktt_New() */
2374 }
2375 Py_INCREF(Py_None);
2376 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377}
2378
2379static PyMethodDef Tktt_methods[] =
2380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2382 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002383};
2384
2385static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002386Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002387{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002390 v = PyObject_New(TkttObject, &Tktt_Type);
2391 if (v == NULL)
2392 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002394 Py_INCREF(func);
2395 v->token = NULL;
2396 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398 /* Extra reference, deleted when called or when handler is deleted */
2399 Py_INCREF(v);
2400 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401}
2402
2403static void
Fred Drake509d79a2000-07-08 04:04:38 +00002404Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002405{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002406 TkttObject *v = (TkttObject *)self;
2407 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002411 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412}
2413
Guido van Rossum597ac201998-05-12 14:36:19 +00002414static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002415Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002417 TkttObject *v = (TkttObject *)self;
2418 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002420 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2421 v->func == NULL ? ", handler deleted" : "");
2422 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423}
2424
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002425static PyTypeObject Tktt_Type =
2426{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 PyVarObject_HEAD_INIT(NULL, 0)
2428 "tktimertoken", /*tp_name */
2429 sizeof(TkttObject), /*tp_basicsize */
2430 0, /*tp_itemsize */
2431 Tktt_Dealloc, /*tp_dealloc */
2432 0, /*tp_print */
2433 0, /*tp_getattr */
2434 0, /*tp_setattr */
2435 0, /*tp_reserved */
2436 Tktt_Repr, /*tp_repr */
2437 0, /*tp_as_number */
2438 0, /*tp_as_sequence */
2439 0, /*tp_as_mapping */
2440 0, /*tp_hash */
2441 0, /*tp_call*/
2442 0, /*tp_str*/
2443 0, /*tp_getattro*/
2444 0, /*tp_setattro*/
2445 0, /*tp_as_buffer*/
2446 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2447 0, /*tp_doc*/
2448 0, /*tp_traverse*/
2449 0, /*tp_clear*/
2450 0, /*tp_richcompare*/
2451 0, /*tp_weaklistoffset*/
2452 0, /*tp_iter*/
2453 0, /*tp_iternext*/
2454 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002455};
2456
Barry Warsawfa701a81997-01-16 00:15:11 +00002457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002458
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002459/** Timer Handler **/
2460
2461static void
Fred Drake509d79a2000-07-08 04:04:38 +00002462TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002463{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 TkttObject *v = (TkttObject *)clientData;
2465 PyObject *func = v->func;
2466 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 if (func == NULL)
2469 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 res = PyEval_CallObject(func, NULL);
2476 Py_DECREF(func);
2477 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002479 if (res == NULL) {
2480 errorInCmd = 1;
2481 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2482 }
2483 else
2484 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002486 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002487}
2488
2489static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002490Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002491{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002492 int milliseconds;
2493 PyObject *func;
2494 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002496 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2497 &milliseconds, &func))
2498 return NULL;
2499 if (!PyCallable_Check(func)) {
2500 PyErr_SetString(PyExc_TypeError, "bad argument list");
2501 return NULL;
2502 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 v = Tktt_New(func);
2507 if (v) {
2508 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2509 (ClientData)v);
2510 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002513}
2514
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002515
Guido van Rossum18468821994-06-20 07:49:28 +00002516/** Event Loop **/
2517
Guido van Rossum18468821994-06-20 07:49:28 +00002518static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002519Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002520{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002521 int threshold = 0;
2522 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002523#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002525#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002526
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002527 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2528 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002529
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002530 CHECK_TCL_APPARTMENT;
2531 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533 quitMainLoop = 0;
2534 while (Tk_GetNumMainWindows() > threshold &&
2535 !quitMainLoop &&
2536 !errorInCmd)
2537 {
2538 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002539
2540#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541 if (self->threaded) {
2542 /* Allow other Python threads to run. */
2543 ENTER_TCL
2544 result = Tcl_DoOneEvent(0);
2545 LEAVE_TCL
2546 }
2547 else {
2548 Py_BEGIN_ALLOW_THREADS
2549 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2550 tcl_tstate = tstate;
2551 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2552 tcl_tstate = NULL;
2553 if(tcl_lock)PyThread_release_lock(tcl_lock);
2554 if (result == 0)
2555 Sleep(Tkinter_busywaitinterval);
2556 Py_END_ALLOW_THREADS
2557 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002558#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002560#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002561
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 if (PyErr_CheckSignals() != 0) {
2563 self->dispatching = 0;
2564 return NULL;
2565 }
2566 if (result < 0)
2567 break;
2568 }
2569 self->dispatching = 0;
2570 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002571
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002572 if (errorInCmd) {
2573 errorInCmd = 0;
2574 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2575 excInCmd = valInCmd = trbInCmd = NULL;
2576 return NULL;
2577 }
2578 Py_INCREF(Py_None);
2579 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002580}
2581
2582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002583Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002584{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 int flags = 0;
2586 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002587
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002588 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2589 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 ENTER_TCL
2592 rv = Tcl_DoOneEvent(flags);
2593 LEAVE_TCL
2594 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002595}
2596
2597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002598Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002599{
2600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002601 if (!PyArg_ParseTuple(args, ":quit"))
2602 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 quitMainLoop = 1;
2605 Py_INCREF(Py_None);
2606 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002607}
2608
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002609static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002610Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002611{
2612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613 if (!PyArg_ParseTuple(args, ":interpaddr"))
2614 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002616 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002617}
2618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002620Tkapp_TkInit(PyObject *self, PyObject *args)
2621{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 Tcl_Interp *interp = Tkapp_Interp(self);
2623 const char * _tk_exists = NULL;
2624 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002625
Guilherme Polob681df42009-02-09 22:33:59 +00002626#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002627 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2628 * first call failed.
2629 * To avoid the deadlock, we just refuse the second call through
2630 * a static variable.
2631 */
2632 if (tk_load_failed) {
2633 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2634 return NULL;
2635 }
Guilherme Polob681df42009-02-09 22:33:59 +00002636#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002637
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002638 /* We want to guard against calling Tk_Init() multiple times */
2639 CHECK_TCL_APPARTMENT;
2640 ENTER_TCL
2641 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2642 ENTER_OVERLAP
2643 if (err == TCL_ERROR) {
2644 /* This sets an exception, but we cannot return right
2645 away because we need to exit the overlap first. */
2646 Tkinter_Error(self);
2647 } else {
2648 _tk_exists = Tkapp_Result(self);
2649 }
2650 LEAVE_OVERLAP_TCL
2651 if (err == TCL_ERROR) {
2652 return NULL;
2653 }
2654 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2655 if (Tk_Init(interp) == TCL_ERROR) {
2656 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002657#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002659#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 return NULL;
2661 }
2662 }
2663 Py_INCREF(Py_None);
2664 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002665}
Barry Warsawfa701a81997-01-16 00:15:11 +00002666
Martin v. Löwisffad6332002-11-26 09:28:05 +00002667static PyObject *
2668Tkapp_WantObjects(PyObject *self, PyObject *args)
2669{
2670
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 int wantobjects = -1;
2672 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2673 return NULL;
2674 if (wantobjects == -1)
2675 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2676 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678 Py_INCREF(Py_None);
2679 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002680}
2681
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002682static PyObject *
2683Tkapp_WillDispatch(PyObject *self, PyObject *args)
2684{
2685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 Py_INCREF(Py_None);
2689 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002690}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002691
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002692
Guido van Rossum18468821994-06-20 07:49:28 +00002693/**** Tkapp Method List ****/
2694
2695static PyMethodDef Tkapp_methods[] =
2696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002697 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2698 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2699 {"call", Tkapp_Call, METH_VARARGS},
2700 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2701 {"eval", Tkapp_Eval, METH_VARARGS},
2702 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2703 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2704 {"record", Tkapp_Record, METH_VARARGS},
2705 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2706 {"setvar", Tkapp_SetVar, METH_VARARGS},
2707 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2708 {"getvar", Tkapp_GetVar, METH_VARARGS},
2709 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2710 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2711 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2712 {"getint", Tkapp_GetInt, METH_VARARGS},
2713 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2714 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2715 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2716 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2717 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2718 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2719 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2720 {"split", Tkapp_Split, METH_VARARGS},
2721 {"merge", Tkapp_Merge, METH_VARARGS},
2722 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2723 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002724#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2726 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002727#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002728 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2729 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2730 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2731 {"quit", Tkapp_Quit, METH_VARARGS},
2732 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2733 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2734 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002735};
2736
Barry Warsawfa701a81997-01-16 00:15:11 +00002737
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738
Guido van Rossum18468821994-06-20 07:49:28 +00002739/**** Tkapp Type Methods ****/
2740
2741static void
Fred Drake509d79a2000-07-08 04:04:38 +00002742Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002743{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 /*CHECK_TCL_APPARTMENT;*/
2745 ENTER_TCL
2746 Tcl_DeleteInterp(Tkapp_Interp(self));
2747 LEAVE_TCL
2748 PyObject_Del(self);
2749 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002750}
2751
Guido van Rossum18468821994-06-20 07:49:28 +00002752static PyTypeObject Tkapp_Type =
2753{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 PyVarObject_HEAD_INIT(NULL, 0)
2755 "tkapp", /*tp_name */
2756 sizeof(TkappObject), /*tp_basicsize */
2757 0, /*tp_itemsize */
2758 Tkapp_Dealloc, /*tp_dealloc */
2759 0, /*tp_print */
2760 0, /*tp_getattr */
2761 0, /*tp_setattr */
2762 0, /*tp_reserved */
2763 0, /*tp_repr */
2764 0, /*tp_as_number */
2765 0, /*tp_as_sequence */
2766 0, /*tp_as_mapping */
2767 0, /*tp_hash */
2768 0, /*tp_call*/
2769 0, /*tp_str*/
2770 0, /*tp_getattro*/
2771 0, /*tp_setattro*/
2772 0, /*tp_as_buffer*/
2773 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2774 0, /*tp_doc*/
2775 0, /*tp_traverse*/
2776 0, /*tp_clear*/
2777 0, /*tp_richcompare*/
2778 0, /*tp_weaklistoffset*/
2779 0, /*tp_iter*/
2780 0, /*tp_iternext*/
2781 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002782};
2783
Barry Warsawfa701a81997-01-16 00:15:11 +00002784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002785
Guido van Rossum18468821994-06-20 07:49:28 +00002786/**** Tkinter Module ****/
2787
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002789 PyObject* tuple;
2790 int size; /* current size */
2791 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792} FlattenContext;
2793
2794static int
2795_bump(FlattenContext* context, int size)
2796{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002797 /* expand tuple to hold (at least) size new items.
2798 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002802 if (maxsize < context->size + size)
2803 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002807 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002808}
2809
2810static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002811_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002817 if (depth > 1000) {
2818 PyErr_SetString(PyExc_ValueError,
2819 "nesting too deep in _flatten");
2820 return 0;
2821 } else if (PyList_Check(item)) {
2822 size = PyList_GET_SIZE(item);
2823 /* preallocate (assume no nesting) */
2824 if (context->size + size > context->maxsize &&
2825 !_bump(context, size))
2826 return 0;
2827 /* copy items to output tuple */
2828 for (i = 0; i < size; i++) {
2829 PyObject *o = PyList_GET_ITEM(item, i);
2830 if (PyList_Check(o) || PyTuple_Check(o)) {
2831 if (!_flatten1(context, o, depth + 1))
2832 return 0;
2833 } else if (o != Py_None) {
2834 if (context->size + 1 > context->maxsize &&
2835 !_bump(context, 1))
2836 return 0;
2837 Py_INCREF(o);
2838 PyTuple_SET_ITEM(context->tuple,
2839 context->size++, o);
2840 }
2841 }
2842 } else if (PyTuple_Check(item)) {
2843 /* same, for tuples */
2844 size = PyTuple_GET_SIZE(item);
2845 if (context->size + size > context->maxsize &&
2846 !_bump(context, size))
2847 return 0;
2848 for (i = 0; i < size; i++) {
2849 PyObject *o = PyTuple_GET_ITEM(item, i);
2850 if (PyList_Check(o) || PyTuple_Check(o)) {
2851 if (!_flatten1(context, o, depth + 1))
2852 return 0;
2853 } else if (o != Py_None) {
2854 if (context->size + 1 > context->maxsize &&
2855 !_bump(context, 1))
2856 return 0;
2857 Py_INCREF(o);
2858 PyTuple_SET_ITEM(context->tuple,
2859 context->size++, o);
2860 }
2861 }
2862 } else {
2863 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2864 return 0;
2865 }
2866 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002867}
2868
2869static PyObject *
2870Tkinter_Flatten(PyObject* self, PyObject* args)
2871{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 FlattenContext context;
2873 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2876 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002877
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002878 context.maxsize = PySequence_Size(item);
2879 if (context.maxsize < 0)
2880 return NULL;
2881 if (context.maxsize == 0)
2882 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002884 context.tuple = PyTuple_New(context.maxsize);
2885 if (!context.tuple)
2886 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002889
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002890 if (!_flatten1(&context, item,0))
2891 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002892
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893 if (_PyTuple_Resize(&context.tuple, context.size))
2894 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002895
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002896 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002897}
2898
Guido van Rossum18468821994-06-20 07:49:28 +00002899static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002900Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002901{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002902 char *screenName = NULL;
2903 char *baseName = NULL; /* XXX this is not used anymore;
2904 try getting rid of it. */
2905 char *className = NULL;
2906 int interactive = 0;
2907 int wantobjects = 0;
2908 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2909 int sync = 0; /* pass -sync to wish */
2910 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002914 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2915 &screenName, &baseName, &className,
2916 &interactive, &wantobjects, &wantTk,
2917 &sync, &use))
2918 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002919
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002920 return (PyObject *) Tkapp_New(screenName, className,
2921 interactive, wantobjects, wantTk,
2922 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002923}
2924
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002925static PyObject *
2926Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2927{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002928 int new_val;
2929 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2930 return NULL;
2931 if (new_val < 0) {
2932 PyErr_SetString(PyExc_ValueError,
2933 "busywaitinterval must be >= 0");
2934 return NULL;
2935 }
2936 Tkinter_busywaitinterval = new_val;
2937 Py_INCREF(Py_None);
2938 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002939}
2940
2941static char setbusywaitinterval_doc[] =
2942"setbusywaitinterval(n) -> None\n\
2943\n\
2944Set the busy-wait interval in milliseconds between successive\n\
2945calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2946It should be set to a divisor of the maximum time between\n\
2947frames in an animation.";
2948
2949static PyObject *
2950Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2951{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002952 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002953}
2954
2955static char getbusywaitinterval_doc[] =
2956"getbusywaitinterval() -> int\n\
2957\n\
2958Return the current busy-wait interval between successive\n\
2959calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2960
Guido van Rossum18468821994-06-20 07:49:28 +00002961static PyMethodDef moduleMethods[] =
2962{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2964 {"create", Tkinter_Create, METH_VARARGS},
2965 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2966 setbusywaitinterval_doc},
2967 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2968 METH_NOARGS, getbusywaitinterval_doc},
2969 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002970};
2971
Guido van Rossum7bf15641998-05-22 18:28:17 +00002972#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973
2974static int stdin_ready = 0;
2975
Guido van Rossumad4db171998-06-13 13:56:28 +00002976#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977static void
Fred Drake509d79a2000-07-08 04:04:38 +00002978MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002980 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002981}
Guido van Rossumad4db171998-06-13 13:56:28 +00002982#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002983
Martin v. Löwisa9656492003-03-30 08:44:58 +00002984#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002985static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002986#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002987
Guido van Rossum18468821994-06-20 07:49:28 +00002988static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002989EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002990{
Guido van Rossumad4db171998-06-13 13:56:28 +00002991#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002992 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002993#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002994#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002996#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002997 stdin_ready = 0;
2998 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002999#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 tfile = fileno(stdin);
3001 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003002#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003003 while (!errorInCmd && !stdin_ready) {
3004 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003005#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003006 if (_kbhit()) {
3007 stdin_ready = 1;
3008 break;
3009 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003010#endif
3011#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 Py_BEGIN_ALLOW_THREADS
3013 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3014 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003018 tcl_tstate = NULL;
3019 if(tcl_lock)PyThread_release_lock(tcl_lock);
3020 if (result == 0)
3021 Sleep(Tkinter_busywaitinterval);
3022 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003023#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003024 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003025#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003026
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003027 if (result < 0)
3028 break;
3029 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003030#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003031 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003032#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003033 if (errorInCmd) {
3034 errorInCmd = 0;
3035 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3036 excInCmd = valInCmd = trbInCmd = NULL;
3037 PyErr_Print();
3038 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003039#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003041#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003042 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003043}
Guido van Rossum18468821994-06-20 07:49:28 +00003044
Guido van Rossum00d93061998-05-28 23:06:38 +00003045#endif
3046
Guido van Rossum7bf15641998-05-22 18:28:17 +00003047static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003048EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003049{
Guido van Rossum00d93061998-05-28 23:06:38 +00003050#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003052#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003054#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 PyOS_InputHook = EventHook;
3056 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003057#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003058}
3059
3060static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003061DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003062{
Guido van Rossum00d93061998-05-28 23:06:38 +00003063#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003064 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3065 PyOS_InputHook = NULL;
3066 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003067#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003068}
3069
Barry Warsawfa701a81997-01-16 00:15:11 +00003070
3071/* all errors will be checked in one fell swoop in init_tkinter() */
3072static void
Fred Drake509d79a2000-07-08 04:04:38 +00003073ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003075 PyObject *v = PyLong_FromLong(val);
3076 if (v) {
3077 PyDict_SetItemString(d, name, v);
3078 Py_DECREF(v);
3079 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003080}
3081static void
Fred Drake509d79a2000-07-08 04:04:38 +00003082ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003083{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003084 PyObject *v = PyUnicode_FromString(val);
3085 if (v) {
3086 PyDict_SetItemString(d, name, v);
3087 Py_DECREF(v);
3088 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003089}
3090
3091
Martin v. Löwis1a214512008-06-11 05:26:20 +00003092static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093 PyModuleDef_HEAD_INIT,
3094 "_tkinter",
3095 NULL,
3096 -1,
3097 moduleMethods,
3098 NULL,
3099 NULL,
3100 NULL,
3101 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003102};
3103
Mark Hammond62b1ab12002-07-23 06:31:15 +00003104PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003105PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003106{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003107 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003109 if (PyType_Ready(&Tkapp_Type) < 0)
3110 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003111
3112#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003114#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003115
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003116 m = PyModule_Create(&_tkintermodule);
3117 if (m == NULL)
3118 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003119
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003120 d = PyModule_GetDict(m);
3121 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3122 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 ins_long(d, "READABLE", TCL_READABLE);
3125 ins_long(d, "WRITABLE", TCL_WRITABLE);
3126 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3127 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3128 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3129 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3130 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3131 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3132 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3133 ins_string(d, "TK_VERSION", TK_VERSION);
3134 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 if (PyType_Ready(&Tktt_Type) < 0)
3139 return NULL;
3140 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3143 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003144
3145#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003146 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3147 * start waking up. Note that Tcl_FindExecutable will do this, this
3148 * code must be above it! The original warning from
3149 * tkMacOSXAppInit.c is copied below.
3150 *
3151 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3152 * Tcl interpreter for now. It probably should work to do this
3153 * in the other order, but for now it doesn't seem to.
3154 *
3155 */
3156 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003157#endif
3158
3159
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003160 /* This helps the dynamic loader; in Unicode aware Tcl versions
3161 it also helps Tcl find its encodings. */
3162 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3163 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003164 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003165 if (cexe)
3166 Tcl_FindExecutable(PyBytes_AsString(cexe));
3167 Py_XDECREF(cexe);
3168 Py_DECREF(uexe);
3169 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003170
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003171 if (PyErr_Occurred()) {
3172 Py_DECREF(m);
3173 return NULL;
3174 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003175
Guido van Rossum43ff8681998-07-14 18:02:13 +00003176#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003177 /* This was not a good idea; through <Destroy> bindings,
3178 Tcl_Finalize() may invoke Python code but at that point the
3179 interpreter and thread state have already been destroyed! */
3180 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003181#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003183}