blob: bc54b7b1e45d841e810e0e9aed603b772f0ca186 [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
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000012 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
Guido van Rossuma80649b2000-03-28 20:07:05 +000014 libraries.)
15*/
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
Jason Tishlerbbe89612002-12-31 20:30:46 +000070/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000071#ifndef CONST84_RETURN
72#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000073#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000074#define CONST
75#endif
76
Guido van Rossum3e819a71997-08-01 19:29:02 +000077#define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
78
Martin v. Löwis6bfa2e62002-10-01 17:48:31 +000079#if TKMAJORMINOR < 8002
80#error "Tk older than 8.2 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 \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201 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 \
207 Py_END_ALLOW_THREADS
208
209#define LEAVE_OVERLAP_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +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 \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
219
220#define CHECK_TCL_APPARTMENT \
221 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 {
Barry Warsawfa701a81997-01-16 00:15:11 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000250 int wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000251 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.
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000255 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
273
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
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Barry Warsawfa701a81997-01-16 00:15:11 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Barry Warsawfa701a81997-01-16 00:15:11 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000296static int Tkinter_busywaitinterval = 20;
297
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301/* Millisecond sleep() for Unix platforms. */
302
303static void
Fred Drake509d79a2000-07-08 04:04:38 +0000304Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000305{
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
Guido van Rossum00d93061998-05-28 23:06:38 +0000308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
311}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000312#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000313
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000314/* Wait up to 1s for the mainloop to come up. */
315
316static int
317WaitForMainloop(TkappObject* self)
318{
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
326 }
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Guido van Rossum00d93061998-05-28 23:06:38 +0000334
Guido van Rossum18468821994-06-20 07:49:28 +0000335static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000336AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000337{
Guido van Rossum35d43371997-08-02 00:09:09 +0000338 if (PyString_Check(value))
339 return PyString_AsString(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000340 else if (PyUnicode_Check(value)) {
341 PyObject *v = PyUnicode_AsUTF8String(value);
342 if (v == NULL)
343 return NULL;
344 if (PyList_Append(tmp, v) != 0) {
345 Py_DECREF(v);
346 return NULL;
347 }
348 Py_DECREF(v);
349 return PyString_AsString(v);
350 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000351 else {
352 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
358 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000359 Py_DECREF(v);
360 return PyString_AsString(v);
361 }
Guido van Rossum18468821994-06-20 07:49:28 +0000362}
363
Barry Warsawfa701a81997-01-16 00:15:11 +0000364
365
Guido van Rossum18468821994-06-20 07:49:28 +0000366#define ARGSZ 64
367
368static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000369Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000370{
Barry Warsawfa701a81997-01-16 00:15:11 +0000371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000376 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000377 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000378
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 if (!(tmp = PyList_New(0)))
380 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382 argv = argvStore;
383 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000384
Barry Warsawfa701a81997-01-16 00:15:11 +0000385 if (args == NULL)
386 argc = 0;
387
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000393 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000394 else {
395 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Barry Warsawfa701a81997-01-16 00:15:11 +0000397 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
403 }
404 }
405
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000412 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000413 }
414 else if (v == Py_None) {
415 argc = i;
416 break;
417 }
418 else {
419 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000423 }
424 }
Guido van Rossum18468821994-06-20 07:49:28 +0000425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000429
Barry Warsawfa701a81997-01-16 00:15:11 +0000430 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000431 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 if (fv[i]) {
433 ckfree(argv[i]);
434 }
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000439
Barry Warsawfa701a81997-01-16 00:15:11 +0000440 Py_DECREF(tmp);
441 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000442}
443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444
445
Guido van Rossum18468821994-06-20 07:49:28 +0000446static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000447Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000448{
Barry Warsawfa701a81997-01-16 00:15:11 +0000449 int argc;
450 char **argv;
451 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Barry Warsawfa701a81997-01-16 00:15:11 +0000453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
456 }
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Guido van Rossum00d93061998-05-28 23:06:38 +0000458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
462 */
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000463 return PyUnicode_FromString(list);
Barry Warsawfa701a81997-01-16 00:15:11 +0000464 }
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466 if (argc == 0)
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000467 v = PyUnicode_FromString("");
Barry Warsawfa701a81997-01-16 00:15:11 +0000468 else if (argc == 1)
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000469 v = PyUnicode_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000470 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000471 int i;
472 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000473
Barry Warsawfa701a81997-01-16 00:15:11 +0000474 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000475 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 Py_DECREF(v);
477 v = NULL;
478 break;
479 }
480 PyTuple_SetItem(v, i, w);
481 }
482 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000483 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000484 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000485}
486
Martin v. Löwisffad6332002-11-26 09:28:05 +0000487/* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
490
491PyObject *
492SplitObj(PyObject *arg)
493{
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
497
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
509 }
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
515 }
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
523 }
524 }
525 PyTuple_SetItem(result, i, newelem);
526 }
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
530 }
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
535
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
539 }
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
544 }
545 Py_INCREF(arg);
546 return arg;
547}
Barry Warsawfa701a81997-01-16 00:15:11 +0000548
549
Guido van Rossum18468821994-06-20 07:49:28 +0000550/**** Tkapp Object ****/
551
552#ifndef WITH_APPINIT
553int
Fred Drake509d79a2000-07-08 04:04:38 +0000554Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000555{
Barry Warsawfa701a81997-01-16 00:15:11 +0000556 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000557 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000558
Barry Warsawfa701a81997-01-16 00:15:11 +0000559 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 return TCL_ERROR;
562 }
David Aschere2b4b322004-02-18 05:59:53 +0000563 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565 main = Tk_MainWindow(interp);
566 if (Tk_Init(interp) == TCL_ERROR) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568 return TCL_ERROR;
569 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000570 }
571 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000572}
573#endif /* !WITH_APPINIT */
574
Guido van Rossum18468821994-06-20 07:49:28 +0000575
Barry Warsawfa701a81997-01-16 00:15:11 +0000576
577
578/* Initialize the Tk application; see the `main' function in
579 * `tkMain.c'.
580 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000581
Thomas Wouters58d05102000-07-24 14:43:35 +0000582static void EnableEventHook(void); /* Forward */
583static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000584
Barry Warsawfa701a81997-01-16 00:15:11 +0000585static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000586Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000587 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000588{
589 TkappObject *v;
590 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000591
Guido van Rossumb18618d2000-05-03 23:44:39 +0000592 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000593 if (v == NULL)
594 return NULL;
595
596 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000597 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000598 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY) != NULL;
600 v->thread_id = Tcl_GetCurrentThread();
601 v->dispatching = 0;
602
603#ifndef TCL_THREADS
604 if (v->threaded) {
605 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
606 Py_DECREF(v);
607 return 0;
608 }
609#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000610#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000611 if (v->threaded && tcl_lock) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock);
614 tcl_lock = NULL;
615 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000616#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000617
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
625
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
628
Barry Warsawfa701a81997-01-16 00:15:11 +0000629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000632
Barry Warsawfa701a81997-01-16 00:15:11 +0000633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000637
Barry Warsawfa701a81997-01-16 00:15:11 +0000638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
644 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000645
Barry Warsawfa701a81997-01-16 00:15:11 +0000646 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000647 if (isupper(Py_CHARMASK(argv0[0])))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
Barry Warsawfa701a81997-01-16 00:15:11 +0000649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
David Aschere2b4b322004-02-18 05:59:53 +0000652 if (! wantTk) {
653 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
654 }
655
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000656 /* some initial arguments need to be in argv */
657 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000658 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000659 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000660
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661 if (sync)
662 len += sizeof "-sync";
663 if (use)
664 len += strlen(use) + sizeof "-use ";
665
Tim Peters51fa3b72004-08-04 02:16:48 +0000666 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667 if (!args) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
671 }
672
673 args[0] = '\0';
674 if (sync)
675 strcat(args, "-sync");
676 if (use) {
677 if (sync)
678 strcat(args, " ");
679 strcat(args, "-use ");
680 strcat(args, use);
681 }
682
683 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
684 ckfree(args);
685 }
686
Thomas Woutersa74a84d2006-03-07 14:04:31 +0000687 if (Tcl_AppInit(v->interp) != TCL_OK) {
688 PyObject *result = Tkinter_Error((PyObject *)v);
689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
691 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000692
Guido van Rossum7bf15641998-05-22 18:28:17 +0000693 EnableEventHook();
694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000696}
697
Barry Warsawfa701a81997-01-16 00:15:11 +0000698
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000699static void
700Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
701 Tcl_Condition *cond, Tcl_Mutex *mutex)
702{
703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
710}
711
Barry Warsawfa701a81997-01-16 00:15:11 +0000712
Guido van Rossum18468821994-06-20 07:49:28 +0000713/** Tcl Eval **/
714
Martin v. Löwisffad6332002-11-26 09:28:05 +0000715typedef struct {
716 PyObject_HEAD
717 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000718 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000719} PyTclObject;
720
Neal Norwitz227b5332006-03-22 09:28:35 +0000721static PyTypeObject PyTclObject_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000722#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
723
724static PyObject *
725newPyTclObject(Tcl_Obj *arg)
726{
727 PyTclObject *self;
728 self = PyObject_New(PyTclObject, &PyTclObject_Type);
729 if (self == NULL)
730 return NULL;
731 Tcl_IncrRefCount(arg);
732 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000733 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000734 return (PyObject*)self;
735}
736
737static void
738PyTclObject_dealloc(PyTclObject *self)
739{
740 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000741 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000742 PyObject_Del(self);
743}
744
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000745static char*
746PyTclObject_TclString(PyObject *self)
747{
748 return Tcl_GetString(((PyTclObject*)self)->value);
749}
750
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000751/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000752PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000753"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000754
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000755static PyObject *
756PyTclObject_string(PyTclObject *self, void *ignored)
757{
758 char *s;
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000759 int len;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000762 self->string = PyUnicode_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000763 if (!self->string)
764 return NULL;
765 }
766 Py_INCREF(self->string);
767 return self->string;
768}
769
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000770static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000771PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000772{
773 char *s;
774 int len;
775 if (self->string && PyUnicode_Check(self->string)) {
776 Py_INCREF(self->string);
777 return self->string;
778 }
779 /* XXX Could chache result if it is non-ASCII. */
780 s = Tcl_GetStringFromObj(self->value, &len);
781 return PyUnicode_DecodeUTF8(s, len, "strict");
782}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000783
Martin v. Löwisffad6332002-11-26 09:28:05 +0000784static PyObject *
785PyTclObject_repr(PyTclObject *self)
786{
Walter Dörwald7569dfe2007-05-19 21:49:49 +0000787 return PyUnicode_FromFormat("<%s object at %p>",
788 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000789}
790
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000791static int
792PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
793{
794 int res;
795 res = strcmp(Tcl_GetString(self->value),
796 Tcl_GetString(other->value));
797 if (res < 0) return -1;
798 if (res > 0) return 1;
799 return 0;
800}
801
Martin v. Löwis39195712003-01-04 00:33:13 +0000802PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
803
Martin v. Löwisffad6332002-11-26 09:28:05 +0000804static PyObject*
805get_typename(PyTclObject* obj, void* ignored)
806{
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000807 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000808}
809
Martin v. Löwis39195712003-01-04 00:33:13 +0000810
Martin v. Löwisffad6332002-11-26 09:28:05 +0000811static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000812 {"typename", (getter)get_typename, NULL, get_typename__doc__},
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000813 {"string", (getter)PyTclObject_string, NULL,
Martin v. Löwis39195712003-01-04 00:33:13 +0000814 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000815 {0},
816};
817
Neal Norwitz227b5332006-03-22 09:28:35 +0000818static PyTypeObject PyTclObject_Type = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000819 PyVarObject_HEAD_INIT(NULL, 0)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820 "_tkinter.Tcl_Obj", /*tp_name*/
821 sizeof(PyTclObject), /*tp_basicsize*/
822 0, /*tp_itemsize*/
823 /* methods */
824 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
825 0, /*tp_print*/
826 0, /*tp_getattr*/
827 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000828 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829 (reprfunc)PyTclObject_repr, /*tp_repr*/
830 0, /*tp_as_number*/
831 0, /*tp_as_sequence*/
832 0, /*tp_as_mapping*/
833 0, /*tp_hash*/
834 0, /*tp_call*/
835 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000836 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000837 0, /*tp_setattro*/
838 0, /*tp_as_buffer*/
839 Py_TPFLAGS_DEFAULT, /*tp_flags*/
840 0, /*tp_doc*/
841 0, /*tp_traverse*/
842 0, /*tp_clear*/
843 0, /*tp_richcompare*/
844 0, /*tp_weaklistoffset*/
845 0, /*tp_iter*/
846 0, /*tp_iternext*/
Walter Dörwald6720d912007-07-12 12:12:25 +0000847 0, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848 0, /*tp_members*/
849 PyTclObject_getsetlist, /*tp_getset*/
850 0, /*tp_base*/
851 0, /*tp_dict*/
852 0, /*tp_descr_get*/
853 0, /*tp_descr_set*/
854 0, /*tp_dictoffset*/
855 0, /*tp_init*/
856 0, /*tp_alloc*/
857 0, /*tp_new*/
858 0, /*tp_free*/
859 0, /*tp_is_gc*/
860};
861
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000862static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000863AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000864{
865 Tcl_Obj *result;
Martin v. Löwisd1a1d1e2007-12-04 22:10:37 +0000866 long longVal;
867 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000868
869 if (PyString_Check(value))
870 return Tcl_NewStringObj(PyString_AS_STRING(value),
871 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000872 else if (PyBool_Check(value))
873 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Martin v. Löwisd1a1d1e2007-12-04 22:10:37 +0000874 else if (PyLong_CheckExact(value) &&
875 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
876 !overflow)) {
877 /* If there is an overflow in the long conversion,
878 fall through to default object handling. */
879 return Tcl_NewLongObj(longVal);
880 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000881 else if (PyFloat_Check(value))
882 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
883 else if (PyTuple_Check(value)) {
884 Tcl_Obj **argv = (Tcl_Obj**)
885 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
886 int i;
887 if(!argv)
888 return 0;
889 for(i=0;i<PyTuple_Size(value);i++)
890 argv[i] = AsObj(PyTuple_GetItem(value,i));
891 result = Tcl_NewListObj(PyTuple_Size(value), argv);
892 ckfree(FREECAST argv);
893 return result;
894 }
895 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000896 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000897 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000898 /* This #ifdef assumes that Tcl uses UCS-2.
899 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000900#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000901 Tcl_UniChar *outbuf;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000902 Py_ssize_t i;
903 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000904 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
905 if (!outbuf) {
906 PyErr_NoMemory();
907 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000908 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000909 for (i = 0; i < size; i++) {
910 if (inbuf[i] >= 0x10000) {
911 /* Tcl doesn't do UTF-16, yet. */
912 PyErr_SetString(PyExc_ValueError,
913 "unsupported character");
914 ckfree(FREECAST outbuf);
915 return NULL;
916 }
917 outbuf[i] = inbuf[i];
918 }
919 result = Tcl_NewUnicodeObj(outbuf, size);
920 ckfree(FREECAST outbuf);
921 return result;
922#else
923 return Tcl_NewUnicodeObj(inbuf, size);
924#endif
925
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000926 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000927 else if(PyTclObject_Check(value)) {
928 Tcl_Obj *v = ((PyTclObject*)value)->value;
929 Tcl_IncrRefCount(v);
930 return v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000931 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000932 else {
933 PyObject *v = PyObject_Str(value);
934 if (!v)
935 return 0;
936 result = AsObj(v);
937 Py_DECREF(v);
938 return result;
939 }
940}
941
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942static PyObject*
943FromObj(PyObject* tkapp, Tcl_Obj *value)
944{
945 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000946 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000947
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000948 if (value->typePtr == NULL) {
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000949 return PyUnicode_FromStringAndSize(value->bytes,
Martin v. Löwis4040fb82007-08-13 06:01:43 +0000950 value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000951 }
Martin v. Löwisffad6332002-11-26 09:28:05 +0000952
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000953 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000954 result = value->internalRep.longValue ? Py_True : Py_False;
955 Py_INCREF(result);
956 return result;
957 }
958
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000959 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000960 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +0000961 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000962 return PyString_FromStringAndSize(data, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000963 }
964
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000965 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966 return PyFloat_FromDouble(value->internalRep.doubleValue);
967 }
968
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000969 if (value->typePtr == app->IntType) {
Christian Heimes217cfd12007-12-02 14:31:20 +0000970 return PyLong_FromLong(value->internalRep.longValue);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971 }
972
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000973 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000974 int size;
975 int i, status;
976 PyObject *elem;
977 Tcl_Obj *tcl_elem;
978
979 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
980 if (status == TCL_ERROR)
981 return Tkinter_Error(tkapp);
982 result = PyTuple_New(size);
983 if (!result)
984 return NULL;
985 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000986 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +0000987 value, i, &tcl_elem);
988 if (status == TCL_ERROR) {
989 Py_DECREF(result);
990 return Tkinter_Error(tkapp);
991 }
992 elem = FromObj(tkapp, tcl_elem);
993 if (!elem) {
994 Py_DECREF(result);
995 return NULL;
996 }
997 PyTuple_SetItem(result, i, elem);
998 }
999 return result;
1000 }
1001
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001002 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001003 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001004 }
1005
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001006 if (value->typePtr == app->StringType) {
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001007#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001008 PyObject *result;
1009 int size;
1010 Tcl_UniChar *input;
1011 Py_UNICODE *output;
1012
1013 size = Tcl_GetCharLength(value);
1014 result = PyUnicode_FromUnicode(NULL, size);
1015 if (!result)
1016 return NULL;
1017 input = Tcl_GetUnicode(value);
1018 output = PyUnicode_AS_UNICODE(result);
1019 while (size--)
1020 *output++ = *input++;
1021 return result;
1022#else
1023 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1024 Tcl_GetCharLength(value));
1025#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +00001026 }
1027
1028 return newPyTclObject(value);
1029}
1030
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001031/* This mutex synchronizes inter-thread command calls. */
1032
1033TCL_DECLARE_MUTEX(call_mutex)
1034
1035typedef struct Tkapp_CallEvent {
1036 Tcl_Event ev; /* Must be first */
1037 TkappObject *self;
1038 PyObject *args;
1039 int flags;
1040 PyObject **res;
1041 PyObject **exc_type, **exc_value, **exc_tb;
1042 Tcl_Condition done;
1043} Tkapp_CallEvent;
1044
1045void
1046Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001047{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001048 int i;
1049 for (i = 0; i < objc; i++)
1050 Tcl_DecrRefCount(objv[i]);
1051 if (objv != objStore)
1052 ckfree(FREECAST objv);
1053}
Guido van Rossum18468821994-06-20 07:49:28 +00001054
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001055/* Convert Python objects to Tcl objects. This must happen in the
1056 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001057
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001058static Tcl_Obj**
1059Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1060{
1061 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001062 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001063 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001064 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001065
Guido van Rossum212643f1998-04-29 16:22:14 +00001066 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001067 objv[0] = AsObj(args);
1068 if (objv[0] == 0)
1069 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001070 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001071 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001072 }
1073 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001074 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001075
Guido van Rossum632de272000-03-29 00:19:50 +00001076 if (objc > ARGSZ) {
1077 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1078 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001079 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001080 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001081 goto finally;
1082 }
1083 }
1084
Guido van Rossum632de272000-03-29 00:19:50 +00001085 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001086 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001087 if (v == Py_None) {
1088 objc = i;
1089 break;
1090 }
Guido van Rossum632de272000-03-29 00:19:50 +00001091 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001092 if (!objv[i]) {
1093 /* Reset objc, so it attempts to clear
1094 objects only up to i. */
1095 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001096 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001097 }
Guido van Rossum632de272000-03-29 00:19:50 +00001098 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001099 }
1100 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001101 *pobjc = objc;
1102 return objv;
1103finally:
1104 Tkapp_CallDeallocArgs(objv, objStore, objc);
1105 return NULL;
1106}
Guido van Rossum212643f1998-04-29 16:22:14 +00001107
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001108/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001109
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001110static PyObject*
1111Tkapp_CallResult(TkappObject *self)
1112{
1113 PyObject *res = NULL;
1114 if(self->wantobjects) {
1115 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001116 /* Not sure whether the IncrRef is necessary, but something
1117 may overwrite the interpreter result while we are
1118 converting it. */
1119 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001120 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001121 Tcl_DecrRefCount(value);
1122 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001123 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001124 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001125
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001126 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
Guido van Rossum990f5c62000-05-04 15:07:16 +00001127 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001128 return res;
1129}
Guido van Rossum632de272000-03-29 00:19:50 +00001130
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001131/* Tkapp_CallProc is the event procedure that is executed in the context of
1132 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1133 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001134
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001135static int
1136Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1137{
1138 Tcl_Obj *objStore[ARGSZ];
1139 Tcl_Obj **objv;
1140 int objc;
1141 int i;
1142 ENTER_PYTHON
1143 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1144 if (!objv) {
1145 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1146 *(e->res) = NULL;
1147 }
1148 LEAVE_PYTHON
1149 if (!objv)
1150 goto done;
1151 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1152 ENTER_PYTHON
1153 if (i == TCL_ERROR) {
1154 *(e->res) = NULL;
1155 *(e->exc_type) = NULL;
1156 *(e->exc_tb) = NULL;
1157 *(e->exc_value) = PyObject_CallFunction(
1158 Tkinter_TclError, "s",
1159 Tcl_GetStringResult(e->self->interp));
1160 }
1161 else {
1162 *(e->res) = Tkapp_CallResult(e->self);
1163 }
1164 LEAVE_PYTHON
1165 done:
1166 /* Wake up calling thread. */
1167 Tcl_MutexLock(&call_mutex);
1168 Tcl_ConditionNotify(&e->done);
1169 Tcl_MutexUnlock(&call_mutex);
1170 return 1;
1171}
1172
1173/* This is the main entry point for calling a Tcl command.
1174 It supports three cases, with regard to threading:
1175 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1176 the context of the calling thread.
1177 2. Tcl is threaded, caller of the command is in the interpreter thread:
1178 Execute the command in the calling thread. Since the Tcl lock will
1179 not be used, we can merge that with case 1.
1180 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1181 the interpreter thread. Allocation of Tcl objects needs to occur in the
1182 interpreter thread, so we ship the PyObject* args to the target thread,
1183 and perform processing there. */
1184
1185static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001186Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001187{
1188 Tcl_Obj *objStore[ARGSZ];
1189 Tcl_Obj **objv = NULL;
1190 int objc, i;
1191 PyObject *res = NULL;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001192 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001193 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1194 int flags = TCL_EVAL_DIRECT;
1195
Guido van Rossum992d4a32007-07-11 13:09:30 +00001196 /* If args is a single tuple, replace with contents of tuple */
1197 if (1 == PyTuple_Size(args)){
1198 PyObject* item = PyTuple_GetItem(args, 0);
1199 if (PyTuple_Check(item))
1200 args = item;
1201 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001202#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001203 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1204 /* We cannot call the command directly. Instead, we must
1205 marshal the parameters to the interpreter thread. */
1206 Tkapp_CallEvent *ev;
1207 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001208 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001209 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001210 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1211 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1212 ev->self = self;
1213 ev->args = args;
1214 ev->res = &res;
1215 ev->exc_type = &exc_type;
1216 ev->exc_value = &exc_value;
1217 ev->exc_tb = &exc_tb;
1218 ev->done = (Tcl_Condition)0;
1219
1220 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1221
1222 if (res == NULL) {
1223 if (exc_type)
1224 PyErr_Restore(exc_type, exc_value, exc_tb);
1225 else
1226 PyErr_SetObject(Tkinter_TclError, exc_value);
1227 }
1228 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001229 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001230#endif
1231 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001232
1233 objv = Tkapp_CallArgs(args, objStore, &objc);
1234 if (!objv)
1235 return NULL;
1236
1237 ENTER_TCL
1238
1239 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1240
1241 ENTER_OVERLAP
1242
1243 if (i == TCL_ERROR)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001244 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245 else
1246 res = Tkapp_CallResult(self);
1247
1248 LEAVE_OVERLAP_TCL
1249
1250 Tkapp_CallDeallocArgs(objv, objStore, objc);
1251 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001252 return res;
1253}
1254
1255
1256static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001257Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001258{
Guido van Rossum212643f1998-04-29 16:22:14 +00001259 /* Could do the same here as for Tkapp_Call(), but this is not used
1260 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1261 way for the user to do what all its Global* variants do (save and
1262 reset the scope pointer, call the local version, restore the saved
1263 scope pointer). */
1264
Guido van Rossum62320c91998-06-15 04:36:09 +00001265 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001266 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001267
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268 CHECK_TCL_APPARTMENT;
1269
Guido van Rossum62320c91998-06-15 04:36:09 +00001270 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001271 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001272 int err;
1273 ENTER_TCL
1274 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001275 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001276 if (err == TCL_ERROR)
1277 res = Tkinter_Error(self);
1278 else
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001279 res = PyUnicode_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001280 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001281 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001282 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001283
1284 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001285}
1286
1287static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001288Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001289{
Barry Warsawfa701a81997-01-16 00:15:11 +00001290 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001291 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001292 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001293
Guido van Rossum43713e52000-02-29 13:59:29 +00001294 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001295 return NULL;
1296
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001297 CHECK_TCL_APPARTMENT;
1298
Guido van Rossum00d93061998-05-28 23:06:38 +00001299 ENTER_TCL
1300 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001301 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001302 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001303 res = Tkinter_Error(self);
1304 else
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001305 res = PyUnicode_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001306 LEAVE_OVERLAP_TCL
1307 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001308}
1309
1310static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001311Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001312{
Barry Warsawfa701a81997-01-16 00:15:11 +00001313 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001314 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001315 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001316
Guido van Rossum43713e52000-02-29 13:59:29 +00001317 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001318 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001319
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320 CHECK_TCL_APPARTMENT;
1321
Guido van Rossum00d93061998-05-28 23:06:38 +00001322 ENTER_TCL
1323 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001324 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001325 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001326 res = Tkinter_Error(self);
1327 else
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001328 res = PyUnicode_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001329 LEAVE_OVERLAP_TCL
1330 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001331}
1332
1333static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001334Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001335{
Barry Warsawfa701a81997-01-16 00:15:11 +00001336 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001337 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001338 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001339
Guido van Rossum43713e52000-02-29 13:59:29 +00001340 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001341 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001342
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343 CHECK_TCL_APPARTMENT;
1344
Guido van Rossum00d93061998-05-28 23:06:38 +00001345 ENTER_TCL
1346 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001348 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001349 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001350
Guido van Rossum62320c91998-06-15 04:36:09 +00001351 else
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001352 res = PyUnicode_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001353 LEAVE_OVERLAP_TCL
1354 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001355}
1356
1357static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001358Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001359{
Barry Warsawfa701a81997-01-16 00:15:11 +00001360 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001361 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001362 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001363
Guido van Rossum35d43371997-08-02 00:09:09 +00001364 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001365 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001366
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001367 CHECK_TCL_APPARTMENT;
1368
Guido van Rossum00d93061998-05-28 23:06:38 +00001369 ENTER_TCL
1370 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001371 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001372 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 res = Tkinter_Error(self);
1374 else
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001375 res = PyUnicode_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001376 LEAVE_OVERLAP_TCL
1377 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001378}
1379
1380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001381Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Barry Warsawfa701a81997-01-16 00:15:11 +00001383 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001384
Guido van Rossum43713e52000-02-29 13:59:29 +00001385 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001386 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387 CHECK_TCL_APPARTMENT;
1388
Guido van Rossum00d93061998-05-28 23:06:38 +00001389 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001390 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001391 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001392
Barry Warsawfa701a81997-01-16 00:15:11 +00001393 Py_INCREF(Py_None);
1394 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001395}
1396
Barry Warsawfa701a81997-01-16 00:15:11 +00001397
1398
Guido van Rossum18468821994-06-20 07:49:28 +00001399/** Tcl Variable **/
1400
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401TCL_DECLARE_MUTEX(var_mutex)
1402
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001403typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001404typedef struct VarEvent {
1405 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001406 PyObject *self;
1407 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001408 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001409 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001411 PyObject **exc_type;
1412 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001414} VarEvent;
1415
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001416static int
1417varname_converter(PyObject *in, void *_out)
1418{
1419 char **out = (char**)_out;
1420 if (PyString_Check(in)) {
1421 *out = PyString_AsString(in);
1422 return 1;
1423 }
Guido van Rossumf761e102007-07-23 18:34:37 +00001424 if (PyUnicode_Check(in)) {
1425 *out = PyUnicode_AsString(in);
1426 return 1;
1427 }
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001428 if (PyTclObject_Check(in)) {
1429 *out = PyTclObject_TclString(in);
1430 return 1;
1431 }
1432 /* XXX: Should give diagnostics. */
1433 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001434}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001435
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001436void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001437var_perform(VarEvent *ev)
1438{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001439 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1440 if (!*(ev->res)) {
1441 PyObject *exc, *val, *tb;
1442 PyErr_Fetch(&exc, &val, &tb);
1443 PyErr_NormalizeException(&exc, &val, &tb);
1444 *(ev->exc_type) = exc;
1445 *(ev->exc_val) = val;
1446 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001447 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001448
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449}
1450
1451static int
1452var_proc(VarEvent* ev, int flags)
1453{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001455 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456 Tcl_MutexLock(&var_mutex);
1457 Tcl_ConditionNotify(&ev->cond);
1458 Tcl_MutexUnlock(&var_mutex);
1459 LEAVE_PYTHON
1460 return 1;
1461}
1462
1463static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001464var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001465{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001466 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001467#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001468 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001469 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001470 VarEvent *ev;
1471 PyObject *res, *exc_type, *exc_val;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001472
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473 /* The current thread is not the interpreter thread. Marshal
1474 the call to the interpreter thread, then wait for
1475 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001476 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001478
1479 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1480
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001481 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001482 ev->args = args;
1483 ev->flags = flags;
1484 ev->func = func;
1485 ev->res = &res;
1486 ev->exc_type = &exc_type;
1487 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488 ev->cond = NULL;
1489 ev->ev.proc = (Tcl_EventProc*)var_proc;
1490 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491 if (!res) {
1492 PyErr_SetObject(exc_type, exc_val);
1493 Py_DECREF(exc_type);
1494 Py_DECREF(exc_val);
1495 return NULL;
1496 }
1497 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001499#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001500 /* Tcl is not threaded, or this is the interpreter thread. */
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001501 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502}
1503
Guido van Rossum18468821994-06-20 07:49:28 +00001504static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001505SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001506{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001507 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001508 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001509 PyObject *res = NULL;
1510 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001511
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001512 if (PyArg_ParseTuple(args, "O&O:setvar",
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001513 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001514 /* XXX Acquire tcl lock??? */
1515 newval = AsObj(newValue);
1516 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001517 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001518 ENTER_TCL
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001519 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001520 newval, flags);
1521 ENTER_OVERLAP
1522 if (!ok)
1523 Tkinter_Error(self);
1524 else {
1525 res = Py_None;
1526 Py_INCREF(res);
1527 }
1528 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001529 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001530 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001531 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001532 if (PyArg_ParseTuple(args, "ssO:setvar",
1533 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001534 /* XXX must hold tcl lock already??? */
1535 newval = AsObj(newValue);
1536 ENTER_TCL
1537 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1538 ENTER_OVERLAP
1539 if (!ok)
1540 Tkinter_Error(self);
1541 else {
1542 res = Py_None;
1543 Py_INCREF(res);
1544 }
1545 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001546 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001547 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001548 return NULL;
1549 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001550 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001551 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001552}
1553
1554static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001555Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001556{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001557 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001558}
1559
1560static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001561Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001562{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001563 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001564}
1565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566
1567
Guido van Rossum18468821994-06-20 07:49:28 +00001568static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001569GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001570{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001571 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001572 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001573 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001574
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001575 if (!PyArg_ParseTuple(args, "O&|s:getvar",
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001576 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001577 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001578
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001579 ENTER_TCL
1580 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1581 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001582 if (tres == NULL) {
1583 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1584 } else {
1585 if (((TkappObject*)self)->wantobjects) {
1586 res = FromObj(self, tres);
1587 }
1588 else {
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001589 res = PyUnicode_FromString(Tcl_GetString(tres));
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001590 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001591 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001592 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001593 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001594}
1595
1596static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001597Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001598{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001599 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001600}
1601
1602static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001603Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001604{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001605 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001606}
1607
Barry Warsawfa701a81997-01-16 00:15:11 +00001608
1609
Guido van Rossum18468821994-06-20 07:49:28 +00001610static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001611UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001612{
Guido van Rossum35d43371997-08-02 00:09:09 +00001613 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001614 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001615 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001616
Guido van Rossum43713e52000-02-29 13:59:29 +00001617 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001619
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001620 ENTER_TCL
1621 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1622 ENTER_OVERLAP
1623 if (code == TCL_ERROR)
1624 res = Tkinter_Error(self);
1625 else {
1626 Py_INCREF(Py_None);
1627 res = Py_None;
1628 }
1629 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001630 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001631}
1632
1633static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001634Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001635{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001636 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001637}
1638
1639static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001640Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001641{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001642 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
Barry Warsawfa701a81997-01-16 00:15:11 +00001645
1646
Guido van Rossum18468821994-06-20 07:49:28 +00001647/** Tcl to Python **/
1648
1649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Barry Warsawfa701a81997-01-16 00:15:11 +00001652 char *s;
1653 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001654
Martin v. Löwisffad6332002-11-26 09:28:05 +00001655 if (PyTuple_Size(args) == 1) {
1656 PyObject* o = PyTuple_GetItem(args, 0);
Christian Heimes217cfd12007-12-02 14:31:20 +00001657 if (PyLong_Check(o)) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001658 Py_INCREF(o);
1659 return o;
1660 }
1661 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001662 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001663 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001664 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001665 return Tkinter_Error(self);
1666 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001667}
1668
1669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Barry Warsawfa701a81997-01-16 00:15:11 +00001672 char *s;
1673 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001674
Martin v. Löwisffad6332002-11-26 09:28:05 +00001675 if (PyTuple_Size(args) == 1) {
1676 PyObject *o = PyTuple_GetItem(args, 0);
1677 if (PyFloat_Check(o)) {
1678 Py_INCREF(o);
1679 return o;
1680 }
1681 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001682 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001683 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001684 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001685 return Tkinter_Error(self);
1686 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
1689static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001690Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001691{
Barry Warsawfa701a81997-01-16 00:15:11 +00001692 char *s;
1693 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001694
Martin v. Löwisffad6332002-11-26 09:28:05 +00001695 if (PyTuple_Size(args) == 1) {
1696 PyObject *o = PyTuple_GetItem(args, 0);
Christian Heimes217cfd12007-12-02 14:31:20 +00001697 if (PyLong_Check(o)) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001698 Py_INCREF(o);
1699 return o;
1700 }
1701 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001702 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001703 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001704 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1705 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001706 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
1709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001711{
Barry Warsawfa701a81997-01-16 00:15:11 +00001712 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001713 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001714 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001715
Guido van Rossum43713e52000-02-29 13:59:29 +00001716 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001717 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001718
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001719 CHECK_TCL_APPARTMENT;
1720
Guido van Rossum00d93061998-05-28 23:06:38 +00001721 ENTER_TCL
1722 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001723 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001724 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001725 res = Tkinter_Error(self);
1726 else
1727 res = Py_BuildValue("s", Tkapp_Result(self));
1728 LEAVE_OVERLAP_TCL
1729 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001730}
1731
1732static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001733Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001734{
Barry Warsawfa701a81997-01-16 00:15:11 +00001735 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001736 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001737 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001738 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001739
Guido van Rossum43713e52000-02-29 13:59:29 +00001740 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001742
1743 CHECK_TCL_APPARTMENT;
1744
Guido van Rossum00d93061998-05-28 23:06:38 +00001745 ENTER_TCL
1746 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001747 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001748 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001749 res = Tkinter_Error(self);
1750 else
1751 res = Py_BuildValue("l", v);
1752 LEAVE_OVERLAP_TCL
1753 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001754}
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Barry Warsawfa701a81997-01-16 00:15:11 +00001759 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001760 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001761 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001762 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001763
Guido van Rossum43713e52000-02-29 13:59:29 +00001764 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001765 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001766 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001767 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001768 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001769 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001770 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001771 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001772 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001773 res = Tkinter_Error(self);
1774 else
1775 res = Py_BuildValue("d", v);
1776 LEAVE_OVERLAP_TCL
1777 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Barry Warsawfa701a81997-01-16 00:15:11 +00001783 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001784 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001785 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001786 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001787
Guido van Rossum43713e52000-02-29 13:59:29 +00001788 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001789 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001790 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001791 ENTER_TCL
1792 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001793 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001794 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001795 res = Tkinter_Error(self);
1796 else
1797 res = Py_BuildValue("i", v);
1798 LEAVE_OVERLAP_TCL
1799 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001800}
1801
Barry Warsawfa701a81997-01-16 00:15:11 +00001802
1803
Guido van Rossum18468821994-06-20 07:49:28 +00001804static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001805Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001806{
Barry Warsawfa701a81997-01-16 00:15:11 +00001807 char *list;
1808 int argc;
1809 char **argv;
1810 PyObject *v;
1811 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001812
Martin v. Löwisffad6332002-11-26 09:28:05 +00001813 if (PyTuple_Size(args) == 1) {
1814 v = PyTuple_GetItem(args, 0);
1815 if (PyTuple_Check(v)) {
1816 Py_INCREF(v);
1817 return v;
1818 }
1819 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001820 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001821 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001822
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001823 if (Tcl_SplitList(Tkapp_Interp(self), list,
Neal Norwitzd1c55102003-05-29 00:17:03 +00001824 &argc, &argv) == TCL_ERROR) {
1825 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001826 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001827 }
Guido van Rossum18468821994-06-20 07:49:28 +00001828
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001830 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001831
Barry Warsawfa701a81997-01-16 00:15:11 +00001832 for (i = 0; i < argc; i++) {
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001833 PyObject *s = PyUnicode_FromString(argv[i]);
Barry Warsawfa701a81997-01-16 00:15:11 +00001834 if (!s || PyTuple_SetItem(v, i, s)) {
1835 Py_DECREF(v);
1836 v = NULL;
1837 goto finally;
1838 }
1839 }
Guido van Rossum18468821994-06-20 07:49:28 +00001840
Barry Warsawfa701a81997-01-16 00:15:11 +00001841 finally:
1842 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001843 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001844 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001845}
1846
1847static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001848Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001849{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001850 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001851 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001852
Martin v. Löwisffad6332002-11-26 09:28:05 +00001853 if (PyTuple_Size(args) == 1) {
1854 PyObject* o = PyTuple_GetItem(args, 0);
1855 if (PyTuple_Check(o)) {
1856 o = SplitObj(o);
1857 return o;
1858 }
1859 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001860 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001861 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001862 v = Split(list);
1863 PyMem_Free(list);
1864 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001865}
1866
1867static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001868Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001869{
Barry Warsawfa701a81997-01-16 00:15:11 +00001870 char *s = Merge(args);
1871 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001872
Barry Warsawfa701a81997-01-16 00:15:11 +00001873 if (s) {
Martin v. Löwis4040fb82007-08-13 06:01:43 +00001874 res = PyUnicode_FromString(s);
Barry Warsawfa701a81997-01-16 00:15:11 +00001875 ckfree(s);
1876 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001877
1878 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
Barry Warsawfa701a81997-01-16 00:15:11 +00001881
1882
Guido van Rossum18468821994-06-20 07:49:28 +00001883/** Tcl Command **/
1884
Guido van Rossum00d93061998-05-28 23:06:38 +00001885/* Client data struct */
1886typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001887 PyObject *self;
1888 PyObject *func;
1889} PythonCmd_ClientData;
1890
1891static int
Fred Drake509d79a2000-07-08 04:04:38 +00001892PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001893{
1894 errorInCmd = 1;
1895 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1896 LEAVE_PYTHON
1897 return TCL_ERROR;
1898}
1899
Guido van Rossum18468821994-06-20 07:49:28 +00001900/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001901 * function or method.
1902 */
Guido van Rossum18468821994-06-20 07:49:28 +00001903static int
Fred Drake509d79a2000-07-08 04:04:38 +00001904PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001905{
Guido van Rossum00d93061998-05-28 23:06:38 +00001906 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Kurt B. Kaiserab45e272007-08-27 01:55:21 +00001907 PyObject *self, *func, *arg, *res, *s;
Guido van Rossum2834b972000-10-06 16:58:26 +00001908 int i, rv;
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001909 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001910
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001911 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001912
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 /* TBD: no error checking here since we know, via the
1914 * Tkapp_CreateCommand() that the client data is a two-tuple
1915 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001916 self = data->self;
1917 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001918
Barry Warsawfa701a81997-01-16 00:15:11 +00001919 /* Create argument list (argv1, ..., argvN) */
1920 if (!(arg = PyTuple_New(argc - 1)))
1921 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00001922
Barry Warsawfa701a81997-01-16 00:15:11 +00001923 for (i = 0; i < (argc - 1); i++) {
Kurt B. Kaiserab45e272007-08-27 01:55:21 +00001924 if (11 == (i + 1)) { /* the %A arg is the unicode char */
1925 char *a = argv[i + 1];
1926 s = PyUnicode_FromUnicode((Py_UNICODE *) a, strlen(a));
1927 }
1928 else {
1929 s = PyUnicode_FromString(argv[i + 1]);
1930 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001931 if (!s || PyTuple_SetItem(arg, i, s)) {
1932 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00001933 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00001934 }
1935 }
1936 res = PyEval_CallObject(func, arg);
1937 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00001938
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 if (res == NULL)
1940 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00001941
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001942 tres = AsObj(res);
1943 if (tres == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00001944 Py_DECREF(res);
1945 return PythonCmd_Error(interp);
1946 }
Guido van Rossum2834b972000-10-06 16:58:26 +00001947 else {
Martin v. Löwis50fb8662007-08-13 05:41:41 +00001948 Tcl_SetObjResult(Tkapp_Interp(self), tres);
Guido van Rossum2834b972000-10-06 16:58:26 +00001949 rv = TCL_OK;
1950 }
1951
Barry Warsawfa701a81997-01-16 00:15:11 +00001952 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00001953
Guido van Rossum00d93061998-05-28 23:06:38 +00001954 LEAVE_PYTHON
1955
Guido van Rossum2834b972000-10-06 16:58:26 +00001956 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00001957}
1958
1959static void
Fred Drake509d79a2000-07-08 04:04:38 +00001960PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00001961{
Guido van Rossum00d93061998-05-28 23:06:38 +00001962 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1963
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001964 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001965 Py_XDECREF(data->self);
1966 Py_XDECREF(data->func);
1967 PyMem_DEL(data);
1968 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00001969}
1970
Barry Warsawfa701a81997-01-16 00:15:11 +00001971
1972
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001973
1974TCL_DECLARE_MUTEX(command_mutex)
1975
1976typedef struct CommandEvent{
1977 Tcl_Event ev;
1978 Tcl_Interp* interp;
1979 char *name;
1980 int create;
1981 int *status;
1982 ClientData *data;
1983 Tcl_Condition done;
1984} CommandEvent;
1985
1986static int
1987Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001988{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001989 if (ev->create)
1990 *ev->status = Tcl_CreateCommand(
1991 ev->interp, ev->name, PythonCmd,
1992 ev->data, PythonCmdDelete) == NULL;
1993 else
1994 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1995 Tcl_MutexLock(&command_mutex);
1996 Tcl_ConditionNotify(&ev->done);
1997 Tcl_MutexUnlock(&command_mutex);
1998 return 1;
1999}
2000
2001static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002002Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002003{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002004 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002005 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002006 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002007 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002008 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002009
Guido van Rossum43713e52000-02-29 13:59:29 +00002010 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002011 return NULL;
2012 if (!PyCallable_Check(func)) {
2013 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 return NULL;
2015 }
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Martin v. Löwisa9656492003-03-30 08:44:58 +00002017#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002018 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002019 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002020 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002021#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002022
Guido van Rossum00d93061998-05-28 23:06:38 +00002023 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002024 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002025 return PyErr_NoMemory();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00002026 Py_INCREF(self);
2027 Py_INCREF(func);
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002028 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002029 data->func = func;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002030
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002031 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2032 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2033 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2034 ev->interp = self->interp;
2035 ev->create = 1;
2036 ev->name = cmdName;
2037 ev->data = (ClientData)data;
2038 ev->status = &err;
2039 ev->done = NULL;
2040 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2041 }
2042 else {
2043 ENTER_TCL
2044 err = Tcl_CreateCommand(
2045 Tkapp_Interp(self), cmdName, PythonCmd,
2046 (ClientData)data, PythonCmdDelete) == NULL;
2047 LEAVE_TCL
2048 }
2049 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002050 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002051 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002052 return NULL;
2053 }
Guido van Rossum18468821994-06-20 07:49:28 +00002054
Barry Warsawfa701a81997-01-16 00:15:11 +00002055 Py_INCREF(Py_None);
2056 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002057}
2058
Barry Warsawfa701a81997-01-16 00:15:11 +00002059
2060
Guido van Rossum18468821994-06-20 07:49:28 +00002061static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002062Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002063{
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002064 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002065 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002066 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002067
Guido van Rossum43713e52000-02-29 13:59:29 +00002068 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002069 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002070 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2071 CommandEvent *ev;
2072 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2073 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2074 ev->interp = self->interp;
2075 ev->create = 0;
2076 ev->name = cmdName;
2077 ev->status = &err;
2078 ev->done = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002079 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002080 &command_mutex);
2081 }
2082 else {
2083 ENTER_TCL
2084 err = Tcl_DeleteCommand(self->interp, cmdName);
2085 LEAVE_TCL
2086 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002087 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002088 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2089 return NULL;
2090 }
2091 Py_INCREF(Py_None);
2092 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002093}
2094
Barry Warsawfa701a81997-01-16 00:15:11 +00002095
2096
Guido van Rossum00d93061998-05-28 23:06:38 +00002097#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002098/** File Handler **/
2099
Guido van Rossum00d93061998-05-28 23:06:38 +00002100typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002101 PyObject *func;
2102 PyObject *file;
2103 int id;
2104 struct _fhcdata *next;
2105} FileHandler_ClientData;
2106
2107static FileHandler_ClientData *HeadFHCD;
2108
2109static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002110NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002111{
2112 FileHandler_ClientData *p;
2113 p = PyMem_NEW(FileHandler_ClientData, 1);
2114 if (p != NULL) {
2115 Py_XINCREF(func);
2116 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002117 p->func = func;
2118 p->file = file;
2119 p->id = id;
2120 p->next = HeadFHCD;
2121 HeadFHCD = p;
2122 }
2123 return p;
2124}
2125
2126static void
Fred Drake509d79a2000-07-08 04:04:38 +00002127DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002128{
2129 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002130
2131 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002132 while ((p = *pp) != NULL) {
2133 if (p->id == id) {
2134 *pp = p->next;
2135 Py_XDECREF(p->func);
2136 Py_XDECREF(p->file);
2137 PyMem_DEL(p);
2138 }
2139 else
2140 pp = &p->next;
2141 }
2142}
2143
Guido van Rossuma597dde1995-01-10 20:56:29 +00002144static void
Fred Drake509d79a2000-07-08 04:04:38 +00002145FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002146{
Guido van Rossum00d93061998-05-28 23:06:38 +00002147 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002148 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002150 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002151 func = data->func;
2152 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002153
Barry Warsawfa701a81997-01-16 00:15:11 +00002154 arg = Py_BuildValue("(Oi)", file, (long) mask);
2155 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002156 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002157
2158 if (res == NULL) {
2159 errorInCmd = 1;
2160 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2161 }
2162 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002163 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002164}
2165
Guido van Rossum18468821994-06-20 07:49:28 +00002166static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002167Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2168 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002169{
Guido van Rossum00d93061998-05-28 23:06:38 +00002170 FileHandler_ClientData *data;
2171 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002172 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002173
Guido van Rossum2834b972000-10-06 16:58:26 +00002174 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2175 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002176 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002177
Martin v. Löwisa9656492003-03-30 08:44:58 +00002178#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002179 if (!self && !tcl_lock) {
2180 /* We don't have the Tcl lock since Tcl is threaded. */
2181 PyErr_SetString(PyExc_RuntimeError,
2182 "_tkinter.createfilehandler not supported "
2183 "for threaded Tcl");
2184 return NULL;
2185 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002186#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002187
2188 if (self) {
2189 CHECK_TCL_APPARTMENT;
2190 }
2191
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002192 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002193 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002194 return NULL;
2195 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002196 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002197 return NULL;
2198 }
2199
Guido van Rossuma80649b2000-03-28 20:07:05 +00002200 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002201 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002202 return NULL;
2203
Barry Warsawfa701a81997-01-16 00:15:11 +00002204 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002205 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002206 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002207 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002208 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002209 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002210}
2211
2212static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002213Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002214{
Barry Warsawfa701a81997-01-16 00:15:11 +00002215 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002216 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002217
Guido van Rossum43713e52000-02-29 13:59:29 +00002218 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002219 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002220
Martin v. Löwisa9656492003-03-30 08:44:58 +00002221#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002222 if (!self && !tcl_lock) {
2223 /* We don't have the Tcl lock since Tcl is threaded. */
2224 PyErr_SetString(PyExc_RuntimeError,
2225 "_tkinter.deletefilehandler not supported "
2226 "for threaded Tcl");
2227 return NULL;
2228 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002229#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002230
2231 if (self) {
2232 CHECK_TCL_APPARTMENT;
2233 }
2234
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002235 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002236 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002237 return NULL;
2238
Guido van Rossuma80649b2000-03-28 20:07:05 +00002239 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002240
Barry Warsawfa701a81997-01-16 00:15:11 +00002241 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002242 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002243 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002244 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002245 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002246 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002247}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002248#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Barry Warsawfa701a81997-01-16 00:15:11 +00002250
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002251/**** Tktt Object (timer token) ****/
2252
Jeremy Hylton938ace62002-07-17 16:30:39 +00002253static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002254
Guido van Rossum00d93061998-05-28 23:06:38 +00002255typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002257 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002259} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002260
2261static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002262Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002263{
Barry Warsawfa701a81997-01-16 00:15:11 +00002264 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002265 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002266
Guido van Rossum43713e52000-02-29 13:59:29 +00002267 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002268 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002269 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002270 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002271 v->token = NULL;
2272 }
2273 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002275 Py_DECREF(func);
2276 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002277 }
2278 Py_INCREF(Py_None);
2279 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002280}
2281
2282static PyMethodDef Tktt_methods[] =
2283{
Neal Norwitzb0493252002-03-31 14:44:22 +00002284 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002285 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002286};
2287
2288static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002289Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002290{
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002292
Guido van Rossumb18618d2000-05-03 23:44:39 +00002293 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002294 if (v == NULL)
2295 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002296
Guido van Rossum00d93061998-05-28 23:06:38 +00002297 Py_INCREF(func);
2298 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002300
2301 /* Extra reference, deleted when called or when handler is deleted */
2302 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002303 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002304}
2305
2306static void
Fred Drake509d79a2000-07-08 04:04:38 +00002307Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002308{
Guido van Rossum00d93061998-05-28 23:06:38 +00002309 TkttObject *v = (TkttObject *)self;
2310 PyObject *func = v->func;
2311
2312 Py_XDECREF(func);
2313
Guido van Rossumb18618d2000-05-03 23:44:39 +00002314 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002315}
2316
Guido van Rossum597ac201998-05-12 14:36:19 +00002317static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002318Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002319{
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002321 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002322
Tim Peters885d4572001-11-28 20:27:42 +00002323 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002324 v->func == NULL ? ", handler deleted" : "");
Walter Dörwald1ab83302007-05-18 17:15:44 +00002325 return PyUnicode_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002326}
2327
2328static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002329Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002330{
Barry Warsawfa701a81997-01-16 00:15:11 +00002331 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002332}
2333
2334static PyTypeObject Tktt_Type =
2335{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002336 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002337 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002338 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002339 0, /*tp_itemsize */
2340 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002341 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 Tktt_GetAttr, /*tp_getattr */
2343 0, /*tp_setattr */
2344 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002345 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002346 0, /*tp_as_number */
2347 0, /*tp_as_sequence */
2348 0, /*tp_as_mapping */
2349 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002350};
2351
Barry Warsawfa701a81997-01-16 00:15:11 +00002352
2353
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002354/** Timer Handler **/
2355
2356static void
Fred Drake509d79a2000-07-08 04:04:38 +00002357TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002358{
Guido van Rossum00d93061998-05-28 23:06:38 +00002359 TkttObject *v = (TkttObject *)clientData;
2360 PyObject *func = v->func;
2361 PyObject *res;
2362
2363 if (func == NULL)
2364 return;
2365
2366 v->func = NULL;
2367
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002368 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002369
2370 res = PyEval_CallObject(func, NULL);
2371 Py_DECREF(func);
2372 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373
Barry Warsawfa701a81997-01-16 00:15:11 +00002374 if (res == NULL) {
2375 errorInCmd = 1;
2376 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2377 }
2378 else
2379 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002380
2381 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002382}
2383
2384static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002385Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386{
Barry Warsawfa701a81997-01-16 00:15:11 +00002387 int milliseconds;
2388 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002389 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002390
Guido van Rossum2834b972000-10-06 16:58:26 +00002391 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2392 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002393 return NULL;
2394 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002395 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002396 return NULL;
2397 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002398
Martin v. Löwisa9656492003-03-30 08:44:58 +00002399#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002400 if (!self && !tcl_lock) {
2401 /* We don't have the Tcl lock since Tcl is threaded. */
2402 PyErr_SetString(PyExc_RuntimeError,
2403 "_tkinter.createtimerhandler not supported "
2404 "for threaded Tcl");
2405 return NULL;
2406 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002407#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002408
2409 if (self) {
2410 CHECK_TCL_APPARTMENT;
2411 }
2412
Guido van Rossum00d93061998-05-28 23:06:38 +00002413 v = Tktt_New(func);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +00002414 if (v) {
2415 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2416 (ClientData)v);
2417 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002418
Guido van Rossum00d93061998-05-28 23:06:38 +00002419 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002420}
2421
Barry Warsawfa701a81997-01-16 00:15:11 +00002422
Guido van Rossum18468821994-06-20 07:49:28 +00002423/** Event Loop **/
2424
Guido van Rossum18468821994-06-20 07:49:28 +00002425static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002426Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002427{
Barry Warsawfa701a81997-01-16 00:15:11 +00002428 int threshold = 0;
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002429 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002430#ifdef WITH_THREAD
2431 PyThreadState *tstate = PyThreadState_Get();
2432#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002433
Guido van Rossum43713e52000-02-29 13:59:29 +00002434 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002435 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002436
Martin v. Löwisa9656492003-03-30 08:44:58 +00002437#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002438 if (!self && !tcl_lock) {
2439 /* We don't have the Tcl lock since Tcl is threaded. */
2440 PyErr_SetString(PyExc_RuntimeError,
2441 "_tkinter.mainloop not supported "
2442 "for threaded Tcl");
2443 return NULL;
2444 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002445#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002446
2447 if (self) {
2448 CHECK_TCL_APPARTMENT;
2449 self->dispatching = 1;
2450 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002451
Barry Warsawfa701a81997-01-16 00:15:11 +00002452 quitMainLoop = 0;
2453 while (Tk_GetNumMainWindows() > threshold &&
2454 !quitMainLoop &&
2455 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002456 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002457 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002458
2459#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002460 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002461 /* Allow other Python threads to run. */
2462 ENTER_TCL
2463 result = Tcl_DoOneEvent(0);
2464 LEAVE_TCL
2465 }
2466 else {
2467 Py_BEGIN_ALLOW_THREADS
2468 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2469 tcl_tstate = tstate;
2470 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2471 tcl_tstate = NULL;
2472 if(tcl_lock)PyThread_release_lock(tcl_lock);
2473 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002474 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002475 Py_END_ALLOW_THREADS
2476 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002477#else
2478 result = Tcl_DoOneEvent(0);
2479#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002480
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002481 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002482 if (self)
2483 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002484 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002485 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002486 if (result < 0)
2487 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002488 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002489 if (self)
2490 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002491 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002492
Barry Warsawfa701a81997-01-16 00:15:11 +00002493 if (errorInCmd) {
2494 errorInCmd = 0;
2495 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2496 excInCmd = valInCmd = trbInCmd = NULL;
2497 return NULL;
2498 }
2499 Py_INCREF(Py_None);
2500 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002501}
2502
2503static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002504Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002505{
Guido van Rossum35d43371997-08-02 00:09:09 +00002506 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002507 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002508
Guido van Rossum43713e52000-02-29 13:59:29 +00002509 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002510 return NULL;
2511
Guido van Rossum00d93061998-05-28 23:06:38 +00002512 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002513 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002514 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002515 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002516}
2517
2518static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002519Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002520{
2521
Guido van Rossum43713e52000-02-29 13:59:29 +00002522 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002523 return NULL;
2524
2525 quitMainLoop = 1;
2526 Py_INCREF(Py_None);
2527 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002528}
2529
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002530static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002531Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002532{
2533
Guido van Rossum43713e52000-02-29 13:59:29 +00002534 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002535 return NULL;
2536
Christian Heimes217cfd12007-12-02 14:31:20 +00002537 return PyLong_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002538}
2539
David Aschere2b4b322004-02-18 05:59:53 +00002540static PyObject *
2541Tkapp_TkInit(PyObject *self, PyObject *args)
2542{
Thomas Wouters477c8d52006-05-27 19:21:47 +00002543 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002544 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002545 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002546 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002547 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002548 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002549
Thomas Wouters477c8d52006-05-27 19:21:47 +00002550 /* In all current versions of Tk (including 8.4.13), Tk_Init
2551 deadlocks on the second call when the first call failed.
2552 To avoid the deadlock, we just refuse the second call through
2553 a static variable. */
2554 if (has_failed) {
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002555 PyErr_SetString(Tkinter_TclError,
Thomas Wouters477c8d52006-05-27 19:21:47 +00002556 "Calling Tk_Init again after a previous call failed might deadlock");
2557 return NULL;
2558 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002559
David Aschere2b4b322004-02-18 05:59:53 +00002560 /* We want to guard against calling Tk_Init() multiple times */
2561 CHECK_TCL_APPARTMENT;
2562 ENTER_TCL
2563 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2564 ENTER_OVERLAP
2565 if (err == TCL_ERROR) {
Thomas Wouters477c8d52006-05-27 19:21:47 +00002566 /* This sets an exception, but we cannot return right
2567 away because we need to exit the overlap first. */
2568 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002569 } else {
2570 _tk_exists = Tkapp_Result(self);
2571 }
2572 LEAVE_OVERLAP_TCL
2573 if (err == TCL_ERROR) {
2574 return NULL;
2575 }
2576 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2577 if (Tk_Init(interp) == TCL_ERROR) {
2578 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Thomas Wouters477c8d52006-05-27 19:21:47 +00002579 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002580 return NULL;
2581 }
2582 }
2583 Py_INCREF(Py_None);
2584 return Py_None;
2585}
Barry Warsawfa701a81997-01-16 00:15:11 +00002586
Martin v. Löwisffad6332002-11-26 09:28:05 +00002587static PyObject *
2588Tkapp_WantObjects(PyObject *self, PyObject *args)
2589{
2590
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002591 int wantobjects = -1;
2592 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002593 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002594 if (wantobjects == -1)
2595 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002596 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002597
2598 Py_INCREF(Py_None);
2599 return Py_None;
2600}
2601
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002602static PyObject *
2603Tkapp_WillDispatch(PyObject *self, PyObject *args)
2604{
2605
2606 ((TkappObject*)self)->dispatching = 1;
2607
2608 Py_INCREF(Py_None);
2609 return Py_None;
2610}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002611
Barry Warsawfa701a81997-01-16 00:15:11 +00002612
Guido van Rossum18468821994-06-20 07:49:28 +00002613/**** Tkapp Method List ****/
2614
2615static PyMethodDef Tkapp_methods[] =
2616{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002617 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002618 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002619 {"call", Tkapp_Call, METH_VARARGS},
2620 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002621 {"eval", Tkapp_Eval, METH_VARARGS},
2622 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2623 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2624 {"record", Tkapp_Record, METH_VARARGS},
2625 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2626 {"setvar", Tkapp_SetVar, METH_VARARGS},
2627 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2628 {"getvar", Tkapp_GetVar, METH_VARARGS},
2629 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2630 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2631 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2632 {"getint", Tkapp_GetInt, METH_VARARGS},
2633 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2634 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2635 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2636 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2637 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2638 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2639 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2640 {"split", Tkapp_Split, METH_VARARGS},
Guido van Rossumd59da4b2007-05-22 18:11:13 +00002641 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002642 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2643 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002644#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002645 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2646 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002647#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002648 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2649 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2650 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2651 {"quit", Tkapp_Quit, METH_VARARGS},
2652 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002653 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002654 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002655};
2656
Barry Warsawfa701a81997-01-16 00:15:11 +00002657
2658
Guido van Rossum18468821994-06-20 07:49:28 +00002659/**** Tkapp Type Methods ****/
2660
2661static void
Fred Drake509d79a2000-07-08 04:04:38 +00002662Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002663{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002664 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002665 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002666 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002667 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002668 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002669 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002670}
2671
2672static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002673Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002674{
Guido van Rossum35d43371997-08-02 00:09:09 +00002675 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002676}
2677
2678static PyTypeObject Tkapp_Type =
2679{
Martin v. Löwis9f2e3462007-07-21 17:22:18 +00002680 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002681 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002682 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002683 0, /*tp_itemsize */
2684 Tkapp_Dealloc, /*tp_dealloc */
2685 0, /*tp_print */
2686 Tkapp_GetAttr, /*tp_getattr */
2687 0, /*tp_setattr */
2688 0, /*tp_compare */
2689 0, /*tp_repr */
2690 0, /*tp_as_number */
2691 0, /*tp_as_sequence */
2692 0, /*tp_as_mapping */
2693 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002694};
2695
Barry Warsawfa701a81997-01-16 00:15:11 +00002696
2697
Guido van Rossum18468821994-06-20 07:49:28 +00002698/**** Tkinter Module ****/
2699
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002700typedef struct {
2701 PyObject* tuple;
2702 int size; /* current size */
2703 int maxsize; /* allocated size */
2704} FlattenContext;
2705
2706static int
2707_bump(FlattenContext* context, int size)
2708{
Guido van Rossum2834b972000-10-06 16:58:26 +00002709 /* expand tuple to hold (at least) size new items.
2710 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002711
2712 int maxsize = context->maxsize * 2;
2713
2714 if (maxsize < context->size + size)
2715 maxsize = context->size + size;
2716
2717 context->maxsize = maxsize;
2718
Tim Peters4324aa32001-05-28 22:30:08 +00002719 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002720}
2721
2722static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002723_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002724{
2725 /* add tuple or list to argument tuple (recursively) */
2726
2727 int i, size;
2728
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002729 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002730 PyErr_SetString(PyExc_ValueError,
2731 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002732 return 0;
2733 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002734 size = PyList_GET_SIZE(item);
2735 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002736 if (context->size + size > context->maxsize &&
2737 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002738 return 0;
2739 /* copy items to output tuple */
2740 for (i = 0; i < size; i++) {
2741 PyObject *o = PyList_GET_ITEM(item, i);
2742 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002743 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002744 return 0;
2745 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002746 if (context->size + 1 > context->maxsize &&
2747 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002748 return 0;
2749 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002750 PyTuple_SET_ITEM(context->tuple,
2751 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002752 }
2753 }
2754 } else if (PyTuple_Check(item)) {
2755 /* same, for tuples */
2756 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002757 if (context->size + size > context->maxsize &&
2758 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002759 return 0;
2760 for (i = 0; i < size; i++) {
2761 PyObject *o = PyTuple_GET_ITEM(item, i);
2762 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002763 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002764 return 0;
2765 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002766 if (context->size + 1 > context->maxsize &&
2767 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768 return 0;
2769 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002770 PyTuple_SET_ITEM(context->tuple,
2771 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002772 }
2773 }
2774 } else {
2775 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2776 return 0;
2777 }
2778 return 1;
2779}
2780
2781static PyObject *
2782Tkinter_Flatten(PyObject* self, PyObject* args)
2783{
2784 FlattenContext context;
2785 PyObject* item;
2786
2787 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2788 return NULL;
2789
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002790 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002791 if (context.maxsize <= 0)
2792 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002793
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002794 context.tuple = PyTuple_New(context.maxsize);
2795 if (!context.tuple)
2796 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002797
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798 context.size = 0;
2799
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002800 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801 return NULL;
2802
Tim Peters4324aa32001-05-28 22:30:08 +00002803 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002804 return NULL;
2805
2806 return context.tuple;
2807}
2808
Guido van Rossum18468821994-06-20 07:49:28 +00002809static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002810Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002811{
Barry Warsawfa701a81997-01-16 00:15:11 +00002812 char *screenName = NULL;
2813 char *baseName = NULL;
2814 char *className = NULL;
2815 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002816 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002817 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002818 int sync = 0; /* pass -sync to wish */
2819 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002820
Guido van Rossum35d43371997-08-02 00:09:09 +00002821 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002822 if (baseName != NULL)
2823 baseName++;
2824 else
2825 baseName = Py_GetProgramName();
2826 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002827
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002828 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002829 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002830 &interactive, &wantobjects, &wantTk,
2831 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002832 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002833
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002834 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002835 interactive, wantobjects, wantTk,
2836 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002837}
2838
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002839static PyObject *
2840Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2841{
2842 int new_val;
2843 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2844 return NULL;
2845 if (new_val < 0) {
2846 PyErr_SetString(PyExc_ValueError,
2847 "busywaitinterval must be >= 0");
2848 return NULL;
2849 }
2850 Tkinter_busywaitinterval = new_val;
2851 Py_INCREF(Py_None);
2852 return Py_None;
2853}
2854
2855static char setbusywaitinterval_doc[] =
2856"setbusywaitinterval(n) -> None\n\
2857\n\
2858Set the busy-wait interval in milliseconds between successive\n\
2859calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2860It should be set to a divisor of the maximum time between\n\
2861frames in an animation.";
2862
2863static PyObject *
2864Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2865{
Christian Heimes217cfd12007-12-02 14:31:20 +00002866 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002867}
2868
2869static char getbusywaitinterval_doc[] =
2870"getbusywaitinterval() -> int\n\
2871\n\
2872Return the current busy-wait interval between successive\n\
2873calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2874
Guido van Rossum18468821994-06-20 07:49:28 +00002875static PyMethodDef moduleMethods[] =
2876{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002877 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2878 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002879#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002880 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2881 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002882#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002883 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2884 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2885 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2886 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002887 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2888 setbusywaitinterval_doc},
2889 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2890 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002891 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002892};
2893
Guido van Rossum7bf15641998-05-22 18:28:17 +00002894#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002895
2896static int stdin_ready = 0;
2897
Guido van Rossumad4db171998-06-13 13:56:28 +00002898#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002899static void
Fred Drake509d79a2000-07-08 04:04:38 +00002900MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002901{
2902 stdin_ready = 1;
2903}
Guido van Rossumad4db171998-06-13 13:56:28 +00002904#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002905
Martin v. Löwisa9656492003-03-30 08:44:58 +00002906#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002907static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002908#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002909
Guido van Rossum18468821994-06-20 07:49:28 +00002910static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002911EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002912{
Guido van Rossumad4db171998-06-13 13:56:28 +00002913#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002914 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002915#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002916#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002917 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002918#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002919 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002920 errorInCmd = 0;
2921#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002922 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002923 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002924#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002925 while (!errorInCmd && !stdin_ready) {
2926 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002927#ifdef MS_WINDOWS
2928 if (_kbhit()) {
2929 stdin_ready = 1;
2930 break;
2931 }
2932#endif
2933#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002934 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002935 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00002936 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002937
Guido van Rossum00d93061998-05-28 23:06:38 +00002938 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002939
2940 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002941 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00002942 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002943 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00002944 Py_END_ALLOW_THREADS
2945#else
2946 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002947#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002948
2949 if (result < 0)
2950 break;
2951 }
Guido van Rossumad4db171998-06-13 13:56:28 +00002952#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00002953 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00002954#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002955 if (errorInCmd) {
2956 errorInCmd = 0;
2957 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2958 excInCmd = valInCmd = trbInCmd = NULL;
2959 PyErr_Print();
2960 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002961#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002962 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002963#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00002964 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002965}
Guido van Rossum18468821994-06-20 07:49:28 +00002966
Guido van Rossum00d93061998-05-28 23:06:38 +00002967#endif
2968
Guido van Rossum7bf15641998-05-22 18:28:17 +00002969static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002970EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002971{
Guido van Rossum00d93061998-05-28 23:06:38 +00002972#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002974#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002975 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002976#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977 PyOS_InputHook = EventHook;
2978 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002979#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002980}
2981
2982static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002983DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984{
Guido van Rossum00d93061998-05-28 23:06:38 +00002985#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002986 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2987 PyOS_InputHook = NULL;
2988 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002989#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002990}
2991
Barry Warsawfa701a81997-01-16 00:15:11 +00002992
2993/* all errors will be checked in one fell swoop in init_tkinter() */
2994static void
Fred Drake509d79a2000-07-08 04:04:38 +00002995ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00002996{
Christian Heimes217cfd12007-12-02 14:31:20 +00002997 PyObject *v = PyLong_FromLong(val);
Barry Warsawfa701a81997-01-16 00:15:11 +00002998 if (v) {
2999 PyDict_SetItemString(d, name, v);
3000 Py_DECREF(v);
3001 }
3002}
3003static void
Fred Drake509d79a2000-07-08 04:04:38 +00003004ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003005{
Martin v. Löwis4040fb82007-08-13 06:01:43 +00003006 PyObject *v = PyUnicode_FromString(val);
Barry Warsawfa701a81997-01-16 00:15:11 +00003007 if (v) {
3008 PyDict_SetItemString(d, name, v);
3009 Py_DECREF(v);
3010 }
3011}
3012
3013
Mark Hammond62b1ab12002-07-23 06:31:15 +00003014PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003015init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003016{
Barry Warsawfa701a81997-01-16 00:15:11 +00003017 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003018
Christian Heimes90aa7642007-12-19 02:45:37 +00003019 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003020
3021#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003022 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003023#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003024
Barry Warsawfa701a81997-01-16 00:15:11 +00003025 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003026 if (m == NULL)
3027 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003028
Barry Warsawfa701a81997-01-16 00:15:11 +00003029 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003030 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003031 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003032
Guido van Rossum35d43371997-08-02 00:09:09 +00003033 ins_long(d, "READABLE", TCL_READABLE);
3034 ins_long(d, "WRITABLE", TCL_WRITABLE);
3035 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3036 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3037 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3038 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3039 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3040 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3041 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003042 ins_string(d, "TK_VERSION", TK_VERSION);
3043 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003044
Guido van Rossum83551bf1997-09-13 00:44:23 +00003045 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003046
Christian Heimes90aa7642007-12-19 02:45:37 +00003047 Py_TYPE(&Tktt_Type) = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003048 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3049
Christian Heimes90aa7642007-12-19 02:45:37 +00003050 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003051 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003052
3053#ifdef TK_AQUA
3054 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3055 * start waking up. Note that Tcl_FindExecutable will do this, this
3056 * code must be above it! The original warning from
3057 * tkMacOSXAppInit.c is copied below.
3058 *
3059 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3060 * Tcl interpreter for now. It probably should work to do this
3061 * in the other order, but for now it doesn't seem to.
3062 *
3063 */
3064 Tk_MacOSXSetupTkNotifier();
3065#endif
3066
3067
Guido van Rossume187b0e2000-03-27 21:46:29 +00003068 /* This helps the dynamic loader; in Unicode aware Tcl versions
3069 it also helps Tcl find its encodings. */
3070 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003071
Barry Warsawfa701a81997-01-16 00:15:11 +00003072 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003073 return;
3074
Guido van Rossum43ff8681998-07-14 18:02:13 +00003075#if 0
3076 /* This was not a good idea; through <Destroy> bindings,
3077 Tcl_Finalize() may invoke Python code but at that point the
3078 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003079 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003080#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003081
Guido van Rossum18468821994-06-20 07:49:28 +00003082}