blob: 3cef4e73a81b25f68c1f5bc5d3e48a654ea602ff [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
47#define PyBool_FromLong PyInt_FromLong
48#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
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 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 Heimese93237d2007-12-19 02:37:44 +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 Heimese93237d2007-12-19 02:37:44 +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);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000340#ifdef Py_USING_UNICODE
Guido van Rossum2834b972000-10-06 16:58:26 +0000341 else if (PyUnicode_Check(value)) {
342 PyObject *v = PyUnicode_AsUTF8String(value);
343 if (v == NULL)
344 return NULL;
345 if (PyList_Append(tmp, v) != 0) {
346 Py_DECREF(v);
347 return NULL;
348 }
349 Py_DECREF(v);
350 return PyString_AsString(v);
351 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000352#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000353 else {
354 PyObject *v = PyObject_Str(value);
Guido van Rossum2834b972000-10-06 16:58:26 +0000355 if (v == NULL)
356 return NULL;
357 if (PyList_Append(tmp, v) != 0) {
358 Py_DECREF(v);
359 return NULL;
360 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000361 Py_DECREF(v);
362 return PyString_AsString(v);
363 }
Guido van Rossum18468821994-06-20 07:49:28 +0000364}
365
Barry Warsawfa701a81997-01-16 00:15:11 +0000366
367
Guido van Rossum18468821994-06-20 07:49:28 +0000368#define ARGSZ 64
369
370static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000371Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000372{
Barry Warsawfa701a81997-01-16 00:15:11 +0000373 PyObject *tmp = NULL;
374 char *argvStore[ARGSZ];
375 char **argv = NULL;
376 int fvStore[ARGSZ];
377 int *fv = NULL;
Guido van Rossum2834b972000-10-06 16:58:26 +0000378 int argc = 0, fvc = 0, i;
Barry Warsawfa701a81997-01-16 00:15:11 +0000379 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000380
Barry Warsawfa701a81997-01-16 00:15:11 +0000381 if (!(tmp = PyList_New(0)))
382 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Barry Warsawfa701a81997-01-16 00:15:11 +0000384 argv = argvStore;
385 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Barry Warsawfa701a81997-01-16 00:15:11 +0000387 if (args == NULL)
388 argc = 0;
389
390 else if (!PyTuple_Check(args)) {
391 argc = 1;
392 fv[0] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000393 if (!(argv[0] = AsString(args, tmp)))
394 goto finally;
Guido van Rossum18468821994-06-20 07:49:28 +0000395 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000396 else {
397 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000398
Barry Warsawfa701a81997-01-16 00:15:11 +0000399 if (argc > ARGSZ) {
Guido van Rossum35d43371997-08-02 00:09:09 +0000400 argv = (char **)ckalloc(argc * sizeof(char *));
401 fv = (int *)ckalloc(argc * sizeof(int));
Barry Warsawfa701a81997-01-16 00:15:11 +0000402 if (argv == NULL || fv == NULL) {
403 PyErr_NoMemory();
404 goto finally;
405 }
406 }
407
408 for (i = 0; i < argc; i++) {
409 PyObject *v = PyTuple_GetItem(args, i);
410 if (PyTuple_Check(v)) {
411 fv[i] = 1;
412 if (!(argv[i] = Merge(v)))
413 goto finally;
Guido van Rossum2834b972000-10-06 16:58:26 +0000414 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000415 }
416 else if (v == Py_None) {
417 argc = i;
418 break;
419 }
420 else {
421 fv[i] = 0;
Guido van Rossum2834b972000-10-06 16:58:26 +0000422 if (!(argv[i] = AsString(v, tmp)))
423 goto finally;
424 fvc++;
Barry Warsawfa701a81997-01-16 00:15:11 +0000425 }
426 }
Guido van Rossum18468821994-06-20 07:49:28 +0000427 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000428 res = Tcl_Merge(argc, argv);
Guido van Rossum2834b972000-10-06 16:58:26 +0000429 if (res == NULL)
430 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000431
Barry Warsawfa701a81997-01-16 00:15:11 +0000432 finally:
Guido van Rossum2834b972000-10-06 16:58:26 +0000433 for (i = 0; i < fvc; i++)
Barry Warsawfa701a81997-01-16 00:15:11 +0000434 if (fv[i]) {
435 ckfree(argv[i]);
436 }
437 if (argv != argvStore)
438 ckfree(FREECAST argv);
439 if (fv != fvStore)
440 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000441
Barry Warsawfa701a81997-01-16 00:15:11 +0000442 Py_DECREF(tmp);
443 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000444}
445
Barry Warsawfa701a81997-01-16 00:15:11 +0000446
447
Guido van Rossum18468821994-06-20 07:49:28 +0000448static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000449Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000450{
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 int argc;
452 char **argv;
453 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000454
Barry Warsawfa701a81997-01-16 00:15:11 +0000455 if (list == NULL) {
456 Py_INCREF(Py_None);
457 return Py_None;
458 }
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Guido van Rossum00d93061998-05-28 23:06:38 +0000460 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000461 /* Not a list.
462 * Could be a quoted string containing funnies, e.g. {"}.
463 * Return the string itself.
464 */
Barry Warsawfa701a81997-01-16 00:15:11 +0000465 return PyString_FromString(list);
466 }
Guido van Rossum18468821994-06-20 07:49:28 +0000467
Barry Warsawfa701a81997-01-16 00:15:11 +0000468 if (argc == 0)
469 v = PyString_FromString("");
470 else if (argc == 1)
471 v = PyString_FromString(argv[0]);
Guido van Rossum35d43371997-08-02 00:09:09 +0000472 else if ((v = PyTuple_New(argc)) != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000473 int i;
474 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000475
Barry Warsawfa701a81997-01-16 00:15:11 +0000476 for (i = 0; i < argc; i++) {
Guido van Rossum00d93061998-05-28 23:06:38 +0000477 if ((w = Split(argv[i])) == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +0000478 Py_DECREF(v);
479 v = NULL;
480 break;
481 }
482 PyTuple_SetItem(v, i, w);
483 }
484 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000485 Tcl_Free(FREECAST argv);
Barry Warsawfa701a81997-01-16 00:15:11 +0000486 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000487}
488
Martin v. Löwisffad6332002-11-26 09:28:05 +0000489/* In some cases, Tcl will still return strings that are supposed to be
490 lists. SplitObj walks through a nested tuple, finding string objects that
491 need to be split. */
492
493PyObject *
494SplitObj(PyObject *arg)
495{
496 if (PyTuple_Check(arg)) {
497 int i, size;
498 PyObject *elem, *newelem, *result;
499
500 size = PyTuple_Size(arg);
501 result = NULL;
502 /* Recursively invoke SplitObj for all tuple items.
503 If this does not return a new object, no action is
504 needed. */
505 for(i = 0; i < size; i++) {
506 elem = PyTuple_GetItem(arg, i);
507 newelem = SplitObj(elem);
508 if (!newelem) {
509 Py_XDECREF(result);
510 return NULL;
511 }
512 if (!result) {
513 int k;
514 if (newelem == elem) {
515 Py_DECREF(newelem);
516 continue;
517 }
518 result = PyTuple_New(size);
519 if (!result)
520 return NULL;
521 for(k = 0; k < i; k++) {
522 elem = PyTuple_GetItem(arg, k);
523 Py_INCREF(elem);
524 PyTuple_SetItem(result, k, elem);
525 }
526 }
527 PyTuple_SetItem(result, i, newelem);
528 }
529 if (result)
530 return result;
531 /* Fall through, returning arg. */
532 }
533 else if (PyString_Check(arg)) {
534 int argc;
535 char **argv;
536 char *list = PyString_AsString(arg);
537
538 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
539 Py_INCREF(arg);
540 return arg;
541 }
542 Tcl_Free(FREECAST argv);
543 if (argc > 1)
544 return Split(PyString_AsString(arg));
545 /* Fall through, returning arg. */
546 }
547 Py_INCREF(arg);
548 return arg;
549}
Barry Warsawfa701a81997-01-16 00:15:11 +0000550
551
Guido van Rossum18468821994-06-20 07:49:28 +0000552/**** Tkapp Object ****/
553
554#ifndef WITH_APPINIT
555int
Fred Drake509d79a2000-07-08 04:04:38 +0000556Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000557{
Barry Warsawfa701a81997-01-16 00:15:11 +0000558 Tk_Window main;
David Aschere2b4b322004-02-18 05:59:53 +0000559 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000560
Barry Warsawfa701a81997-01-16 00:15:11 +0000561 if (Tcl_Init(interp) == TCL_ERROR) {
Guido van Rossumada6d872000-10-12 17:14:46 +0000562 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
Barry Warsawfa701a81997-01-16 00:15:11 +0000563 return TCL_ERROR;
564 }
David Aschere2b4b322004-02-18 05:59:53 +0000565 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
566 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
567 main = Tk_MainWindow(interp);
568 if (Tk_Init(interp) == TCL_ERROR) {
569 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
570 return TCL_ERROR;
571 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000572 }
573 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000574}
575#endif /* !WITH_APPINIT */
576
Guido van Rossum18468821994-06-20 07:49:28 +0000577
Barry Warsawfa701a81997-01-16 00:15:11 +0000578
579
580/* Initialize the Tk application; see the `main' function in
581 * `tkMain.c'.
582 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000583
Thomas Wouters58d05102000-07-24 14:43:35 +0000584static void EnableEventHook(void); /* Forward */
585static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000586
Barry Warsawfa701a81997-01-16 00:15:11 +0000587static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000588Tkapp_New(char *screenName, char *baseName, char *className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000589 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000590{
591 TkappObject *v;
592 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000593
Guido van Rossumb18618d2000-05-03 23:44:39 +0000594 v = PyObject_New(TkappObject, &Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000595 if (v == NULL)
596 return NULL;
597
598 v->interp = Tcl_CreateInterp();
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +0000599 v->wantobjects = wantobjects;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000600 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
601 TCL_GLOBAL_ONLY) != NULL;
602 v->thread_id = Tcl_GetCurrentThread();
603 v->dispatching = 0;
604
605#ifndef TCL_THREADS
606 if (v->threaded) {
607 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
608 Py_DECREF(v);
609 return 0;
610 }
611#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000612#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000613 if (v->threaded && tcl_lock) {
614 /* If Tcl is threaded, we don't need the lock. */
615 PyThread_free_lock(tcl_lock);
616 tcl_lock = NULL;
617 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000618#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000619
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000620 v->BooleanType = Tcl_GetObjType("boolean");
621 v->ByteArrayType = Tcl_GetObjType("bytearray");
622 v->DoubleType = Tcl_GetObjType("double");
623 v->IntType = Tcl_GetObjType("int");
624 v->ListType = Tcl_GetObjType("list");
625 v->ProcBodyType = Tcl_GetObjType("procbody");
626 v->StringType = Tcl_GetObjType("string");
627
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000628 /* Delete the 'exit' command, which can screw things up */
629 Tcl_DeleteCommand(v->interp, "exit");
630
Barry Warsawfa701a81997-01-16 00:15:11 +0000631 if (screenName != NULL)
632 Tcl_SetVar2(v->interp, "env", "DISPLAY",
633 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000634
Barry Warsawfa701a81997-01-16 00:15:11 +0000635 if (interactive)
636 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
637 else
638 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000639
Barry Warsawfa701a81997-01-16 00:15:11 +0000640 /* This is used to get the application class for Tk 4.1 and up */
641 argv0 = (char*)ckalloc(strlen(className) + 1);
642 if (!argv0) {
643 PyErr_NoMemory();
644 Py_DECREF(v);
645 return NULL;
646 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000647
Barry Warsawfa701a81997-01-16 00:15:11 +0000648 strcpy(argv0, className);
Neal Norwitz9dbc7dd2005-12-19 06:08:59 +0000649 if (isupper(Py_CHARMASK(argv0[0])))
Neal Norwitz65c05b22006-04-10 02:17:47 +0000650 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
Barry Warsawfa701a81997-01-16 00:15:11 +0000651 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
652 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000653
David Aschere2b4b322004-02-18 05:59:53 +0000654 if (! wantTk) {
655 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
656 }
657
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000658 /* some initial arguments need to be in argv */
659 if (sync || use) {
Tim Peters51fa3b72004-08-04 02:16:48 +0000660 char *args;
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000661 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000662
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000663 if (sync)
664 len += sizeof "-sync";
665 if (use)
666 len += strlen(use) + sizeof "-use ";
667
Tim Peters51fa3b72004-08-04 02:16:48 +0000668 args = (char*)ckalloc(len);
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000669 if (!args) {
670 PyErr_NoMemory();
671 Py_DECREF(v);
672 return NULL;
673 }
674
675 args[0] = '\0';
676 if (sync)
677 strcat(args, "-sync");
678 if (use) {
679 if (sync)
680 strcat(args, " ");
681 strcat(args, "-use ");
682 strcat(args, use);
683 }
684
685 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
686 ckfree(args);
687 }
688
Thomas Woutersa74a84d2006-03-07 14:04:31 +0000689 if (Tcl_AppInit(v->interp) != TCL_OK) {
690 PyObject *result = Tkinter_Error((PyObject *)v);
691 Py_DECREF((PyObject *)v);
692 return (TkappObject *)result;
693 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000694
Guido van Rossum7bf15641998-05-22 18:28:17 +0000695 EnableEventHook();
696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000698}
699
Barry Warsawfa701a81997-01-16 00:15:11 +0000700
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701static void
702Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
703 Tcl_Condition *cond, Tcl_Mutex *mutex)
704{
705 Py_BEGIN_ALLOW_THREADS;
706 Tcl_MutexLock(mutex);
707 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
708 Tcl_ThreadAlert(self->thread_id);
709 Tcl_ConditionWait(cond, mutex, NULL);
710 Tcl_MutexUnlock(mutex);
711 Py_END_ALLOW_THREADS
712}
713
Barry Warsawfa701a81997-01-16 00:15:11 +0000714
Guido van Rossum18468821994-06-20 07:49:28 +0000715/** Tcl Eval **/
716
Martin v. Löwisffad6332002-11-26 09:28:05 +0000717typedef struct {
718 PyObject_HEAD
719 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000720 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000721} PyTclObject;
722
723staticforward PyTypeObject PyTclObject_Type;
724#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
725
726static PyObject *
727newPyTclObject(Tcl_Obj *arg)
728{
729 PyTclObject *self;
730 self = PyObject_New(PyTclObject, &PyTclObject_Type);
731 if (self == NULL)
732 return NULL;
733 Tcl_IncrRefCount(arg);
734 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000735 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000736 return (PyObject*)self;
737}
738
739static void
740PyTclObject_dealloc(PyTclObject *self)
741{
742 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000743 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000744 PyObject_Del(self);
745}
746
747static PyObject *
748PyTclObject_str(PyTclObject *self)
749{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000750 if (self->string && PyString_Check(self->string)) {
751 Py_INCREF(self->string);
752 return self->string;
753 }
754 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000755 return PyString_FromString(Tcl_GetString(self->value));
756}
757
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000758static char*
759PyTclObject_TclString(PyObject *self)
760{
761 return Tcl_GetString(((PyTclObject*)self)->value);
762}
763
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000764/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000765PyDoc_STRVAR(PyTclObject_string__doc__,
766"the string representation of this object, either as string or Unicode");
767
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000768static PyObject *
769PyTclObject_string(PyTclObject *self, void *ignored)
770{
771 char *s;
772 int i, len;
773 if (!self->string) {
774 s = Tcl_GetStringFromObj(self->value, &len);
775 for (i = 0; i < len; i++)
776 if (s[i] & 0x80)
777 break;
778#ifdef Py_USING_UNICODE
779 if (i == len)
780 /* It is an ASCII string. */
781 self->string = PyString_FromStringAndSize(s, len);
782 else {
783 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
784 if (!self->string) {
785 PyErr_Clear();
786 self->string = PyString_FromStringAndSize(s, len);
787 }
788 }
789#else
790 self->string = PyString_FromStringAndSize(s, len);
791#endif
792 if (!self->string)
793 return NULL;
794 }
795 Py_INCREF(self->string);
796 return self->string;
797}
798
799#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000800PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
801
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000802static PyObject *
803PyTclObject_unicode(PyTclObject *self, void *ignored)
804{
805 char *s;
806 int len;
807 if (self->string && PyUnicode_Check(self->string)) {
808 Py_INCREF(self->string);
809 return self->string;
810 }
811 /* XXX Could chache result if it is non-ASCII. */
812 s = Tcl_GetStringFromObj(self->value, &len);
813 return PyUnicode_DecodeUTF8(s, len, "strict");
814}
815#endif
816
Martin v. Löwisffad6332002-11-26 09:28:05 +0000817static PyObject *
818PyTclObject_repr(PyTclObject *self)
819{
820 char buf[50];
Martin v. Löwisfba73692004-11-13 11:13:35 +0000821 PyOS_snprintf(buf, 50, "<%s object at %p>",
822 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000823 return PyString_FromString(buf);
824}
825
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000826static int
827PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
828{
829 int res;
830 res = strcmp(Tcl_GetString(self->value),
831 Tcl_GetString(other->value));
832 if (res < 0) return -1;
833 if (res > 0) return 1;
834 return 0;
835}
836
Martin v. Löwis39195712003-01-04 00:33:13 +0000837PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
838
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839static PyObject*
840get_typename(PyTclObject* obj, void* ignored)
841{
842 return PyString_FromString(obj->value->typePtr->name);
843}
844
Martin v. Löwis39195712003-01-04 00:33:13 +0000845
Martin v. Löwisffad6332002-11-26 09:28:05 +0000846static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000847 {"typename", (getter)get_typename, NULL, get_typename__doc__},
848 {"string", (getter)PyTclObject_string, NULL,
849 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000850 {0},
851};
852
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000853static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000854#ifdef Py_USING_UNICODE
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000855 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000856 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000857#endif
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000858 {0}
859};
860
Martin v. Löwisffad6332002-11-26 09:28:05 +0000861statichere PyTypeObject PyTclObject_Type = {
862 PyObject_HEAD_INIT(NULL)
863 0, /*ob_size*/
864 "_tkinter.Tcl_Obj", /*tp_name*/
865 sizeof(PyTclObject), /*tp_basicsize*/
866 0, /*tp_itemsize*/
867 /* methods */
868 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
869 0, /*tp_print*/
870 0, /*tp_getattr*/
871 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000872 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873 (reprfunc)PyTclObject_repr, /*tp_repr*/
874 0, /*tp_as_number*/
875 0, /*tp_as_sequence*/
876 0, /*tp_as_mapping*/
877 0, /*tp_hash*/
878 0, /*tp_call*/
879 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000880 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000881 0, /*tp_setattro*/
882 0, /*tp_as_buffer*/
883 Py_TPFLAGS_DEFAULT, /*tp_flags*/
884 0, /*tp_doc*/
885 0, /*tp_traverse*/
886 0, /*tp_clear*/
887 0, /*tp_richcompare*/
888 0, /*tp_weaklistoffset*/
889 0, /*tp_iter*/
890 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000891 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000892 0, /*tp_members*/
893 PyTclObject_getsetlist, /*tp_getset*/
894 0, /*tp_base*/
895 0, /*tp_dict*/
896 0, /*tp_descr_get*/
897 0, /*tp_descr_set*/
898 0, /*tp_dictoffset*/
899 0, /*tp_init*/
900 0, /*tp_alloc*/
901 0, /*tp_new*/
902 0, /*tp_free*/
903 0, /*tp_is_gc*/
904};
905
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000906static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000907AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000908{
909 Tcl_Obj *result;
910
911 if (PyString_Check(value))
912 return Tcl_NewStringObj(PyString_AS_STRING(value),
913 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000914 else if (PyBool_Check(value))
915 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000916 else if (PyInt_Check(value))
917 return Tcl_NewLongObj(PyInt_AS_LONG(value));
918 else if (PyFloat_Check(value))
919 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
920 else if (PyTuple_Check(value)) {
921 Tcl_Obj **argv = (Tcl_Obj**)
922 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
923 int i;
924 if(!argv)
925 return 0;
926 for(i=0;i<PyTuple_Size(value);i++)
927 argv[i] = AsObj(PyTuple_GetItem(value,i));
928 result = Tcl_NewListObj(PyTuple_Size(value), argv);
929 ckfree(FREECAST argv);
930 return result;
931 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000932#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000933 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000934 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
Neal Norwitz047f3c72006-06-12 02:06:42 +0000935 Py_ssize_t size = PyUnicode_GET_SIZE(value);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000936 /* This #ifdef assumes that Tcl uses UCS-2.
937 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000938#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000939 Tcl_UniChar *outbuf;
Neal Norwitz047f3c72006-06-12 02:06:42 +0000940 Py_ssize_t i;
941 assert(size < size * sizeof(Tcl_UniChar));
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000942 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
943 if (!outbuf) {
944 PyErr_NoMemory();
945 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000946 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000947 for (i = 0; i < size; i++) {
948 if (inbuf[i] >= 0x10000) {
949 /* Tcl doesn't do UTF-16, yet. */
950 PyErr_SetString(PyExc_ValueError,
951 "unsupported character");
952 ckfree(FREECAST outbuf);
953 return NULL;
954 }
955 outbuf[i] = inbuf[i];
956 }
957 result = Tcl_NewUnicodeObj(outbuf, size);
958 ckfree(FREECAST outbuf);
959 return result;
960#else
961 return Tcl_NewUnicodeObj(inbuf, size);
962#endif
963
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000964 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000965#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966 else if(PyTclObject_Check(value)) {
967 Tcl_Obj *v = ((PyTclObject*)value)->value;
968 Tcl_IncrRefCount(v);
969 return v;
970 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000971 else {
972 PyObject *v = PyObject_Str(value);
973 if (!v)
974 return 0;
975 result = AsObj(v);
976 Py_DECREF(v);
977 return result;
978 }
979}
980
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981static PyObject*
982FromObj(PyObject* tkapp, Tcl_Obj *value)
983{
984 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000985 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000986
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000987 if (value->typePtr == NULL) {
988 /* If the result contains any bytes with the top bit set,
989 it's UTF-8 and we should decode it to Unicode */
990#ifdef Py_USING_UNICODE
991 int i;
992 char *s = value->bytes;
993 int len = value->length;
994 for (i = 0; i < len; i++) {
995 if (value->bytes[i] & 0x80)
996 break;
997 }
998
999 if (i == value->length)
1000 result = PyString_FromStringAndSize(s, len);
1001 else {
1002 /* Convert UTF-8 to Unicode string */
1003 result = PyUnicode_DecodeUTF8(s, len, "strict");
1004 if (result == NULL) {
1005 PyErr_Clear();
1006 result = PyString_FromStringAndSize(s, len);
1007 }
1008 }
1009#else
Martin v. Löwise2713be2005-03-08 15:03:08 +00001010 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001011#endif
1012 return result;
1013 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001014
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001015 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016 result = value->internalRep.longValue ? Py_True : Py_False;
1017 Py_INCREF(result);
1018 return result;
1019 }
1020
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001021 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001023 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024 return PyString_FromStringAndSize(data, size);
1025 }
1026
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001027 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028 return PyFloat_FromDouble(value->internalRep.doubleValue);
1029 }
1030
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001031 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032 return PyInt_FromLong(value->internalRep.longValue);
1033 }
1034
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001035 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036 int size;
1037 int i, status;
1038 PyObject *elem;
1039 Tcl_Obj *tcl_elem;
1040
1041 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1042 if (status == TCL_ERROR)
1043 return Tkinter_Error(tkapp);
1044 result = PyTuple_New(size);
1045 if (!result)
1046 return NULL;
1047 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001048 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001049 value, i, &tcl_elem);
1050 if (status == TCL_ERROR) {
1051 Py_DECREF(result);
1052 return Tkinter_Error(tkapp);
1053 }
1054 elem = FromObj(tkapp, tcl_elem);
1055 if (!elem) {
1056 Py_DECREF(result);
1057 return NULL;
1058 }
1059 PyTuple_SetItem(result, i, elem);
1060 }
1061 return result;
1062 }
1063
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001064 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001065 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001066 }
1067
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001068 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001069#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001070#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001071 PyObject *result;
1072 int size;
1073 Tcl_UniChar *input;
1074 Py_UNICODE *output;
1075
1076 size = Tcl_GetCharLength(value);
1077 result = PyUnicode_FromUnicode(NULL, size);
1078 if (!result)
1079 return NULL;
1080 input = Tcl_GetUnicode(value);
1081 output = PyUnicode_AS_UNICODE(result);
1082 while (size--)
1083 *output++ = *input++;
1084 return result;
1085#else
1086 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1087 Tcl_GetCharLength(value));
1088#endif
1089#else
1090 int size;
1091 char *c;
1092 c = Tcl_GetStringFromObj(value, &size);
1093 return PyString_FromStringAndSize(c, size);
1094#endif
1095 }
1096
1097 return newPyTclObject(value);
1098}
1099
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001100/* This mutex synchronizes inter-thread command calls. */
1101
1102TCL_DECLARE_MUTEX(call_mutex)
1103
1104typedef struct Tkapp_CallEvent {
1105 Tcl_Event ev; /* Must be first */
1106 TkappObject *self;
1107 PyObject *args;
1108 int flags;
1109 PyObject **res;
1110 PyObject **exc_type, **exc_value, **exc_tb;
1111 Tcl_Condition done;
1112} Tkapp_CallEvent;
1113
1114void
1115Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001116{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001117 int i;
1118 for (i = 0; i < objc; i++)
1119 Tcl_DecrRefCount(objv[i]);
1120 if (objv != objStore)
1121 ckfree(FREECAST objv);
1122}
Guido van Rossum18468821994-06-20 07:49:28 +00001123
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124/* Convert Python objects to Tcl objects. This must happen in the
1125 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001126
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001127static Tcl_Obj**
1128Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1129{
1130 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001131 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001132 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001133 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001134
Guido van Rossum212643f1998-04-29 16:22:14 +00001135 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001136 objv[0] = AsObj(args);
1137 if (objv[0] == 0)
1138 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001139 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001140 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001141 }
1142 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001143 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001144
Guido van Rossum632de272000-03-29 00:19:50 +00001145 if (objc > ARGSZ) {
1146 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1147 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001148 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001149 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001150 goto finally;
1151 }
1152 }
1153
Guido van Rossum632de272000-03-29 00:19:50 +00001154 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001155 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001156 if (v == Py_None) {
1157 objc = i;
1158 break;
1159 }
Guido van Rossum632de272000-03-29 00:19:50 +00001160 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001161 if (!objv[i]) {
1162 /* Reset objc, so it attempts to clear
1163 objects only up to i. */
1164 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001165 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001166 }
Guido van Rossum632de272000-03-29 00:19:50 +00001167 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001168 }
1169 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170 *pobjc = objc;
1171 return objv;
1172finally:
1173 Tkapp_CallDeallocArgs(objv, objStore, objc);
1174 return NULL;
1175}
Guido van Rossum212643f1998-04-29 16:22:14 +00001176
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179static PyObject*
1180Tkapp_CallResult(TkappObject *self)
1181{
1182 PyObject *res = NULL;
1183 if(self->wantobjects) {
1184 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001185 /* Not sure whether the IncrRef is necessary, but something
1186 may overwrite the interpreter result while we are
1187 converting it. */
1188 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001190 Tcl_DecrRefCount(value);
1191 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001193 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001194
Guido van Rossum990f5c62000-05-04 15:07:16 +00001195 /* If the result contains any bytes with the top bit set,
1196 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001197#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001198 while (*p != '\0') {
1199 if (*p & 0x80)
1200 break;
1201 p++;
1202 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001203
Guido van Rossum990f5c62000-05-04 15:07:16 +00001204 if (*p == '\0')
1205 res = PyString_FromStringAndSize(s, (int)(p-s));
1206 else {
1207 /* Convert UTF-8 to Unicode string */
1208 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001209 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1210 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211 PyErr_Clear();
1212 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001213 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001214 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001215#else
1216 p = strchr(p, '\0');
1217 res = PyString_FromStringAndSize(s, (int)(p-s));
1218#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001219 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220 return res;
1221}
Guido van Rossum632de272000-03-29 00:19:50 +00001222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223/* Tkapp_CallProc is the event procedure that is executed in the context of
1224 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1225 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001226
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001227static int
1228Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1229{
1230 Tcl_Obj *objStore[ARGSZ];
1231 Tcl_Obj **objv;
1232 int objc;
1233 int i;
1234 ENTER_PYTHON
1235 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1236 if (!objv) {
1237 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1238 *(e->res) = NULL;
1239 }
1240 LEAVE_PYTHON
1241 if (!objv)
1242 goto done;
1243 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1244 ENTER_PYTHON
1245 if (i == TCL_ERROR) {
1246 *(e->res) = NULL;
1247 *(e->exc_type) = NULL;
1248 *(e->exc_tb) = NULL;
1249 *(e->exc_value) = PyObject_CallFunction(
1250 Tkinter_TclError, "s",
1251 Tcl_GetStringResult(e->self->interp));
1252 }
1253 else {
1254 *(e->res) = Tkapp_CallResult(e->self);
1255 }
1256 LEAVE_PYTHON
1257 done:
1258 /* Wake up calling thread. */
1259 Tcl_MutexLock(&call_mutex);
1260 Tcl_ConditionNotify(&e->done);
1261 Tcl_MutexUnlock(&call_mutex);
1262 return 1;
1263}
1264
1265/* This is the main entry point for calling a Tcl command.
1266 It supports three cases, with regard to threading:
1267 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1268 the context of the calling thread.
1269 2. Tcl is threaded, caller of the command is in the interpreter thread:
1270 Execute the command in the calling thread. Since the Tcl lock will
1271 not be used, we can merge that with case 1.
1272 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1273 the interpreter thread. Allocation of Tcl objects needs to occur in the
1274 interpreter thread, so we ship the PyObject* args to the target thread,
1275 and perform processing there. */
1276
1277static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001278Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001279{
1280 Tcl_Obj *objStore[ARGSZ];
1281 Tcl_Obj **objv = NULL;
1282 int objc, i;
1283 PyObject *res = NULL;
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001284 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1286 int flags = TCL_EVAL_DIRECT;
1287
Kurt B. Kaiserd67a3b92007-07-05 22:03:39 +00001288 /* If args is a single tuple, replace with contents of tuple */
1289 if (1 == PyTuple_Size(args)){
1290 PyObject* item = PyTuple_GetItem(args, 0);
1291 if (PyTuple_Check(item))
1292 args = item;
1293 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001294#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1296 /* We cannot call the command directly. Instead, we must
1297 marshal the parameters to the interpreter thread. */
1298 Tkapp_CallEvent *ev;
1299 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001300 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1303 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1304 ev->self = self;
1305 ev->args = args;
1306 ev->res = &res;
1307 ev->exc_type = &exc_type;
1308 ev->exc_value = &exc_value;
1309 ev->exc_tb = &exc_tb;
1310 ev->done = (Tcl_Condition)0;
1311
1312 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1313
1314 if (res == NULL) {
1315 if (exc_type)
1316 PyErr_Restore(exc_type, exc_value, exc_tb);
1317 else
1318 PyErr_SetObject(Tkinter_TclError, exc_value);
1319 }
1320 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001321 else
1322#endif
1323 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324
1325 objv = Tkapp_CallArgs(args, objStore, &objc);
1326 if (!objv)
1327 return NULL;
1328
1329 ENTER_TCL
1330
1331 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1332
1333 ENTER_OVERLAP
1334
1335 if (i == TCL_ERROR)
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001336 Tkinter_Error(selfptr);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001337 else
1338 res = Tkapp_CallResult(self);
1339
1340 LEAVE_OVERLAP_TCL
1341
1342 Tkapp_CallDeallocArgs(objv, objStore, objc);
1343 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001344 return res;
1345}
1346
1347
1348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001349Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001350{
Guido van Rossum212643f1998-04-29 16:22:14 +00001351 /* Could do the same here as for Tkapp_Call(), but this is not used
1352 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353 way for the user to do what all its Global* variants do (save and
1354 reset the scope pointer, call the local version, restore the saved
1355 scope pointer). */
1356
Guido van Rossum62320c91998-06-15 04:36:09 +00001357 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001358 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001359
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360 CHECK_TCL_APPARTMENT;
1361
Guido van Rossum62320c91998-06-15 04:36:09 +00001362 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001363 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001364 int err;
1365 ENTER_TCL
1366 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001367 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001368 if (err == TCL_ERROR)
1369 res = Tkinter_Error(self);
1370 else
1371 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001372 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001373 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001374 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001375
1376 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001377}
1378
1379static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001380Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001381{
Barry Warsawfa701a81997-01-16 00:15:11 +00001382 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001383 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001384 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385
Guido van Rossum43713e52000-02-29 13:59:29 +00001386 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001387 return NULL;
1388
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389 CHECK_TCL_APPARTMENT;
1390
Guido van Rossum00d93061998-05-28 23:06:38 +00001391 ENTER_TCL
1392 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001393 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001394 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001395 res = Tkinter_Error(self);
1396 else
1397 res = PyString_FromString(Tkapp_Result(self));
1398 LEAVE_OVERLAP_TCL
1399 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001400}
1401
1402static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001403Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001404{
Barry Warsawfa701a81997-01-16 00:15:11 +00001405 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001406 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001408
Guido van Rossum43713e52000-02-29 13:59:29 +00001409 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001410 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001411
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412 CHECK_TCL_APPARTMENT;
1413
Guido van Rossum00d93061998-05-28 23:06:38 +00001414 ENTER_TCL
1415 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001416 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001417 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001418 res = Tkinter_Error(self);
1419 else
1420 res = PyString_FromString(Tkapp_Result(self));
1421 LEAVE_OVERLAP_TCL
1422 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001423}
1424
1425static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001426Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001427{
Barry Warsawfa701a81997-01-16 00:15:11 +00001428 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001429 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001430 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001431
Guido van Rossum43713e52000-02-29 13:59:29 +00001432 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001433 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001434
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001435 CHECK_TCL_APPARTMENT;
1436
Guido van Rossum00d93061998-05-28 23:06:38 +00001437 ENTER_TCL
1438 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001439 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001440 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001441 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001442
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 else
1444 res = PyString_FromString(Tkapp_Result(self));
1445 LEAVE_OVERLAP_TCL
1446 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001447}
1448
1449static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001450Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001451{
Barry Warsawfa701a81997-01-16 00:15:11 +00001452 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001453 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001454 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001455
Guido van Rossum35d43371997-08-02 00:09:09 +00001456 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001457 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001458
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459 CHECK_TCL_APPARTMENT;
1460
Guido van Rossum00d93061998-05-28 23:06:38 +00001461 ENTER_TCL
1462 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001463 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001464 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001465 res = Tkinter_Error(self);
1466 else
1467 res = PyString_FromString(Tkapp_Result(self));
1468 LEAVE_OVERLAP_TCL
1469 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001470}
1471
1472static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001473Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001474{
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001476
Guido van Rossum43713e52000-02-29 13:59:29 +00001477 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001478 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001479 CHECK_TCL_APPARTMENT;
1480
Guido van Rossum00d93061998-05-28 23:06:38 +00001481 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001482 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001483 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001484
Barry Warsawfa701a81997-01-16 00:15:11 +00001485 Py_INCREF(Py_None);
1486 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001487}
1488
Barry Warsawfa701a81997-01-16 00:15:11 +00001489
1490
Guido van Rossum18468821994-06-20 07:49:28 +00001491/** Tcl Variable **/
1492
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493TCL_DECLARE_MUTEX(var_mutex)
1494
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001495typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496typedef struct VarEvent {
1497 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001498 PyObject *self;
1499 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001501 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001503 PyObject **exc_type;
1504 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506} VarEvent;
1507
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001508static int
1509varname_converter(PyObject *in, void *_out)
1510{
1511 char **out = (char**)_out;
1512 if (PyString_Check(in)) {
1513 *out = PyString_AsString(in);
1514 return 1;
1515 }
1516 if (PyTclObject_Check(in)) {
1517 *out = PyTclObject_TclString(in);
1518 return 1;
1519 }
1520 /* XXX: Should give diagnostics. */
1521 return 0;
1522}
1523
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001524void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001525var_perform(VarEvent *ev)
1526{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001527 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1528 if (!*(ev->res)) {
1529 PyObject *exc, *val, *tb;
1530 PyErr_Fetch(&exc, &val, &tb);
1531 PyErr_NormalizeException(&exc, &val, &tb);
1532 *(ev->exc_type) = exc;
1533 *(ev->exc_val) = val;
1534 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001536
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537}
1538
1539static int
1540var_proc(VarEvent* ev, int flags)
1541{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001542 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001543 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544 Tcl_MutexLock(&var_mutex);
1545 Tcl_ConditionNotify(&ev->cond);
1546 Tcl_MutexUnlock(&var_mutex);
1547 LEAVE_PYTHON
1548 return 1;
1549}
1550
1551static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001552var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001553{
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001554 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001555#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001557 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001558 VarEvent *ev;
1559 PyObject *res, *exc_type, *exc_val;
1560
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001561 /* The current thread is not the interpreter thread. Marshal
1562 the call to the interpreter thread, then wait for
1563 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001564 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001565 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001566
1567 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1568
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001569 ev->self = selfptr;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001570 ev->args = args;
1571 ev->flags = flags;
1572 ev->func = func;
1573 ev->res = &res;
1574 ev->exc_type = &exc_type;
1575 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576 ev->cond = NULL;
1577 ev->ev.proc = (Tcl_EventProc*)var_proc;
1578 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001579 if (!res) {
1580 PyErr_SetObject(exc_type, exc_val);
1581 Py_DECREF(exc_type);
1582 Py_DECREF(exc_val);
1583 return NULL;
1584 }
1585 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001586 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001587#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001588 /* Tcl is not threaded, or this is the interpreter thread. */
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001589 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590}
1591
Guido van Rossum18468821994-06-20 07:49:28 +00001592static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001593SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001594{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001595 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001596 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001597 PyObject *res = NULL;
1598 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001600 if (PyArg_ParseTuple(args, "O&O:setvar",
1601 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001602 /* XXX Acquire tcl lock??? */
1603 newval = AsObj(newValue);
1604 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001605 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001606 ENTER_TCL
1607 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1608 newval, flags);
1609 ENTER_OVERLAP
1610 if (!ok)
1611 Tkinter_Error(self);
1612 else {
1613 res = Py_None;
1614 Py_INCREF(res);
1615 }
1616 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001617 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001618 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001619 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001620 if (PyArg_ParseTuple(args, "ssO:setvar",
1621 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001622 /* XXX must hold tcl lock already??? */
1623 newval = AsObj(newValue);
1624 ENTER_TCL
1625 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1626 ENTER_OVERLAP
1627 if (!ok)
1628 Tkinter_Error(self);
1629 else {
1630 res = Py_None;
1631 Py_INCREF(res);
1632 }
1633 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001634 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001635 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001636 return NULL;
1637 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001638 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001639 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001640}
1641
1642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001643Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001644{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001645 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001646}
1647
1648static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001649Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001650{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001651 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001652}
1653
Barry Warsawfa701a81997-01-16 00:15:11 +00001654
1655
Guido van Rossum18468821994-06-20 07:49:28 +00001656static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001657GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001658{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001659 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001660 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001661 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001662
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001663 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1664 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001665 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001666
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001667 ENTER_TCL
1668 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1669 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001670 if (tres == NULL) {
1671 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1672 } else {
1673 if (((TkappObject*)self)->wantobjects) {
1674 res = FromObj(self, tres);
1675 }
1676 else {
1677 res = PyString_FromString(Tcl_GetString(tres));
1678 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001679 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001681 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001682}
1683
1684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001685Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001686{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001687 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001688}
1689
1690static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001691Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001692{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001693 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001694}
1695
Barry Warsawfa701a81997-01-16 00:15:11 +00001696
1697
Guido van Rossum18468821994-06-20 07:49:28 +00001698static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001699UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001700{
Guido van Rossum35d43371997-08-02 00:09:09 +00001701 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001702 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001703 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001704
Guido van Rossum43713e52000-02-29 13:59:29 +00001705 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001706 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001707
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001708 ENTER_TCL
1709 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1710 ENTER_OVERLAP
1711 if (code == TCL_ERROR)
1712 res = Tkinter_Error(self);
1713 else {
1714 Py_INCREF(Py_None);
1715 res = Py_None;
1716 }
1717 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001718 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001719}
1720
1721static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001722Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001723{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001724 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001725}
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001730 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001731}
1732
Barry Warsawfa701a81997-01-16 00:15:11 +00001733
1734
Guido van Rossum18468821994-06-20 07:49:28 +00001735/** Tcl to Python **/
1736
1737static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001738Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001739{
Barry Warsawfa701a81997-01-16 00:15:11 +00001740 char *s;
1741 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Martin v. Löwisffad6332002-11-26 09:28:05 +00001743 if (PyTuple_Size(args) == 1) {
1744 PyObject* o = PyTuple_GetItem(args, 0);
1745 if (PyInt_Check(o)) {
1746 Py_INCREF(o);
1747 return o;
1748 }
1749 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001750 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001751 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001752 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 return Tkinter_Error(self);
1754 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
1757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Barry Warsawfa701a81997-01-16 00:15:11 +00001760 char *s;
1761 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001762
Martin v. Löwisffad6332002-11-26 09:28:05 +00001763 if (PyTuple_Size(args) == 1) {
1764 PyObject *o = PyTuple_GetItem(args, 0);
1765 if (PyFloat_Check(o)) {
1766 Py_INCREF(o);
1767 return o;
1768 }
1769 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001770 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001771 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001772 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001773 return Tkinter_Error(self);
1774 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001775}
1776
1777static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001778Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001779{
Barry Warsawfa701a81997-01-16 00:15:11 +00001780 char *s;
1781 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001782
Martin v. Löwisffad6332002-11-26 09:28:05 +00001783 if (PyTuple_Size(args) == 1) {
1784 PyObject *o = PyTuple_GetItem(args, 0);
1785 if (PyInt_Check(o)) {
1786 Py_INCREF(o);
1787 return o;
1788 }
1789 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001790 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001791 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001792 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1793 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001794 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001795}
1796
1797static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001798Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001799{
Barry Warsawfa701a81997-01-16 00:15:11 +00001800 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001801 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001803
Guido van Rossum43713e52000-02-29 13:59:29 +00001804 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001805 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001806
1807 CHECK_TCL_APPARTMENT;
1808
Guido van Rossum00d93061998-05-28 23:06:38 +00001809 ENTER_TCL
1810 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001811 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001812 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001813 res = Tkinter_Error(self);
1814 else
1815 res = Py_BuildValue("s", Tkapp_Result(self));
1816 LEAVE_OVERLAP_TCL
1817 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
1820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001821Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001822{
Barry Warsawfa701a81997-01-16 00:15:11 +00001823 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001824 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001825 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001826 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001827
Guido van Rossum43713e52000-02-29 13:59:29 +00001828 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001829 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001830
1831 CHECK_TCL_APPARTMENT;
1832
Guido van Rossum00d93061998-05-28 23:06:38 +00001833 ENTER_TCL
1834 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001835 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001836 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("l", v);
1840 LEAVE_OVERLAP_TCL
1841 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001842}
1843
1844static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001845Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001846{
Barry Warsawfa701a81997-01-16 00:15:11 +00001847 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001848 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001849 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001850 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Guido van Rossum43713e52000-02-29 13:59:29 +00001852 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001853 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001854 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001855 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001856 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001857 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001858 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001859 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001860 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001861 res = Tkinter_Error(self);
1862 else
1863 res = Py_BuildValue("d", v);
1864 LEAVE_OVERLAP_TCL
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Barry Warsawfa701a81997-01-16 00:15:11 +00001871 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001872 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001873 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001874 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Guido van Rossum43713e52000-02-29 13:59:29 +00001876 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001877 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001878 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001879 ENTER_TCL
1880 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001881 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001882 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001883 res = Tkinter_Error(self);
1884 else
1885 res = Py_BuildValue("i", v);
1886 LEAVE_OVERLAP_TCL
1887 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001888}
1889
Barry Warsawfa701a81997-01-16 00:15:11 +00001890
1891
Guido van Rossum18468821994-06-20 07:49:28 +00001892static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001893Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001894{
Barry Warsawfa701a81997-01-16 00:15:11 +00001895 char *list;
1896 int argc;
1897 char **argv;
1898 PyObject *v;
1899 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001900
Martin v. Löwisffad6332002-11-26 09:28:05 +00001901 if (PyTuple_Size(args) == 1) {
1902 v = PyTuple_GetItem(args, 0);
1903 if (PyTuple_Check(v)) {
1904 Py_INCREF(v);
1905 return v;
1906 }
1907 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001908 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001909 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001910
Neal Norwitzd1c55102003-05-29 00:17:03 +00001911 if (Tcl_SplitList(Tkapp_Interp(self), list,
1912 &argc, &argv) == TCL_ERROR) {
1913 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001914 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001915 }
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Barry Warsawfa701a81997-01-16 00:15:11 +00001917 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001918 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001919
Barry Warsawfa701a81997-01-16 00:15:11 +00001920 for (i = 0; i < argc; i++) {
1921 PyObject *s = PyString_FromString(argv[i]);
1922 if (!s || PyTuple_SetItem(v, i, s)) {
1923 Py_DECREF(v);
1924 v = NULL;
1925 goto finally;
1926 }
1927 }
Guido van Rossum18468821994-06-20 07:49:28 +00001928
Barry Warsawfa701a81997-01-16 00:15:11 +00001929 finally:
1930 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001931 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001932 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
1935static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001936Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001937{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001938 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001940
Martin v. Löwisffad6332002-11-26 09:28:05 +00001941 if (PyTuple_Size(args) == 1) {
1942 PyObject* o = PyTuple_GetItem(args, 0);
1943 if (PyTuple_Check(o)) {
1944 o = SplitObj(o);
1945 return o;
1946 }
1947 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001948 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001949 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001950 v = Split(list);
1951 PyMem_Free(list);
1952 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001953}
1954
1955static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001956Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001957{
Barry Warsawfa701a81997-01-16 00:15:11 +00001958 char *s = Merge(args);
1959 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Barry Warsawfa701a81997-01-16 00:15:11 +00001961 if (s) {
1962 res = PyString_FromString(s);
1963 ckfree(s);
1964 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001965
1966 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001967}
1968
Barry Warsawfa701a81997-01-16 00:15:11 +00001969
1970
Guido van Rossum18468821994-06-20 07:49:28 +00001971/** Tcl Command **/
1972
Guido van Rossum00d93061998-05-28 23:06:38 +00001973/* Client data struct */
1974typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001975 PyObject *self;
1976 PyObject *func;
1977} PythonCmd_ClientData;
1978
1979static int
Fred Drake509d79a2000-07-08 04:04:38 +00001980PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001981{
1982 errorInCmd = 1;
1983 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1984 LEAVE_PYTHON
1985 return TCL_ERROR;
1986}
1987
Guido van Rossum18468821994-06-20 07:49:28 +00001988/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001989 * function or method.
1990 */
Guido van Rossum18468821994-06-20 07:49:28 +00001991static int
Fred Drake509d79a2000-07-08 04:04:38 +00001992PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001993{
Guido van Rossum00d93061998-05-28 23:06:38 +00001994 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Martin v. Löwis17cb5cf2008-01-01 21:05:17 +00001995 PyObject *self, *func, *arg, *res;
Guido van Rossum2834b972000-10-06 16:58:26 +00001996 int i, rv;
Martin v. Löwis17cb5cf2008-01-01 21:05:17 +00001997 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001999 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001 /* TBD: no error checking here since we know, via the
2002 * Tkapp_CreateCommand() that the client data is a two-tuple
2003 */
Guido van Rossum00d93061998-05-28 23:06:38 +00002004 self = data->self;
2005 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002006
Barry Warsawfa701a81997-01-16 00:15:11 +00002007 /* Create argument list (argv1, ..., argvN) */
2008 if (!(arg = PyTuple_New(argc - 1)))
2009 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002010
Barry Warsawfa701a81997-01-16 00:15:11 +00002011 for (i = 0; i < (argc - 1); i++) {
2012 PyObject *s = PyString_FromString(argv[i + 1]);
2013 if (!s || PyTuple_SetItem(arg, i, s)) {
2014 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00002015 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00002016 }
2017 }
2018 res = PyEval_CallObject(func, arg);
2019 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002020
Barry Warsawfa701a81997-01-16 00:15:11 +00002021 if (res == NULL)
2022 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002023
Martin v. Löwis17cb5cf2008-01-01 21:05:17 +00002024 obj_res = AsObj(res);
2025 if (obj_res == NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002026 Py_DECREF(res);
2027 return PythonCmd_Error(interp);
2028 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002029 else {
Martin v. Löwis17cb5cf2008-01-01 21:05:17 +00002030 Tcl_SetObjResult(Tkapp_Interp(self), obj_res);
Guido van Rossum2834b972000-10-06 16:58:26 +00002031 rv = TCL_OK;
2032 }
2033
Barry Warsawfa701a81997-01-16 00:15:11 +00002034 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002035
Guido van Rossum00d93061998-05-28 23:06:38 +00002036 LEAVE_PYTHON
2037
Guido van Rossum2834b972000-10-06 16:58:26 +00002038 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002039}
2040
2041static void
Fred Drake509d79a2000-07-08 04:04:38 +00002042PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002043{
Guido van Rossum00d93061998-05-28 23:06:38 +00002044 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2045
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002046 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002047 Py_XDECREF(data->self);
2048 Py_XDECREF(data->func);
2049 PyMem_DEL(data);
2050 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002051}
2052
Barry Warsawfa701a81997-01-16 00:15:11 +00002053
2054
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002055
2056TCL_DECLARE_MUTEX(command_mutex)
2057
2058typedef struct CommandEvent{
2059 Tcl_Event ev;
2060 Tcl_Interp* interp;
2061 char *name;
2062 int create;
2063 int *status;
2064 ClientData *data;
2065 Tcl_Condition done;
2066} CommandEvent;
2067
2068static int
2069Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002070{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002071 if (ev->create)
2072 *ev->status = Tcl_CreateCommand(
2073 ev->interp, ev->name, PythonCmd,
2074 ev->data, PythonCmdDelete) == NULL;
2075 else
2076 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2077 Tcl_MutexLock(&command_mutex);
2078 Tcl_ConditionNotify(&ev->done);
2079 Tcl_MutexUnlock(&command_mutex);
2080 return 1;
2081}
2082
2083static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002084Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085{
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002086 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002087 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002088 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002089 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002090 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002091
Guido van Rossum43713e52000-02-29 13:59:29 +00002092 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002093 return NULL;
2094 if (!PyCallable_Check(func)) {
2095 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002096 return NULL;
2097 }
Guido van Rossum18468821994-06-20 07:49:28 +00002098
Martin v. Löwisa9656492003-03-30 08:44:58 +00002099#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002100 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002101 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002102 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002103#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002104
Guido van Rossum00d93061998-05-28 23:06:38 +00002105 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002106 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002107 return PyErr_NoMemory();
Neal Norwitzce5b3c32006-07-16 02:02:57 +00002108 Py_INCREF(self);
2109 Py_INCREF(func);
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002110 data->self = selfptr;
Guido van Rossum00d93061998-05-28 23:06:38 +00002111 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002112
2113 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2114 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2115 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2116 ev->interp = self->interp;
2117 ev->create = 1;
2118 ev->name = cmdName;
2119 ev->data = (ClientData)data;
2120 ev->status = &err;
2121 ev->done = NULL;
2122 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2123 }
2124 else {
2125 ENTER_TCL
2126 err = Tcl_CreateCommand(
2127 Tkapp_Interp(self), cmdName, PythonCmd,
2128 (ClientData)data, PythonCmdDelete) == NULL;
2129 LEAVE_TCL
2130 }
2131 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002132 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002133 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002134 return NULL;
2135 }
Guido van Rossum18468821994-06-20 07:49:28 +00002136
Barry Warsawfa701a81997-01-16 00:15:11 +00002137 Py_INCREF(Py_None);
2138 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002139}
2140
Barry Warsawfa701a81997-01-16 00:15:11 +00002141
2142
Guido van Rossum18468821994-06-20 07:49:28 +00002143static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002144Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002145{
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002146 TkappObject *self = (TkappObject*)selfptr;
Barry Warsawfa701a81997-01-16 00:15:11 +00002147 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002148 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Guido van Rossum43713e52000-02-29 13:59:29 +00002150 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002151 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002152 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2153 CommandEvent *ev;
2154 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2155 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2156 ev->interp = self->interp;
2157 ev->create = 0;
2158 ev->name = cmdName;
2159 ev->status = &err;
2160 ev->done = NULL;
2161 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2162 &command_mutex);
2163 }
2164 else {
2165 ENTER_TCL
2166 err = Tcl_DeleteCommand(self->interp, cmdName);
2167 LEAVE_TCL
2168 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002169 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002170 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2171 return NULL;
2172 }
2173 Py_INCREF(Py_None);
2174 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002175}
2176
Barry Warsawfa701a81997-01-16 00:15:11 +00002177
2178
Guido van Rossum00d93061998-05-28 23:06:38 +00002179#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002180/** File Handler **/
2181
Guido van Rossum00d93061998-05-28 23:06:38 +00002182typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002183 PyObject *func;
2184 PyObject *file;
2185 int id;
2186 struct _fhcdata *next;
2187} FileHandler_ClientData;
2188
2189static FileHandler_ClientData *HeadFHCD;
2190
2191static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002192NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002193{
2194 FileHandler_ClientData *p;
2195 p = PyMem_NEW(FileHandler_ClientData, 1);
2196 if (p != NULL) {
2197 Py_XINCREF(func);
2198 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002199 p->func = func;
2200 p->file = file;
2201 p->id = id;
2202 p->next = HeadFHCD;
2203 HeadFHCD = p;
2204 }
2205 return p;
2206}
2207
2208static void
Fred Drake509d79a2000-07-08 04:04:38 +00002209DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002210{
2211 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002212
2213 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002214 while ((p = *pp) != NULL) {
2215 if (p->id == id) {
2216 *pp = p->next;
2217 Py_XDECREF(p->func);
2218 Py_XDECREF(p->file);
2219 PyMem_DEL(p);
2220 }
2221 else
2222 pp = &p->next;
2223 }
2224}
2225
Guido van Rossuma597dde1995-01-10 20:56:29 +00002226static void
Fred Drake509d79a2000-07-08 04:04:38 +00002227FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002228{
Guido van Rossum00d93061998-05-28 23:06:38 +00002229 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002230 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002231
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002232 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002233 func = data->func;
2234 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002235
Barry Warsawfa701a81997-01-16 00:15:11 +00002236 arg = Py_BuildValue("(Oi)", file, (long) mask);
2237 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002238 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002239
2240 if (res == NULL) {
2241 errorInCmd = 1;
2242 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2243 }
2244 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002245 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002246}
2247
Guido van Rossum18468821994-06-20 07:49:28 +00002248static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002249Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2250 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002251{
Guido van Rossum00d93061998-05-28 23:06:38 +00002252 FileHandler_ClientData *data;
2253 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002254 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002255
Guido van Rossum2834b972000-10-06 16:58:26 +00002256 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2257 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002258 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002259
Martin v. Löwisa9656492003-03-30 08:44:58 +00002260#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002261 if (!self && !tcl_lock) {
2262 /* We don't have the Tcl lock since Tcl is threaded. */
2263 PyErr_SetString(PyExc_RuntimeError,
2264 "_tkinter.createfilehandler not supported "
2265 "for threaded Tcl");
2266 return NULL;
2267 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002268#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002269
2270 if (self) {
2271 CHECK_TCL_APPARTMENT;
2272 }
2273
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002274 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002275 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002276 return NULL;
2277 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002278 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 return NULL;
2280 }
2281
Guido van Rossuma80649b2000-03-28 20:07:05 +00002282 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002283 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 return NULL;
2285
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002287 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002288 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002289 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002290 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002291 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002292}
2293
2294static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002295Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002296{
Barry Warsawfa701a81997-01-16 00:15:11 +00002297 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002298 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002299
Guido van Rossum43713e52000-02-29 13:59:29 +00002300 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002301 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002302
Martin v. Löwisa9656492003-03-30 08:44:58 +00002303#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002304 if (!self && !tcl_lock) {
2305 /* We don't have the Tcl lock since Tcl is threaded. */
2306 PyErr_SetString(PyExc_RuntimeError,
2307 "_tkinter.deletefilehandler not supported "
2308 "for threaded Tcl");
2309 return NULL;
2310 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002311#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002312
2313 if (self) {
2314 CHECK_TCL_APPARTMENT;
2315 }
2316
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002317 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002318 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002319 return NULL;
2320
Guido van Rossuma80649b2000-03-28 20:07:05 +00002321 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002322
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002324 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002325 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002326 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002327 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002328 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002329}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002330#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002331
Barry Warsawfa701a81997-01-16 00:15:11 +00002332
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002333/**** Tktt Object (timer token) ****/
2334
Jeremy Hylton938ace62002-07-17 16:30:39 +00002335static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336
Guido van Rossum00d93061998-05-28 23:06:38 +00002337typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002338 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002339 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002340 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002341} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002342
2343static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002344Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345{
Barry Warsawfa701a81997-01-16 00:15:11 +00002346 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002347 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348
Guido van Rossum43713e52000-02-29 13:59:29 +00002349 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002350 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002351 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002352 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002353 v->token = NULL;
2354 }
2355 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002356 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002357 Py_DECREF(func);
2358 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002359 }
2360 Py_INCREF(Py_None);
2361 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002362}
2363
2364static PyMethodDef Tktt_methods[] =
2365{
Neal Norwitzb0493252002-03-31 14:44:22 +00002366 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002367 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002368};
2369
2370static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002371Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372{
Barry Warsawfa701a81997-01-16 00:15:11 +00002373 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002374
Guido van Rossumb18618d2000-05-03 23:44:39 +00002375 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002376 if (v == NULL)
2377 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002378
Guido van Rossum00d93061998-05-28 23:06:38 +00002379 Py_INCREF(func);
2380 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002381 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002382
2383 /* Extra reference, deleted when called or when handler is deleted */
2384 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002385 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002386}
2387
2388static void
Fred Drake509d79a2000-07-08 04:04:38 +00002389Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002390{
Guido van Rossum00d93061998-05-28 23:06:38 +00002391 TkttObject *v = (TkttObject *)self;
2392 PyObject *func = v->func;
2393
2394 Py_XDECREF(func);
2395
Guido van Rossumb18618d2000-05-03 23:44:39 +00002396 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002397}
2398
Guido van Rossum597ac201998-05-12 14:36:19 +00002399static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002400Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002401{
Barry Warsawfa701a81997-01-16 00:15:11 +00002402 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002403 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404
Tim Peters885d4572001-11-28 20:27:42 +00002405 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002406 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002407 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002408}
2409
2410static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002411Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412{
Barry Warsawfa701a81997-01-16 00:15:11 +00002413 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414}
2415
2416static PyTypeObject Tktt_Type =
2417{
Martin v. Löwis68192102007-07-21 06:55:02 +00002418 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002419 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002420 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002421 0, /*tp_itemsize */
2422 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002423 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002424 Tktt_GetAttr, /*tp_getattr */
2425 0, /*tp_setattr */
2426 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002427 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002428 0, /*tp_as_number */
2429 0, /*tp_as_sequence */
2430 0, /*tp_as_mapping */
2431 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002432};
2433
Barry Warsawfa701a81997-01-16 00:15:11 +00002434
2435
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436/** Timer Handler **/
2437
2438static void
Fred Drake509d79a2000-07-08 04:04:38 +00002439TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002440{
Guido van Rossum00d93061998-05-28 23:06:38 +00002441 TkttObject *v = (TkttObject *)clientData;
2442 PyObject *func = v->func;
2443 PyObject *res;
2444
2445 if (func == NULL)
2446 return;
2447
2448 v->func = NULL;
2449
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002450 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002451
2452 res = PyEval_CallObject(func, NULL);
2453 Py_DECREF(func);
2454 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002455
Barry Warsawfa701a81997-01-16 00:15:11 +00002456 if (res == NULL) {
2457 errorInCmd = 1;
2458 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2459 }
2460 else
2461 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002462
2463 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002464}
2465
2466static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002467Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002468{
Barry Warsawfa701a81997-01-16 00:15:11 +00002469 int milliseconds;
2470 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002471 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472
Guido van Rossum2834b972000-10-06 16:58:26 +00002473 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2474 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002475 return NULL;
2476 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002477 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002478 return NULL;
2479 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002480
Martin v. Löwisa9656492003-03-30 08:44:58 +00002481#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002482 if (!self && !tcl_lock) {
2483 /* We don't have the Tcl lock since Tcl is threaded. */
2484 PyErr_SetString(PyExc_RuntimeError,
2485 "_tkinter.createtimerhandler not supported "
2486 "for threaded Tcl");
2487 return NULL;
2488 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002489#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002490
2491 if (self) {
2492 CHECK_TCL_APPARTMENT;
2493 }
2494
Guido van Rossum00d93061998-05-28 23:06:38 +00002495 v = Tktt_New(func);
Neal Norwitz5f17d9a2006-08-12 02:33:36 +00002496 if (v) {
2497 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2498 (ClientData)v);
2499 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002500
Guido van Rossum00d93061998-05-28 23:06:38 +00002501 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002502}
2503
Barry Warsawfa701a81997-01-16 00:15:11 +00002504
Guido van Rossum18468821994-06-20 07:49:28 +00002505/** Event Loop **/
2506
Guido van Rossum18468821994-06-20 07:49:28 +00002507static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002508Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002509{
Barry Warsawfa701a81997-01-16 00:15:11 +00002510 int threshold = 0;
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002511 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002512#ifdef WITH_THREAD
2513 PyThreadState *tstate = PyThreadState_Get();
2514#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002515
Guido van Rossum43713e52000-02-29 13:59:29 +00002516 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002517 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002518
Martin v. Löwisa9656492003-03-30 08:44:58 +00002519#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002520 if (!self && !tcl_lock) {
2521 /* We don't have the Tcl lock since Tcl is threaded. */
2522 PyErr_SetString(PyExc_RuntimeError,
2523 "_tkinter.mainloop not supported "
2524 "for threaded Tcl");
2525 return NULL;
2526 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002527#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002528
2529 if (self) {
2530 CHECK_TCL_APPARTMENT;
2531 self->dispatching = 1;
2532 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002533
Barry Warsawfa701a81997-01-16 00:15:11 +00002534 quitMainLoop = 0;
2535 while (Tk_GetNumMainWindows() > threshold &&
2536 !quitMainLoop &&
2537 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002538 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002539 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002540
2541#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002542 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002543 /* Allow other Python threads to run. */
2544 ENTER_TCL
2545 result = Tcl_DoOneEvent(0);
2546 LEAVE_TCL
2547 }
2548 else {
2549 Py_BEGIN_ALLOW_THREADS
2550 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2551 tcl_tstate = tstate;
2552 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2553 tcl_tstate = NULL;
2554 if(tcl_lock)PyThread_release_lock(tcl_lock);
2555 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002556 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002557 Py_END_ALLOW_THREADS
2558 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002559#else
2560 result = Tcl_DoOneEvent(0);
2561#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002562
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002563 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002564 if (self)
2565 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002566 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002567 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002568 if (result < 0)
2569 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002570 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002571 if (self)
2572 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002573 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002574
Barry Warsawfa701a81997-01-16 00:15:11 +00002575 if (errorInCmd) {
2576 errorInCmd = 0;
2577 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2578 excInCmd = valInCmd = trbInCmd = NULL;
2579 return NULL;
2580 }
2581 Py_INCREF(Py_None);
2582 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002583}
2584
2585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002586Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002587{
Guido van Rossum35d43371997-08-02 00:09:09 +00002588 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002589 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002590
Guido van Rossum43713e52000-02-29 13:59:29 +00002591 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002592 return NULL;
2593
Guido van Rossum00d93061998-05-28 23:06:38 +00002594 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002595 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002596 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002597 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002598}
2599
2600static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002601Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002602{
2603
Guido van Rossum43713e52000-02-29 13:59:29 +00002604 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002605 return NULL;
2606
2607 quitMainLoop = 1;
2608 Py_INCREF(Py_None);
2609 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002610}
2611
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002612static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002613Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002614{
2615
Guido van Rossum43713e52000-02-29 13:59:29 +00002616 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002617 return NULL;
2618
2619 return PyInt_FromLong((long)Tkapp_Interp(self));
2620}
2621
David Aschere2b4b322004-02-18 05:59:53 +00002622static PyObject *
2623Tkapp_TkInit(PyObject *self, PyObject *args)
2624{
Martin v. Löwis86725192006-05-01 06:28:01 +00002625 static int has_failed;
David Aschere2b4b322004-02-18 05:59:53 +00002626 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002627 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002628 const char * _tk_exists = NULL;
David Aschere2b4b322004-02-18 05:59:53 +00002629 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002630 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002631
Martin v. Löwis86725192006-05-01 06:28:01 +00002632 /* In all current versions of Tk (including 8.4.13), Tk_Init
2633 deadlocks on the second call when the first call failed.
2634 To avoid the deadlock, we just refuse the second call through
2635 a static variable. */
2636 if (has_failed) {
2637 PyErr_SetString(Tkinter_TclError,
2638 "Calling Tk_Init again after a previous call failed might deadlock");
2639 return NULL;
2640 }
2641
David Aschere2b4b322004-02-18 05:59:53 +00002642 /* We want to guard against calling Tk_Init() multiple times */
2643 CHECK_TCL_APPARTMENT;
2644 ENTER_TCL
2645 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2646 ENTER_OVERLAP
2647 if (err == TCL_ERROR) {
Martin v. Löwis86725192006-05-01 06:28:01 +00002648 /* This sets an exception, but we cannot return right
2649 away because we need to exit the overlap first. */
2650 Tkinter_Error(self);
David Aschere2b4b322004-02-18 05:59:53 +00002651 } else {
2652 _tk_exists = Tkapp_Result(self);
2653 }
2654 LEAVE_OVERLAP_TCL
2655 if (err == TCL_ERROR) {
2656 return NULL;
2657 }
2658 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2659 if (Tk_Init(interp) == TCL_ERROR) {
2660 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Martin v. Löwis86725192006-05-01 06:28:01 +00002661 has_failed = 1;
David Aschere2b4b322004-02-18 05:59:53 +00002662 return NULL;
2663 }
2664 }
2665 Py_INCREF(Py_None);
2666 return Py_None;
2667}
Barry Warsawfa701a81997-01-16 00:15:11 +00002668
Martin v. Löwisffad6332002-11-26 09:28:05 +00002669static PyObject *
2670Tkapp_WantObjects(PyObject *self, PyObject *args)
2671{
2672
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002673 int wantobjects = -1;
2674 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002675 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002676 if (wantobjects == -1)
2677 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002678 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002679
2680 Py_INCREF(Py_None);
2681 return Py_None;
2682}
2683
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002684static PyObject *
2685Tkapp_WillDispatch(PyObject *self, PyObject *args)
2686{
2687
2688 ((TkappObject*)self)->dispatching = 1;
2689
2690 Py_INCREF(Py_None);
2691 return Py_None;
2692}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002693
Barry Warsawfa701a81997-01-16 00:15:11 +00002694
Guido van Rossum18468821994-06-20 07:49:28 +00002695/**** Tkapp Method List ****/
2696
2697static PyMethodDef Tkapp_methods[] =
2698{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002699 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002700 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Neal Norwitze2e447b2007-05-22 07:16:10 +00002701 {"call", Tkapp_Call, METH_VARARGS},
2702 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002703 {"eval", Tkapp_Eval, METH_VARARGS},
2704 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2705 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2706 {"record", Tkapp_Record, METH_VARARGS},
2707 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2708 {"setvar", Tkapp_SetVar, METH_VARARGS},
2709 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2710 {"getvar", Tkapp_GetVar, METH_VARARGS},
2711 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2712 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2713 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2714 {"getint", Tkapp_GetInt, METH_VARARGS},
2715 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2716 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2717 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2718 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2719 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2720 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2721 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2722 {"split", Tkapp_Split, METH_VARARGS},
Neal Norwitze2e447b2007-05-22 07:16:10 +00002723 {"merge", Tkapp_Merge, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002724 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2725 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002726#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002727 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2728 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002729#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002730 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2731 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2732 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2733 {"quit", Tkapp_Quit, METH_VARARGS},
2734 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002735 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002736 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002737};
2738
Barry Warsawfa701a81997-01-16 00:15:11 +00002739
2740
Guido van Rossum18468821994-06-20 07:49:28 +00002741/**** Tkapp Type Methods ****/
2742
2743static void
Fred Drake509d79a2000-07-08 04:04:38 +00002744Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002745{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002746 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002747 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002748 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002749 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002750 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002751 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002752}
2753
2754static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002755Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002756{
Guido van Rossum35d43371997-08-02 00:09:09 +00002757 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002758}
2759
2760static PyTypeObject Tkapp_Type =
2761{
Martin v. Löwis68192102007-07-21 06:55:02 +00002762 PyVarObject_HEAD_INIT(NULL, 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002763 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002764 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002765 0, /*tp_itemsize */
2766 Tkapp_Dealloc, /*tp_dealloc */
2767 0, /*tp_print */
2768 Tkapp_GetAttr, /*tp_getattr */
2769 0, /*tp_setattr */
2770 0, /*tp_compare */
2771 0, /*tp_repr */
2772 0, /*tp_as_number */
2773 0, /*tp_as_sequence */
2774 0, /*tp_as_mapping */
2775 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002776};
2777
Barry Warsawfa701a81997-01-16 00:15:11 +00002778
2779
Guido van Rossum18468821994-06-20 07:49:28 +00002780/**** Tkinter Module ****/
2781
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002782typedef struct {
2783 PyObject* tuple;
2784 int size; /* current size */
2785 int maxsize; /* allocated size */
2786} FlattenContext;
2787
2788static int
2789_bump(FlattenContext* context, int size)
2790{
Guido van Rossum2834b972000-10-06 16:58:26 +00002791 /* expand tuple to hold (at least) size new items.
2792 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002793
2794 int maxsize = context->maxsize * 2;
2795
2796 if (maxsize < context->size + size)
2797 maxsize = context->size + size;
2798
2799 context->maxsize = maxsize;
2800
Tim Peters4324aa32001-05-28 22:30:08 +00002801 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802}
2803
2804static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002805_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806{
2807 /* add tuple or list to argument tuple (recursively) */
2808
2809 int i, size;
2810
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002811 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002812 PyErr_SetString(PyExc_ValueError,
2813 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002814 return 0;
2815 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002816 size = PyList_GET_SIZE(item);
2817 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002818 if (context->size + size > context->maxsize &&
2819 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002820 return 0;
2821 /* copy items to output tuple */
2822 for (i = 0; i < size; i++) {
2823 PyObject *o = PyList_GET_ITEM(item, i);
2824 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002825 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002826 return 0;
2827 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002828 if (context->size + 1 > context->maxsize &&
2829 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002830 return 0;
2831 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002832 PyTuple_SET_ITEM(context->tuple,
2833 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002834 }
2835 }
2836 } else if (PyTuple_Check(item)) {
2837 /* same, for tuples */
2838 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002839 if (context->size + size > context->maxsize &&
2840 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002841 return 0;
2842 for (i = 0; i < size; i++) {
2843 PyObject *o = PyTuple_GET_ITEM(item, i);
2844 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002845 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002846 return 0;
2847 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002848 if (context->size + 1 > context->maxsize &&
2849 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002850 return 0;
2851 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002852 PyTuple_SET_ITEM(context->tuple,
2853 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002854 }
2855 }
2856 } else {
2857 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2858 return 0;
2859 }
2860 return 1;
2861}
2862
2863static PyObject *
2864Tkinter_Flatten(PyObject* self, PyObject* args)
2865{
2866 FlattenContext context;
2867 PyObject* item;
2868
2869 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2870 return NULL;
2871
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002872 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002873 if (context.maxsize <= 0)
2874 return PyTuple_New(0);
2875
2876 context.tuple = PyTuple_New(context.maxsize);
2877 if (!context.tuple)
2878 return NULL;
2879
2880 context.size = 0;
2881
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002882 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002883 return NULL;
2884
Tim Peters4324aa32001-05-28 22:30:08 +00002885 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002886 return NULL;
2887
2888 return context.tuple;
2889}
2890
Guido van Rossum18468821994-06-20 07:49:28 +00002891static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002892Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002893{
Barry Warsawfa701a81997-01-16 00:15:11 +00002894 char *screenName = NULL;
2895 char *baseName = NULL;
2896 char *className = NULL;
2897 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002898 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002899 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002900 int sync = 0; /* pass -sync to wish */
2901 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002902
Guido van Rossum35d43371997-08-02 00:09:09 +00002903 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002904 if (baseName != NULL)
2905 baseName++;
2906 else
2907 baseName = Py_GetProgramName();
2908 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002909
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002910 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002911 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002912 &interactive, &wantobjects, &wantTk,
2913 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002914 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002915
Barry Warsawfa701a81997-01-16 00:15:11 +00002916 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002917 interactive, wantobjects, wantTk,
2918 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002919}
2920
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002921static PyObject *
2922Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2923{
2924 int new_val;
2925 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2926 return NULL;
2927 if (new_val < 0) {
2928 PyErr_SetString(PyExc_ValueError,
2929 "busywaitinterval must be >= 0");
2930 return NULL;
2931 }
2932 Tkinter_busywaitinterval = new_val;
2933 Py_INCREF(Py_None);
2934 return Py_None;
2935}
2936
2937static char setbusywaitinterval_doc[] =
2938"setbusywaitinterval(n) -> None\n\
2939\n\
2940Set the busy-wait interval in milliseconds between successive\n\
2941calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2942It should be set to a divisor of the maximum time between\n\
2943frames in an animation.";
2944
2945static PyObject *
2946Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2947{
2948 return PyInt_FromLong(Tkinter_busywaitinterval);
2949}
2950
2951static char getbusywaitinterval_doc[] =
2952"getbusywaitinterval() -> int\n\
2953\n\
2954Return the current busy-wait interval between successive\n\
2955calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2956
Guido van Rossum18468821994-06-20 07:49:28 +00002957static PyMethodDef moduleMethods[] =
2958{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002959 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2960 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002961#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002962 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2963 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002964#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002965 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2966 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2967 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2968 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002969 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2970 setbusywaitinterval_doc},
2971 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2972 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002973 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002974};
2975
Guido van Rossum7bf15641998-05-22 18:28:17 +00002976#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002977
2978static int stdin_ready = 0;
2979
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002981static void
Fred Drake509d79a2000-07-08 04:04:38 +00002982MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002983{
2984 stdin_ready = 1;
2985}
Guido van Rossumad4db171998-06-13 13:56:28 +00002986#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987
Martin v. Löwisa9656492003-03-30 08:44:58 +00002988#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002989static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002990#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002991
Guido van Rossum18468821994-06-20 07:49:28 +00002992static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002993EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002994{
Guido van Rossumad4db171998-06-13 13:56:28 +00002995#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002996 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002997#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002998#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002999 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003000#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003001 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003002 errorInCmd = 0;
3003#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00003004 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003005 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003006#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003007 while (!errorInCmd && !stdin_ready) {
3008 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003009#ifdef MS_WINDOWS
3010 if (_kbhit()) {
3011 stdin_ready = 1;
3012 break;
3013 }
3014#endif
3015#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00003016 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003017 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00003018 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003019
Guido van Rossum00d93061998-05-28 23:06:38 +00003020 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003021
3022 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003023 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00003024 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003025 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00003026 Py_END_ALLOW_THREADS
3027#else
3028 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003029#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003030
3031 if (result < 0)
3032 break;
3033 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003034#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003035 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003036#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003037 if (errorInCmd) {
3038 errorInCmd = 0;
3039 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3040 excInCmd = valInCmd = trbInCmd = NULL;
3041 PyErr_Print();
3042 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003043#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003044 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003045#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003046 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003047}
Guido van Rossum18468821994-06-20 07:49:28 +00003048
Guido van Rossum00d93061998-05-28 23:06:38 +00003049#endif
3050
Guido van Rossum7bf15641998-05-22 18:28:17 +00003051static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003052EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003053{
Guido van Rossum00d93061998-05-28 23:06:38 +00003054#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003055 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003056#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003057 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003058#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003059 PyOS_InputHook = EventHook;
3060 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003061#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003062}
3063
3064static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003065DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003066{
Guido van Rossum00d93061998-05-28 23:06:38 +00003067#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003068 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3069 PyOS_InputHook = NULL;
3070 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003071#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003072}
3073
Barry Warsawfa701a81997-01-16 00:15:11 +00003074
3075/* all errors will be checked in one fell swoop in init_tkinter() */
3076static void
Fred Drake509d79a2000-07-08 04:04:38 +00003077ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003078{
3079 PyObject *v = PyInt_FromLong(val);
3080 if (v) {
3081 PyDict_SetItemString(d, name, v);
3082 Py_DECREF(v);
3083 }
3084}
3085static void
Fred Drake509d79a2000-07-08 04:04:38 +00003086ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003087{
3088 PyObject *v = PyString_FromString(val);
3089 if (v) {
3090 PyDict_SetItemString(d, name, v);
3091 Py_DECREF(v);
3092 }
3093}
3094
3095
Mark Hammond62b1ab12002-07-23 06:31:15 +00003096PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003097init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003098{
Barry Warsawfa701a81997-01-16 00:15:11 +00003099 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003100
Christian Heimese93237d2007-12-19 02:37:44 +00003101 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003102
3103#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003104 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003105#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003106
Barry Warsawfa701a81997-01-16 00:15:11 +00003107 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003108 if (m == NULL)
3109 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003110
Barry Warsawfa701a81997-01-16 00:15:11 +00003111 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003112 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003113 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003114
Guido van Rossum35d43371997-08-02 00:09:09 +00003115 ins_long(d, "READABLE", TCL_READABLE);
3116 ins_long(d, "WRITABLE", TCL_WRITABLE);
3117 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3118 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3119 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3120 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3121 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3122 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3123 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003124 ins_string(d, "TK_VERSION", TK_VERSION);
3125 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003126
Guido van Rossum83551bf1997-09-13 00:44:23 +00003127 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003128
Christian Heimese93237d2007-12-19 02:37:44 +00003129 Py_TYPE(&Tktt_Type) = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003130 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3131
Christian Heimese93237d2007-12-19 02:37:44 +00003132 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003133 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003134
3135#ifdef TK_AQUA
3136 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3137 * start waking up. Note that Tcl_FindExecutable will do this, this
3138 * code must be above it! The original warning from
3139 * tkMacOSXAppInit.c is copied below.
3140 *
3141 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3142 * Tcl interpreter for now. It probably should work to do this
3143 * in the other order, but for now it doesn't seem to.
3144 *
3145 */
3146 Tk_MacOSXSetupTkNotifier();
3147#endif
3148
3149
Guido van Rossume187b0e2000-03-27 21:46:29 +00003150 /* This helps the dynamic loader; in Unicode aware Tcl versions
3151 it also helps Tcl find its encodings. */
3152 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003153
Barry Warsawfa701a81997-01-16 00:15:11 +00003154 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003155 return;
3156
Guido van Rossum43ff8681998-07-14 18:02:13 +00003157#if 0
3158 /* This was not a good idea; through <Destroy> bindings,
3159 Tcl_Finalize() may invoke Python code but at that point the
3160 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003161 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003162#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003163
Guido van Rossum18468821994-06-20 07:49:28 +00003164}