blob: cb2795f7d96add7c2c86c1ce6cc9e7b4eb1e5e43 [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);
664 if (isupper(Py_CHARMASK(argv0[0])))
665 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
666 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. */
996 PyErr_SetString(PyExc_ValueError,
997 "unsupported character");
998 ckfree(FREECAST outbuf);
999 return NULL;
1000 }
1001 outbuf[i] = inbuf[i];
1002 }
1003 result = Tcl_NewUnicodeObj(outbuf, size);
1004 ckfree(FREECAST outbuf);
1005 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001006#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001007 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001008#endif
1009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001010 }
1011 else if(PyTclObject_Check(value)) {
1012 Tcl_Obj *v = ((PyTclObject*)value)->value;
1013 Tcl_IncrRefCount(v);
1014 return v;
1015 }
1016 else {
1017 PyObject *v = PyObject_Str(value);
1018 if (!v)
1019 return 0;
1020 result = AsObj(v);
1021 Py_DECREF(v);
1022 return result;
1023 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001024}
1025
Martin v. Löwisffad6332002-11-26 09:28:05 +00001026static PyObject*
1027FromObj(PyObject* tkapp, Tcl_Obj *value)
1028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 PyObject *result = NULL;
1030 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001031
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001032 if (value->typePtr == NULL) {
1033 return PyUnicode_FromStringAndSize(value->bytes,
1034 value->length);
1035 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (value->typePtr == app->BooleanType) {
1038 result = value->internalRep.longValue ? Py_True : Py_False;
1039 Py_INCREF(result);
1040 return result;
1041 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001042
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 if (value->typePtr == app->ByteArrayType) {
1044 int size;
1045 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1046 return PyBytes_FromStringAndSize(data, size);
1047 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 if (value->typePtr == app->DoubleType) {
1050 return PyFloat_FromDouble(value->internalRep.doubleValue);
1051 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001053 if (value->typePtr == app->IntType) {
1054 return PyLong_FromLong(value->internalRep.longValue);
1055 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 if (value->typePtr == app->ListType) {
1058 int size;
1059 int i, status;
1060 PyObject *elem;
1061 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1064 if (status == TCL_ERROR)
1065 return Tkinter_Error(tkapp);
1066 result = PyTuple_New(size);
1067 if (!result)
1068 return NULL;
1069 for (i = 0; i < size; i++) {
1070 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1071 value, i, &tcl_elem);
1072 if (status == TCL_ERROR) {
1073 Py_DECREF(result);
1074 return Tkinter_Error(tkapp);
1075 }
1076 elem = FromObj(tkapp, tcl_elem);
1077 if (!elem) {
1078 Py_DECREF(result);
1079 return NULL;
1080 }
1081 PyTuple_SetItem(result, i, elem);
1082 }
1083 return result;
1084 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001085
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 if (value->typePtr == app->ProcBodyType) {
1087 /* fall through: return tcl object. */
1088 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001089
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001090 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001091#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 PyObject *result;
1093 int size;
1094 Tcl_UniChar *input;
1095 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001096
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 size = Tcl_GetCharLength(value);
1098 result = PyUnicode_FromUnicode(NULL, size);
1099 if (!result)
1100 return NULL;
1101 input = Tcl_GetUnicode(value);
1102 output = PyUnicode_AS_UNICODE(result);
1103 while (size--)
1104 *output++ = *input++;
1105 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001106#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1108 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001109#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001110 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001112 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001113}
1114
Benjamin Peterson5879d412009-03-30 14:51:56 +00001115#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001116/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001117TCL_DECLARE_MUTEX(call_mutex)
1118
1119typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001120 Tcl_Event ev; /* Must be first */
1121 TkappObject *self;
1122 PyObject *args;
1123 int flags;
1124 PyObject **res;
1125 PyObject **exc_type, **exc_value, **exc_tb;
1126 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001127} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001128#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001129
1130void
1131Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 int i;
1134 for (i = 0; i < objc; i++)
1135 Tcl_DecrRefCount(objv[i]);
1136 if (objv != objStore)
1137 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001138}
Guido van Rossum18468821994-06-20 07:49:28 +00001139
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001140/* Convert Python objects to Tcl objects. This must happen in the
1141 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001142
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001143static Tcl_Obj**
1144Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1145{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 Tcl_Obj **objv = objStore;
1147 int objc = 0, i;
1148 if (args == NULL)
1149 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 else if (!PyTuple_Check(args)) {
1152 objv[0] = AsObj(args);
1153 if (objv[0] == 0)
1154 goto finally;
1155 objc = 1;
1156 Tcl_IncrRefCount(objv[0]);
1157 }
1158 else {
1159 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001160
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001161 if (objc > ARGSZ) {
1162 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1163 if (objv == NULL) {
1164 PyErr_NoMemory();
1165 objc = 0;
1166 goto finally;
1167 }
1168 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001169
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 for (i = 0; i < objc; i++) {
1171 PyObject *v = PyTuple_GetItem(args, i);
1172 if (v == Py_None) {
1173 objc = i;
1174 break;
1175 }
1176 objv[i] = AsObj(v);
1177 if (!objv[i]) {
1178 /* Reset objc, so it attempts to clear
1179 objects only up to i. */
1180 objc = i;
1181 goto finally;
1182 }
1183 Tcl_IncrRefCount(objv[i]);
1184 }
1185 }
1186 *pobjc = objc;
1187 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001188finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001189 Tkapp_CallDeallocArgs(objv, objStore, objc);
1190 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001191}
Guido van Rossum212643f1998-04-29 16:22:14 +00001192
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001194
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001195static PyObject*
1196Tkapp_CallResult(TkappObject *self)
1197{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001198 PyObject *res = NULL;
1199 if(self->wantobjects) {
1200 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1201 /* Not sure whether the IncrRef is necessary, but something
1202 may overwrite the interpreter result while we are
1203 converting it. */
1204 Tcl_IncrRefCount(value);
1205 res = FromObj((PyObject*)self, value);
1206 Tcl_DecrRefCount(value);
1207 } else {
1208 const char *s = Tcl_GetStringResult(self->interp);
1209 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1212 }
1213 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214}
Guido van Rossum632de272000-03-29 00:19:50 +00001215
Benjamin Peterson5879d412009-03-30 14:51:56 +00001216#ifdef WITH_THREAD
1217
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218/* Tkapp_CallProc is the event procedure that is executed in the context of
1219 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1220 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001221
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222static int
1223Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1224{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 Tcl_Obj *objStore[ARGSZ];
1226 Tcl_Obj **objv;
1227 int objc;
1228 int i;
1229 ENTER_PYTHON
1230 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1231 if (!objv) {
1232 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1233 *(e->res) = NULL;
1234 }
1235 LEAVE_PYTHON
1236 if (!objv)
1237 goto done;
1238 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1239 ENTER_PYTHON
1240 if (i == TCL_ERROR) {
1241 *(e->res) = NULL;
1242 *(e->exc_type) = NULL;
1243 *(e->exc_tb) = NULL;
1244 *(e->exc_value) = PyObject_CallFunction(
1245 Tkinter_TclError, "s",
1246 Tcl_GetStringResult(e->self->interp));
1247 }
1248 else {
1249 *(e->res) = Tkapp_CallResult(e->self);
1250 }
1251 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001252
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001254done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 /* Wake up calling thread. */
1256 Tcl_MutexLock(&call_mutex);
1257 Tcl_ConditionNotify(e->done);
1258 Tcl_MutexUnlock(&call_mutex);
1259 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001260}
1261
Benjamin Peterson5879d412009-03-30 14:51:56 +00001262#endif
1263
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264/* This is the main entry point for calling a Tcl command.
1265 It supports three cases, with regard to threading:
1266 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1267 the context of the calling thread.
1268 2. Tcl is threaded, caller of the command is in the interpreter thread:
1269 Execute the command in the calling thread. Since the Tcl lock will
1270 not be used, we can merge that with case 1.
1271 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1272 the interpreter thread. Allocation of Tcl objects needs to occur in the
1273 interpreter thread, so we ship the PyObject* args to the target thread,
1274 and perform processing there. */
1275
1276static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001277Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001279 Tcl_Obj *objStore[ARGSZ];
1280 Tcl_Obj **objv = NULL;
1281 int objc, i;
1282 PyObject *res = NULL;
1283 TkappObject *self = (TkappObject*)selfptr;
1284 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001286 /* If args is a single tuple, replace with contents of tuple */
1287 if (1 == PyTuple_Size(args)){
1288 PyObject* item = PyTuple_GetItem(args, 0);
1289 if (PyTuple_Check(item))
1290 args = item;
1291 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001292#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001293 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1294 /* We cannot call the command directly. Instead, we must
1295 marshal the parameters to the interpreter thread. */
1296 Tkapp_CallEvent *ev;
1297 Tcl_Condition cond = NULL;
1298 PyObject *exc_type, *exc_value, *exc_tb;
1299 if (!WaitForMainloop(self))
1300 return NULL;
1301 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1302 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1303 ev->self = self;
1304 ev->args = args;
1305 ev->res = &res;
1306 ev->exc_type = &exc_type;
1307 ev->exc_value = &exc_value;
1308 ev->exc_tb = &exc_tb;
1309 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001311 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001313 if (res == NULL) {
1314 if (exc_type)
1315 PyErr_Restore(exc_type, exc_value, exc_tb);
1316 else
1317 PyErr_SetObject(Tkinter_TclError, exc_value);
1318 }
1319 Tcl_ConditionFinalize(&cond);
1320 }
1321 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001322#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 objv = Tkapp_CallArgs(args, objStore, &objc);
1326 if (!objv)
1327 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001333 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001335 if (i == TCL_ERROR)
1336 Tkinter_Error(selfptr);
1337 else
1338 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 Tkapp_CallDeallocArgs(objv, objStore, objc);
1343 }
1344 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001345}
1346
1347
1348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001349Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001350{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 /* Could do the same here as for Tkapp_Call(), but this is not used
1352 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353 way for the user to do what all its Global* variants do (save and
1354 reset the scope pointer, call the local version, restore the saved
1355 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 char *cmd;
1358 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001362 cmd = Merge(args);
1363 if (cmd) {
1364 int err;
1365 ENTER_TCL
1366 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1367 ENTER_OVERLAP
1368 if (err == TCL_ERROR)
1369 res = Tkinter_Error(self);
1370 else
1371 res = PyUnicode_FromString(Tkapp_Result(self));
1372 LEAVE_OVERLAP_TCL
1373 ckfree(cmd);
1374 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001376 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001377}
1378
1379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001380Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001381{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 char *script;
1383 PyObject *res = NULL;
1384 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001386 if (!PyArg_ParseTuple(args, "s:eval", &script))
1387 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001389 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001391 ENTER_TCL
1392 err = Tcl_Eval(Tkapp_Interp(self), script);
1393 ENTER_OVERLAP
1394 if (err == TCL_ERROR)
1395 res = Tkinter_Error(self);
1396 else
1397 res = PyUnicode_FromString(Tkapp_Result(self));
1398 LEAVE_OVERLAP_TCL
1399 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001400}
1401
1402static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001403Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001404{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001405 char *script;
1406 PyObject *res = NULL;
1407 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001409 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1410 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001412 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001414 ENTER_TCL
1415 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1416 ENTER_OVERLAP
1417 if (err == TCL_ERROR)
1418 res = Tkinter_Error(self);
1419 else
1420 res = PyUnicode_FromString(Tkapp_Result(self));
1421 LEAVE_OVERLAP_TCL
1422 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001423}
1424
1425static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001426Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001427{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001428 char *fileName;
1429 PyObject *res = NULL;
1430 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001432 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1433 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001434
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001435 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001437 ENTER_TCL
1438 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1439 ENTER_OVERLAP
1440 if (err == TCL_ERROR)
1441 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 else
1444 res = PyUnicode_FromString(Tkapp_Result(self));
1445 LEAVE_OVERLAP_TCL
1446 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001447}
1448
1449static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001450Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001451{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 char *script;
1453 PyObject *res = NULL;
1454 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001456 if (!PyArg_ParseTuple(args, "s", &script))
1457 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 ENTER_TCL
1462 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1463 ENTER_OVERLAP
1464 if (err == TCL_ERROR)
1465 res = Tkinter_Error(self);
1466 else
1467 res = PyUnicode_FromString(Tkapp_Result(self));
1468 LEAVE_OVERLAP_TCL
1469 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001470}
1471
1472static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001473Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001474{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1478 return NULL;
1479 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 ENTER_TCL
1482 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1483 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001484
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 Py_INCREF(Py_None);
1486 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001487}
1488
Barry Warsawfa701a81997-01-16 00:15:11 +00001489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490
Guido van Rossum18468821994-06-20 07:49:28 +00001491/** Tcl Variable **/
1492
Benjamin Peterson5879d412009-03-30 14:51:56 +00001493typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1494
1495#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496TCL_DECLARE_MUTEX(var_mutex)
1497
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001499 Tcl_Event ev; /* must be first */
1500 PyObject *self;
1501 PyObject *args;
1502 int flags;
1503 EventFunc func;
1504 PyObject **res;
1505 PyObject **exc_type;
1506 PyObject **exc_val;
1507 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001508} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001509#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001511static int
1512varname_converter(PyObject *in, void *_out)
1513{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 char **out = (char**)_out;
1515 if (PyBytes_Check(in)) {
1516 *out = PyBytes_AsString(in);
1517 return 1;
1518 }
1519 if (PyUnicode_Check(in)) {
1520 *out = _PyUnicode_AsString(in);
1521 return 1;
1522 }
1523 if (PyTclObject_Check(in)) {
1524 *out = PyTclObject_TclString(in);
1525 return 1;
1526 }
1527 /* XXX: Should give diagnostics. */
1528 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001529}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001530
Benjamin Peterson5879d412009-03-30 14:51:56 +00001531#ifdef WITH_THREAD
1532
Martin v. Löwis59683e82008-06-13 07:50:45 +00001533static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534var_perform(VarEvent *ev)
1535{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1537 if (!*(ev->res)) {
1538 PyObject *exc, *val, *tb;
1539 PyErr_Fetch(&exc, &val, &tb);
1540 PyErr_NormalizeException(&exc, &val, &tb);
1541 *(ev->exc_type) = exc;
1542 *(ev->exc_val) = val;
1543 Py_DECREF(tb);
1544 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001545
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546}
1547
1548static int
1549var_proc(VarEvent* ev, int flags)
1550{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 ENTER_PYTHON
1552 var_perform(ev);
1553 Tcl_MutexLock(&var_mutex);
1554 Tcl_ConditionNotify(ev->cond);
1555 Tcl_MutexUnlock(&var_mutex);
1556 LEAVE_PYTHON
1557 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558}
1559
Benjamin Peterson5879d412009-03-30 14:51:56 +00001560#endif
1561
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001562static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001563var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001565#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 TkappObject *self = (TkappObject*)selfptr;
1567 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1568 TkappObject *self = (TkappObject*)selfptr;
1569 VarEvent *ev;
1570 PyObject *res, *exc_type, *exc_val;
1571 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 /* The current thread is not the interpreter thread. Marshal
1574 the call to the interpreter thread, then wait for
1575 completion. */
1576 if (!WaitForMainloop(self))
1577 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001580
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001581 ev->self = selfptr;
1582 ev->args = args;
1583 ev->flags = flags;
1584 ev->func = func;
1585 ev->res = &res;
1586 ev->exc_type = &exc_type;
1587 ev->exc_val = &exc_val;
1588 ev->cond = &cond;
1589 ev->ev.proc = (Tcl_EventProc*)var_proc;
1590 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1591 Tcl_ConditionFinalize(&cond);
1592 if (!res) {
1593 PyErr_SetObject(exc_type, exc_val);
1594 Py_DECREF(exc_type);
1595 Py_DECREF(exc_val);
1596 return NULL;
1597 }
1598 return res;
1599 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001600#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001601 /* Tcl is not threaded, or this is the interpreter thread. */
1602 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001603}
1604
Guido van Rossum18468821994-06-20 07:49:28 +00001605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001606SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001607{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001608 char *name1, *name2;
1609 PyObject *newValue;
1610 PyObject *res = NULL;
1611 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001613 if (PyArg_ParseTuple(args, "O&O:setvar",
1614 varname_converter, &name1, &newValue)) {
1615 /* XXX Acquire tcl lock??? */
1616 newval = AsObj(newValue);
1617 if (newval == NULL)
1618 return NULL;
1619 ENTER_TCL
1620 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1621 newval, flags);
1622 ENTER_OVERLAP
1623 if (!ok)
1624 Tkinter_Error(self);
1625 else {
1626 res = Py_None;
1627 Py_INCREF(res);
1628 }
1629 LEAVE_OVERLAP_TCL
1630 }
1631 else {
1632 PyErr_Clear();
1633 if (PyArg_ParseTuple(args, "ssO:setvar",
1634 &name1, &name2, &newValue)) {
1635 /* XXX must hold tcl lock already??? */
1636 newval = AsObj(newValue);
1637 ENTER_TCL
1638 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1639 ENTER_OVERLAP
1640 if (!ok)
1641 Tkinter_Error(self);
1642 else {
1643 res = Py_None;
1644 Py_INCREF(res);
1645 }
1646 LEAVE_OVERLAP_TCL
1647 }
1648 else {
1649 return NULL;
1650 }
1651 }
1652 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001653}
1654
1655static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001656Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001657{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001658 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
Barry Warsawfa701a81997-01-16 00:15:11 +00001667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668
Guido van Rossum18468821994-06-20 07:49:28 +00001669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 char *name1, *name2=NULL;
1673 PyObject *res = NULL;
1674 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001676 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1677 varname_converter, &name1, &name2))
1678 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001679
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001680 ENTER_TCL
1681 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1682 ENTER_OVERLAP
1683 if (tres == NULL) {
1684 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1685 } else {
1686 if (((TkappObject*)self)->wantobjects) {
1687 res = FromObj(self, tres);
1688 }
1689 else {
1690 res = PyUnicode_FromString(Tcl_GetString(tres));
1691 }
1692 }
1693 LEAVE_OVERLAP_TCL
1694 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001695}
1696
1697static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001698Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001699{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001700 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001701}
1702
1703static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001704Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001706 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
Barry Warsawfa701a81997-01-16 00:15:11 +00001709
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001710
Guido van Rossum18468821994-06-20 07:49:28 +00001711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001714 char *name1, *name2=NULL;
1715 int code;
1716 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1719 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001721 ENTER_TCL
1722 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1723 ENTER_OVERLAP
1724 if (code == TCL_ERROR)
1725 res = Tkinter_Error(self);
1726 else {
1727 Py_INCREF(Py_None);
1728 res = Py_None;
1729 }
1730 LEAVE_OVERLAP_TCL
1731 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001732}
1733
1734static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001735Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001736{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001737 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
1740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001744}
1745
Barry Warsawfa701a81997-01-16 00:15:11 +00001746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001747
Guido van Rossum18468821994-06-20 07:49:28 +00001748/** Tcl to Python **/
1749
1750static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001751Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001752{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753 char *s;
1754 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001755
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001756 if (PyTuple_Size(args) == 1) {
1757 PyObject* o = PyTuple_GetItem(args, 0);
1758 if (PyLong_Check(o)) {
1759 Py_INCREF(o);
1760 return o;
1761 }
1762 }
1763 if (!PyArg_ParseTuple(args, "s:getint", &s))
1764 return NULL;
1765 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1766 return Tkinter_Error(self);
1767 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 char *s;
1774 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001776 if (PyTuple_Size(args) == 1) {
1777 PyObject *o = PyTuple_GetItem(args, 0);
1778 if (PyFloat_Check(o)) {
1779 Py_INCREF(o);
1780 return o;
1781 }
1782 }
1783 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1784 return NULL;
1785 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786 return Tkinter_Error(self);
1787 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
1790static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001791Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001792{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001793 char *s;
1794 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001796 if (PyTuple_Size(args) == 1) {
1797 PyObject *o = PyTuple_GetItem(args, 0);
1798 if (PyLong_Check(o)) {
1799 Py_INCREF(o);
1800 return o;
1801 }
1802 }
1803 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1804 return NULL;
1805 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1806 return Tkinter_Error(self);
1807 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
1810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001813 char *s;
1814 PyObject *res = NULL;
1815 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001816
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1818 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001819
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822 ENTER_TCL
1823 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1824 ENTER_OVERLAP
1825 if (retval == TCL_ERROR)
1826 res = Tkinter_Error(self);
1827 else
1828 res = Py_BuildValue("s", Tkapp_Result(self));
1829 LEAVE_OVERLAP_TCL
1830 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001831}
1832
1833static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001834Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001835{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001836 char *s;
1837 PyObject *res = NULL;
1838 int retval;
1839 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001840
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001841 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1842 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001843
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001844 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001845
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001846 ENTER_TCL
1847 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1848 ENTER_OVERLAP
1849 if (retval == TCL_ERROR)
1850 res = Tkinter_Error(self);
1851 else
1852 res = Py_BuildValue("l", v);
1853 LEAVE_OVERLAP_TCL
1854 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001855}
1856
1857static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001858Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 char *s;
1861 PyObject *res = NULL;
1862 double v;
1863 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001864
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001865 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1866 return NULL;
1867 CHECK_TCL_APPARTMENT;
1868 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1869 ENTER_TCL
1870 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1871 ENTER_OVERLAP
1872 PyFPE_END_PROTECT(retval)
1873 if (retval == TCL_ERROR)
1874 res = Tkinter_Error(self);
1875 else
1876 res = Py_BuildValue("d", v);
1877 LEAVE_OVERLAP_TCL
1878 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
1881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001882Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001883{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 char *s;
1885 PyObject *res = NULL;
1886 int retval;
1887 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1890 return NULL;
1891 CHECK_TCL_APPARTMENT;
1892 ENTER_TCL
1893 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1894 ENTER_OVERLAP
1895 if (retval == TCL_ERROR)
1896 res = Tkinter_Error(self);
1897 else
1898 res = Py_BuildValue("i", v);
1899 LEAVE_OVERLAP_TCL
1900 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001901}
1902
Barry Warsawfa701a81997-01-16 00:15:11 +00001903
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001904
Guido van Rossum18468821994-06-20 07:49:28 +00001905static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001906Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 char *list;
1909 int argc;
1910 char **argv;
1911 PyObject *v;
1912 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 if (PyTuple_Size(args) == 1) {
1915 v = PyTuple_GetItem(args, 0);
1916 if (PyTuple_Check(v)) {
1917 Py_INCREF(v);
1918 return v;
1919 }
1920 }
1921 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1922 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001924 if (Tcl_SplitList(Tkapp_Interp(self), list,
1925 &argc, &argv) == TCL_ERROR) {
1926 PyMem_Free(list);
1927 return Tkinter_Error(self);
1928 }
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001930 if (!(v = PyTuple_New(argc)))
1931 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001933 for (i = 0; i < argc; i++) {
1934 PyObject *s = PyUnicode_FromString(argv[i]);
1935 if (!s || PyTuple_SetItem(v, i, s)) {
1936 Py_DECREF(v);
1937 v = NULL;
1938 goto finally;
1939 }
1940 }
Guido van Rossum18468821994-06-20 07:49:28 +00001941
Barry Warsawfa701a81997-01-16 00:15:11 +00001942 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001943 ckfree(FREECAST argv);
1944 PyMem_Free(list);
1945 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 PyObject *v;
1952 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001954 if (PyTuple_Size(args) == 1) {
1955 PyObject* o = PyTuple_GetItem(args, 0);
1956 if (PyTuple_Check(o)) {
1957 o = SplitObj(o);
1958 return o;
1959 }
1960 }
1961 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1962 return NULL;
1963 v = Split(list);
1964 PyMem_Free(list);
1965 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001966}
1967
1968static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001969Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001970{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 char *s = Merge(args);
1972 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001974 if (s) {
1975 res = PyUnicode_FromString(s);
1976 ckfree(s);
1977 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001978
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001980}
1981
Barry Warsawfa701a81997-01-16 00:15:11 +00001982
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001983
Guido van Rossum18468821994-06-20 07:49:28 +00001984/** Tcl Command **/
1985
Guido van Rossum00d93061998-05-28 23:06:38 +00001986/* Client data struct */
1987typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001988 PyObject *self;
1989 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001990} PythonCmd_ClientData;
1991
1992static int
Fred Drake509d79a2000-07-08 04:04:38 +00001993PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001994{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 errorInCmd = 1;
1996 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1997 LEAVE_PYTHON
1998 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001999}
2000
Guido van Rossum18468821994-06-20 07:49:28 +00002001/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002002 * function or method.
2003 */
Guido van Rossum18468821994-06-20 07:49:28 +00002004static int
Fred Drake509d79a2000-07-08 04:04:38 +00002005PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002006{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002007 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2008 PyObject *self, *func, *arg, *res;
2009 int i, rv;
2010 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002012 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 /* TBD: no error checking here since we know, via the
2015 * Tkapp_CreateCommand() that the client data is a two-tuple
2016 */
2017 self = data->self;
2018 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002020 /* Create argument list (argv1, ..., argvN) */
2021 if (!(arg = PyTuple_New(argc - 1)))
2022 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002024 for (i = 0; i < (argc - 1); i++) {
2025 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002026 if (!s) {
2027 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2028 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2029 !strcmp(argv[i + 1], "\xC0\x80")) {
2030 PyErr_Clear();
2031 /* Convert to "strict" utf-8 null */
2032 s = PyUnicode_FromString("\0");
2033 } else {
2034 Py_DECREF(arg);
2035 return PythonCmd_Error(interp);
2036 }
2037 }
2038 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 Py_DECREF(arg);
2040 return PythonCmd_Error(interp);
2041 }
2042 }
2043 res = PyEval_CallObject(func, arg);
2044 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002046 if (res == NULL)
2047 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002048
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002049 obj_res = AsObj(res);
2050 if (obj_res == NULL) {
2051 Py_DECREF(res);
2052 return PythonCmd_Error(interp);
2053 }
2054 else {
2055 Tcl_SetObjResult(interp, obj_res);
2056 rv = TCL_OK;
2057 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002058
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002060
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002064}
2065
2066static void
Fred Drake509d79a2000-07-08 04:04:38 +00002067PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 ENTER_PYTHON
2072 Py_XDECREF(data->self);
2073 Py_XDECREF(data->func);
2074 PyMem_DEL(data);
2075 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002076}
2077
Barry Warsawfa701a81997-01-16 00:15:11 +00002078
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002079
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002080
Benjamin Peterson5879d412009-03-30 14:51:56 +00002081#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002082TCL_DECLARE_MUTEX(command_mutex)
2083
2084typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 Tcl_Event ev;
2086 Tcl_Interp* interp;
2087 char *name;
2088 int create;
2089 int *status;
2090 ClientData *data;
2091 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002092} CommandEvent;
2093
2094static int
2095Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002096{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002097 if (ev->create)
2098 *ev->status = Tcl_CreateCommand(
2099 ev->interp, ev->name, PythonCmd,
2100 ev->data, PythonCmdDelete) == NULL;
2101 else
2102 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2103 Tcl_MutexLock(&command_mutex);
2104 Tcl_ConditionNotify(ev->done);
2105 Tcl_MutexUnlock(&command_mutex);
2106 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002108#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002109
2110static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002111Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002112{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002113 TkappObject *self = (TkappObject*)selfptr;
2114 PythonCmd_ClientData *data;
2115 char *cmdName;
2116 PyObject *func;
2117 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002119 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2120 return NULL;
2121 if (!PyCallable_Check(func)) {
2122 PyErr_SetString(PyExc_TypeError, "command not callable");
2123 return NULL;
2124 }
Guido van Rossum18468821994-06-20 07:49:28 +00002125
Martin v. Löwisa9656492003-03-30 08:44:58 +00002126#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2128 !WaitForMainloop(self))
2129 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002130#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 data = PyMem_NEW(PythonCmd_ClientData, 1);
2133 if (!data)
2134 return PyErr_NoMemory();
2135 Py_INCREF(self);
2136 Py_INCREF(func);
2137 data->self = selfptr;
2138 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002139#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002140 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2141 Tcl_Condition cond = NULL;
2142 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2143 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2144 ev->interp = self->interp;
2145 ev->create = 1;
2146 ev->name = cmdName;
2147 ev->data = (ClientData)data;
2148 ev->status = &err;
2149 ev->done = &cond;
2150 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2151 Tcl_ConditionFinalize(&cond);
2152 }
2153 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002154#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002155 {
2156 ENTER_TCL
2157 err = Tcl_CreateCommand(
2158 Tkapp_Interp(self), cmdName, PythonCmd,
2159 (ClientData)data, PythonCmdDelete) == NULL;
2160 LEAVE_TCL
2161 }
2162 if (err) {
2163 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2164 PyMem_DEL(data);
2165 return NULL;
2166 }
Guido van Rossum18468821994-06-20 07:49:28 +00002167
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 Py_INCREF(Py_None);
2169 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002170}
2171
Barry Warsawfa701a81997-01-16 00:15:11 +00002172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173
Guido van Rossum18468821994-06-20 07:49:28 +00002174static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002175Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002176{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002177 TkappObject *self = (TkappObject*)selfptr;
2178 char *cmdName;
2179 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002181 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2182 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002183
2184#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2186 Tcl_Condition cond = NULL;
2187 CommandEvent *ev;
2188 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2189 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2190 ev->interp = self->interp;
2191 ev->create = 0;
2192 ev->name = cmdName;
2193 ev->status = &err;
2194 ev->done = &cond;
2195 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2196 &command_mutex);
2197 Tcl_ConditionFinalize(&cond);
2198 }
2199 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002200#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002201 {
2202 ENTER_TCL
2203 err = Tcl_DeleteCommand(self->interp, cmdName);
2204 LEAVE_TCL
2205 }
2206 if (err == -1) {
2207 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2208 return NULL;
2209 }
2210 Py_INCREF(Py_None);
2211 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002212}
2213
Barry Warsawfa701a81997-01-16 00:15:11 +00002214
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215
Guido van Rossum00d93061998-05-28 23:06:38 +00002216#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002217/** File Handler **/
2218
Guido van Rossum00d93061998-05-28 23:06:38 +00002219typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002220 PyObject *func;
2221 PyObject *file;
2222 int id;
2223 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002224} FileHandler_ClientData;
2225
2226static FileHandler_ClientData *HeadFHCD;
2227
2228static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002229NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 FileHandler_ClientData *p;
2232 p = PyMem_NEW(FileHandler_ClientData, 1);
2233 if (p != NULL) {
2234 Py_XINCREF(func);
2235 Py_XINCREF(file);
2236 p->func = func;
2237 p->file = file;
2238 p->id = id;
2239 p->next = HeadFHCD;
2240 HeadFHCD = p;
2241 }
2242 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002243}
2244
2245static void
Fred Drake509d79a2000-07-08 04:04:38 +00002246DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002247{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002248 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002250 pp = &HeadFHCD;
2251 while ((p = *pp) != NULL) {
2252 if (p->id == id) {
2253 *pp = p->next;
2254 Py_XDECREF(p->func);
2255 Py_XDECREF(p->file);
2256 PyMem_DEL(p);
2257 }
2258 else
2259 pp = &p->next;
2260 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002261}
2262
Guido van Rossuma597dde1995-01-10 20:56:29 +00002263static void
Fred Drake509d79a2000-07-08 04:04:38 +00002264FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002265{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002266 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2267 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002269 ENTER_PYTHON
2270 func = data->func;
2271 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 arg = Py_BuildValue("(Oi)", file, (long) mask);
2274 res = PyEval_CallObject(func, arg);
2275 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002276
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002277 if (res == NULL) {
2278 errorInCmd = 1;
2279 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2280 }
2281 Py_XDECREF(res);
2282 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002283}
2284
Guido van Rossum18468821994-06-20 07:49:28 +00002285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002286Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2287 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002288{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 FileHandler_ClientData *data;
2290 PyObject *file, *func;
2291 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002293 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2294 &file, &mask, &func))
2295 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002297 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002299 tfile = PyObject_AsFileDescriptor(file);
2300 if (tfile < 0)
2301 return NULL;
2302 if (!PyCallable_Check(func)) {
2303 PyErr_SetString(PyExc_TypeError, "bad argument list");
2304 return NULL;
2305 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002307 data = NewFHCD(func, file, tfile);
2308 if (data == NULL)
2309 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002310
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002311 /* Ought to check for null Tcl_File object... */
2312 ENTER_TCL
2313 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2314 LEAVE_TCL
2315 Py_INCREF(Py_None);
2316 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002317}
2318
2319static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002320Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002321{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 PyObject *file;
2323 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002325 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2326 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002327
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 tfile = PyObject_AsFileDescriptor(file);
2331 if (tfile < 0)
2332 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002334 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002336 /* Ought to check for null Tcl_File object... */
2337 ENTER_TCL
2338 Tcl_DeleteFileHandler(tfile);
2339 LEAVE_TCL
2340 Py_INCREF(Py_None);
2341 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002342}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002343#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346/**** Tktt Object (timer token) ****/
2347
Jeremy Hylton938ace62002-07-17 16:30:39 +00002348static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002349
Guido van Rossum00d93061998-05-28 23:06:38 +00002350typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002351 PyObject_HEAD
2352 Tcl_TimerToken token;
2353 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002354} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002355
2356static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002357Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 TkttObject *v = (TkttObject *)self;
2360 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002361
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002362 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2363 return NULL;
2364 if (v->token != NULL) {
2365 Tcl_DeleteTimerHandler(v->token);
2366 v->token = NULL;
2367 }
2368 if (func != NULL) {
2369 v->func = NULL;
2370 Py_DECREF(func);
2371 Py_DECREF(v); /* See Tktt_New() */
2372 }
2373 Py_INCREF(Py_None);
2374 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375}
2376
2377static PyMethodDef Tktt_methods[] =
2378{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2380 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381};
2382
2383static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002384Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002385{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002386 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002387
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002388 v = PyObject_New(TkttObject, &Tktt_Type);
2389 if (v == NULL)
2390 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392 Py_INCREF(func);
2393 v->token = NULL;
2394 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002395
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 /* Extra reference, deleted when called or when handler is deleted */
2397 Py_INCREF(v);
2398 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399}
2400
2401static void
Fred Drake509d79a2000-07-08 04:04:38 +00002402Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002403{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 TkttObject *v = (TkttObject *)self;
2405 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410}
2411
Guido van Rossum597ac201998-05-12 14:36:19 +00002412static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002413Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 TkttObject *v = (TkttObject *)self;
2416 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002418 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2419 v->func == NULL ? ", handler deleted" : "");
2420 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002421}
2422
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423static PyTypeObject Tktt_Type =
2424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 PyVarObject_HEAD_INIT(NULL, 0)
2426 "tktimertoken", /*tp_name */
2427 sizeof(TkttObject), /*tp_basicsize */
2428 0, /*tp_itemsize */
2429 Tktt_Dealloc, /*tp_dealloc */
2430 0, /*tp_print */
2431 0, /*tp_getattr */
2432 0, /*tp_setattr */
2433 0, /*tp_reserved */
2434 Tktt_Repr, /*tp_repr */
2435 0, /*tp_as_number */
2436 0, /*tp_as_sequence */
2437 0, /*tp_as_mapping */
2438 0, /*tp_hash */
2439 0, /*tp_call*/
2440 0, /*tp_str*/
2441 0, /*tp_getattro*/
2442 0, /*tp_setattro*/
2443 0, /*tp_as_buffer*/
2444 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2445 0, /*tp_doc*/
2446 0, /*tp_traverse*/
2447 0, /*tp_clear*/
2448 0, /*tp_richcompare*/
2449 0, /*tp_weaklistoffset*/
2450 0, /*tp_iter*/
2451 0, /*tp_iternext*/
2452 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002453};
2454
Barry Warsawfa701a81997-01-16 00:15:11 +00002455
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002456
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457/** Timer Handler **/
2458
2459static void
Fred Drake509d79a2000-07-08 04:04:38 +00002460TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002461{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 TkttObject *v = (TkttObject *)clientData;
2463 PyObject *func = v->func;
2464 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 if (func == NULL)
2467 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002471 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 res = PyEval_CallObject(func, NULL);
2474 Py_DECREF(func);
2475 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002477 if (res == NULL) {
2478 errorInCmd = 1;
2479 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2480 }
2481 else
2482 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002485}
2486
2487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002488Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002489{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 int milliseconds;
2491 PyObject *func;
2492 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2495 &milliseconds, &func))
2496 return NULL;
2497 if (!PyCallable_Check(func)) {
2498 PyErr_SetString(PyExc_TypeError, "bad argument list");
2499 return NULL;
2500 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002501
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002502 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 v = Tktt_New(func);
2505 if (v) {
2506 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2507 (ClientData)v);
2508 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002511}
2512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513
Guido van Rossum18468821994-06-20 07:49:28 +00002514/** Event Loop **/
2515
Guido van Rossum18468821994-06-20 07:49:28 +00002516static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002517Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002518{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519 int threshold = 0;
2520 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002521#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002523#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002524
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2526 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 CHECK_TCL_APPARTMENT;
2529 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002531 quitMainLoop = 0;
2532 while (Tk_GetNumMainWindows() > threshold &&
2533 !quitMainLoop &&
2534 !errorInCmd)
2535 {
2536 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002537
2538#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002539 if (self->threaded) {
2540 /* Allow other Python threads to run. */
2541 ENTER_TCL
2542 result = Tcl_DoOneEvent(0);
2543 LEAVE_TCL
2544 }
2545 else {
2546 Py_BEGIN_ALLOW_THREADS
2547 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2548 tcl_tstate = tstate;
2549 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2550 tcl_tstate = NULL;
2551 if(tcl_lock)PyThread_release_lock(tcl_lock);
2552 if (result == 0)
2553 Sleep(Tkinter_busywaitinterval);
2554 Py_END_ALLOW_THREADS
2555 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002556#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002557 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002558#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 if (PyErr_CheckSignals() != 0) {
2561 self->dispatching = 0;
2562 return NULL;
2563 }
2564 if (result < 0)
2565 break;
2566 }
2567 self->dispatching = 0;
2568 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 if (errorInCmd) {
2571 errorInCmd = 0;
2572 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2573 excInCmd = valInCmd = trbInCmd = NULL;
2574 return NULL;
2575 }
2576 Py_INCREF(Py_None);
2577 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002578}
2579
2580static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002581Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002582{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 int flags = 0;
2584 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002585
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002586 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2587 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002588
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002589 ENTER_TCL
2590 rv = Tcl_DoOneEvent(flags);
2591 LEAVE_TCL
2592 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002593}
2594
2595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002596Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002597{
2598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002599 if (!PyArg_ParseTuple(args, ":quit"))
2600 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 quitMainLoop = 1;
2603 Py_INCREF(Py_None);
2604 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002605}
2606
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002607static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002608Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002609{
2610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 if (!PyArg_ParseTuple(args, ":interpaddr"))
2612 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002613
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002614 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002615}
2616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002617static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002618Tkapp_TkInit(PyObject *self, PyObject *args)
2619{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002620 Tcl_Interp *interp = Tkapp_Interp(self);
2621 const char * _tk_exists = NULL;
2622 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002623
Guilherme Polob681df42009-02-09 22:33:59 +00002624#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2626 * first call failed.
2627 * To avoid the deadlock, we just refuse the second call through
2628 * a static variable.
2629 */
2630 if (tk_load_failed) {
2631 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2632 return NULL;
2633 }
Guilherme Polob681df42009-02-09 22:33:59 +00002634#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002636 /* We want to guard against calling Tk_Init() multiple times */
2637 CHECK_TCL_APPARTMENT;
2638 ENTER_TCL
2639 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2640 ENTER_OVERLAP
2641 if (err == TCL_ERROR) {
2642 /* This sets an exception, but we cannot return right
2643 away because we need to exit the overlap first. */
2644 Tkinter_Error(self);
2645 } else {
2646 _tk_exists = Tkapp_Result(self);
2647 }
2648 LEAVE_OVERLAP_TCL
2649 if (err == TCL_ERROR) {
2650 return NULL;
2651 }
2652 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2653 if (Tk_Init(interp) == TCL_ERROR) {
2654 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002655#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002656 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002657#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 return NULL;
2659 }
2660 }
2661 Py_INCREF(Py_None);
2662 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002663}
Barry Warsawfa701a81997-01-16 00:15:11 +00002664
Martin v. Löwisffad6332002-11-26 09:28:05 +00002665static PyObject *
2666Tkapp_WantObjects(PyObject *self, PyObject *args)
2667{
2668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669 int wantobjects = -1;
2670 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2671 return NULL;
2672 if (wantobjects == -1)
2673 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2674 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 Py_INCREF(Py_None);
2677 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002678}
2679
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002680static PyObject *
2681Tkapp_WillDispatch(PyObject *self, PyObject *args)
2682{
2683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 Py_INCREF(Py_None);
2687 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002688}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002689
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002690
Guido van Rossum18468821994-06-20 07:49:28 +00002691/**** Tkapp Method List ****/
2692
2693static PyMethodDef Tkapp_methods[] =
2694{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2696 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2697 {"call", Tkapp_Call, METH_VARARGS},
2698 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2699 {"eval", Tkapp_Eval, METH_VARARGS},
2700 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2701 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2702 {"record", Tkapp_Record, METH_VARARGS},
2703 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2704 {"setvar", Tkapp_SetVar, METH_VARARGS},
2705 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2706 {"getvar", Tkapp_GetVar, METH_VARARGS},
2707 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2708 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2709 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2710 {"getint", Tkapp_GetInt, METH_VARARGS},
2711 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2712 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2713 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2714 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2715 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2716 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2717 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2718 {"split", Tkapp_Split, METH_VARARGS},
2719 {"merge", Tkapp_Merge, METH_VARARGS},
2720 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2721 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002722#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002723 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2724 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002725#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2727 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2728 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2729 {"quit", Tkapp_Quit, METH_VARARGS},
2730 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2731 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2732 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002733};
2734
Barry Warsawfa701a81997-01-16 00:15:11 +00002735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736
Guido van Rossum18468821994-06-20 07:49:28 +00002737/**** Tkapp Type Methods ****/
2738
2739static void
Fred Drake509d79a2000-07-08 04:04:38 +00002740Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002741{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 /*CHECK_TCL_APPARTMENT;*/
2743 ENTER_TCL
2744 Tcl_DeleteInterp(Tkapp_Interp(self));
2745 LEAVE_TCL
2746 PyObject_Del(self);
2747 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002748}
2749
Guido van Rossum18468821994-06-20 07:49:28 +00002750static PyTypeObject Tkapp_Type =
2751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002752 PyVarObject_HEAD_INIT(NULL, 0)
2753 "tkapp", /*tp_name */
2754 sizeof(TkappObject), /*tp_basicsize */
2755 0, /*tp_itemsize */
2756 Tkapp_Dealloc, /*tp_dealloc */
2757 0, /*tp_print */
2758 0, /*tp_getattr */
2759 0, /*tp_setattr */
2760 0, /*tp_reserved */
2761 0, /*tp_repr */
2762 0, /*tp_as_number */
2763 0, /*tp_as_sequence */
2764 0, /*tp_as_mapping */
2765 0, /*tp_hash */
2766 0, /*tp_call*/
2767 0, /*tp_str*/
2768 0, /*tp_getattro*/
2769 0, /*tp_setattro*/
2770 0, /*tp_as_buffer*/
2771 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2772 0, /*tp_doc*/
2773 0, /*tp_traverse*/
2774 0, /*tp_clear*/
2775 0, /*tp_richcompare*/
2776 0, /*tp_weaklistoffset*/
2777 0, /*tp_iter*/
2778 0, /*tp_iternext*/
2779 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002780};
2781
Barry Warsawfa701a81997-01-16 00:15:11 +00002782
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002783
Guido van Rossum18468821994-06-20 07:49:28 +00002784/**** Tkinter Module ****/
2785
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002786typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787 PyObject* tuple;
2788 int size; /* current size */
2789 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002790} FlattenContext;
2791
2792static int
2793_bump(FlattenContext* context, int size)
2794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 /* expand tuple to hold (at least) size new items.
2796 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002797
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002798 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002799
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002800 if (maxsize < context->size + size)
2801 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002805 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806}
2807
2808static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002809_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002810{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002814
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002815 if (depth > 1000) {
2816 PyErr_SetString(PyExc_ValueError,
2817 "nesting too deep in _flatten");
2818 return 0;
2819 } else if (PyList_Check(item)) {
2820 size = PyList_GET_SIZE(item);
2821 /* preallocate (assume no nesting) */
2822 if (context->size + size > context->maxsize &&
2823 !_bump(context, size))
2824 return 0;
2825 /* copy items to output tuple */
2826 for (i = 0; i < size; i++) {
2827 PyObject *o = PyList_GET_ITEM(item, i);
2828 if (PyList_Check(o) || PyTuple_Check(o)) {
2829 if (!_flatten1(context, o, depth + 1))
2830 return 0;
2831 } else if (o != Py_None) {
2832 if (context->size + 1 > context->maxsize &&
2833 !_bump(context, 1))
2834 return 0;
2835 Py_INCREF(o);
2836 PyTuple_SET_ITEM(context->tuple,
2837 context->size++, o);
2838 }
2839 }
2840 } else if (PyTuple_Check(item)) {
2841 /* same, for tuples */
2842 size = PyTuple_GET_SIZE(item);
2843 if (context->size + size > context->maxsize &&
2844 !_bump(context, size))
2845 return 0;
2846 for (i = 0; i < size; i++) {
2847 PyObject *o = PyTuple_GET_ITEM(item, i);
2848 if (PyList_Check(o) || PyTuple_Check(o)) {
2849 if (!_flatten1(context, o, depth + 1))
2850 return 0;
2851 } else if (o != Py_None) {
2852 if (context->size + 1 > context->maxsize &&
2853 !_bump(context, 1))
2854 return 0;
2855 Py_INCREF(o);
2856 PyTuple_SET_ITEM(context->tuple,
2857 context->size++, o);
2858 }
2859 }
2860 } else {
2861 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2862 return 0;
2863 }
2864 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002865}
2866
2867static PyObject *
2868Tkinter_Flatten(PyObject* self, PyObject* args)
2869{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 FlattenContext context;
2871 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002872
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2874 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 context.maxsize = PySequence_Size(item);
2877 if (context.maxsize < 0)
2878 return NULL;
2879 if (context.maxsize == 0)
2880 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002881
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002882 context.tuple = PyTuple_New(context.maxsize);
2883 if (!context.tuple)
2884 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002887
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002888 if (!_flatten1(&context, item,0))
2889 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002890
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002891 if (_PyTuple_Resize(&context.tuple, context.size))
2892 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002893
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002894 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002895}
2896
Guido van Rossum18468821994-06-20 07:49:28 +00002897static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002898Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002899{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 char *screenName = NULL;
2901 char *baseName = NULL; /* XXX this is not used anymore;
2902 try getting rid of it. */
2903 char *className = NULL;
2904 int interactive = 0;
2905 int wantobjects = 0;
2906 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2907 int sync = 0; /* pass -sync to wish */
2908 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002910 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002912 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2913 &screenName, &baseName, &className,
2914 &interactive, &wantobjects, &wantTk,
2915 &sync, &use))
2916 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002917
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918 return (PyObject *) Tkapp_New(screenName, className,
2919 interactive, wantobjects, wantTk,
2920 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002921}
2922
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002923static PyObject *
2924Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2925{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002926 int new_val;
2927 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2928 return NULL;
2929 if (new_val < 0) {
2930 PyErr_SetString(PyExc_ValueError,
2931 "busywaitinterval must be >= 0");
2932 return NULL;
2933 }
2934 Tkinter_busywaitinterval = new_val;
2935 Py_INCREF(Py_None);
2936 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002937}
2938
2939static char setbusywaitinterval_doc[] =
2940"setbusywaitinterval(n) -> None\n\
2941\n\
2942Set the busy-wait interval in milliseconds between successive\n\
2943calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2944It should be set to a divisor of the maximum time between\n\
2945frames in an animation.";
2946
2947static PyObject *
2948Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2949{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002951}
2952
2953static char getbusywaitinterval_doc[] =
2954"getbusywaitinterval() -> int\n\
2955\n\
2956Return the current busy-wait interval between successive\n\
2957calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2958
Guido van Rossum18468821994-06-20 07:49:28 +00002959static PyMethodDef moduleMethods[] =
2960{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2962 {"create", Tkinter_Create, METH_VARARGS},
2963 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2964 setbusywaitinterval_doc},
2965 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2966 METH_NOARGS, getbusywaitinterval_doc},
2967 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002968};
2969
Guido van Rossum7bf15641998-05-22 18:28:17 +00002970#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971
2972static int stdin_ready = 0;
2973
Guido van Rossumad4db171998-06-13 13:56:28 +00002974#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002975static void
Fred Drake509d79a2000-07-08 04:04:38 +00002976MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002978 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979}
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002981
Martin v. Löwisa9656492003-03-30 08:44:58 +00002982#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002983static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002984#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002985
Guido van Rossum18468821994-06-20 07:49:28 +00002986static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002987EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002988{
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002990 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002991#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002992#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002993 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002994#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002995 stdin_ready = 0;
2996 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002997#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002998 tfile = fileno(stdin);
2999 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003000#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003001 while (!errorInCmd && !stdin_ready) {
3002 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003003#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 if (_kbhit()) {
3005 stdin_ready = 1;
3006 break;
3007 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003008#endif
3009#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 Py_BEGIN_ALLOW_THREADS
3011 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3012 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003014 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 tcl_tstate = NULL;
3017 if(tcl_lock)PyThread_release_lock(tcl_lock);
3018 if (result == 0)
3019 Sleep(Tkinter_busywaitinterval);
3020 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003021#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003023#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003025 if (result < 0)
3026 break;
3027 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003028#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003030#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003031 if (errorInCmd) {
3032 errorInCmd = 0;
3033 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3034 excInCmd = valInCmd = trbInCmd = NULL;
3035 PyErr_Print();
3036 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003037#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003038 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003039#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003040 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003041}
Guido van Rossum18468821994-06-20 07:49:28 +00003042
Guido van Rossum00d93061998-05-28 23:06:38 +00003043#endif
3044
Guido van Rossum7bf15641998-05-22 18:28:17 +00003045static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003046EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003047{
Guido van Rossum00d93061998-05-28 23:06:38 +00003048#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003050#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003051 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003052#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003053 PyOS_InputHook = EventHook;
3054 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003055#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003056}
3057
3058static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003059DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003060{
Guido van Rossum00d93061998-05-28 23:06:38 +00003061#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003062 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3063 PyOS_InputHook = NULL;
3064 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003065#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003066}
3067
Barry Warsawfa701a81997-01-16 00:15:11 +00003068
3069/* all errors will be checked in one fell swoop in init_tkinter() */
3070static void
Fred Drake509d79a2000-07-08 04:04:38 +00003071ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003072{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003073 PyObject *v = PyLong_FromLong(val);
3074 if (v) {
3075 PyDict_SetItemString(d, name, v);
3076 Py_DECREF(v);
3077 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003078}
3079static void
Fred Drake509d79a2000-07-08 04:04:38 +00003080ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003081{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003082 PyObject *v = PyUnicode_FromString(val);
3083 if (v) {
3084 PyDict_SetItemString(d, name, v);
3085 Py_DECREF(v);
3086 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003087}
3088
3089
Martin v. Löwis1a214512008-06-11 05:26:20 +00003090static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003091 PyModuleDef_HEAD_INIT,
3092 "_tkinter",
3093 NULL,
3094 -1,
3095 moduleMethods,
3096 NULL,
3097 NULL,
3098 NULL,
3099 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003100};
3101
Mark Hammond62b1ab12002-07-23 06:31:15 +00003102PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003103PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003104{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003105 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003107 if (PyType_Ready(&Tkapp_Type) < 0)
3108 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003109
3110#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003111 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003112#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 m = PyModule_Create(&_tkintermodule);
3115 if (m == NULL)
3116 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003117
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003118 d = PyModule_GetDict(m);
3119 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3120 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003121
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 ins_long(d, "READABLE", TCL_READABLE);
3123 ins_long(d, "WRITABLE", TCL_WRITABLE);
3124 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3125 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3126 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3127 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3128 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3129 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3130 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3131 ins_string(d, "TK_VERSION", TK_VERSION);
3132 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003134 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003135
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 if (PyType_Ready(&Tktt_Type) < 0)
3137 return NULL;
3138 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003139
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3141 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003142
3143#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003144 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3145 * start waking up. Note that Tcl_FindExecutable will do this, this
3146 * code must be above it! The original warning from
3147 * tkMacOSXAppInit.c is copied below.
3148 *
3149 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3150 * Tcl interpreter for now. It probably should work to do this
3151 * in the other order, but for now it doesn't seem to.
3152 *
3153 */
3154 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003155#endif
3156
3157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 /* This helps the dynamic loader; in Unicode aware Tcl versions
3159 it also helps Tcl find its encodings. */
3160 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3161 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003162 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003163 if (cexe)
3164 Tcl_FindExecutable(PyBytes_AsString(cexe));
3165 Py_XDECREF(cexe);
3166 Py_DECREF(uexe);
3167 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 if (PyErr_Occurred()) {
3170 Py_DECREF(m);
3171 return NULL;
3172 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003173
Guido van Rossum43ff8681998-07-14 18:02:13 +00003174#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 /* This was not a good idea; through <Destroy> bindings,
3176 Tcl_Finalize() may invoke Python code but at that point the
3177 interpreter and thread state have already been destroyed! */
3178 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003179#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003180 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003181}