blob: e8efaa7a19bd51e20d7e463380bf34ecdb44c718 [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
265#define Tkapp_Check(v) ((v)->ob_type == &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", \
Barry Warsawfa701a81997-01-16 00:15:11 +0000270(void *) v, ((PyObject *) v)->ob_refcnt))
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])))
Barry Warsawfa701a81997-01-16 00:15:11 +0000650 argv0[0] = tolower(argv0[0]);
651 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
Neal Norwitz227b5332006-03-22 09:28:35 +0000723static PyTypeObject PyTclObject_Type;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000724#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
Neal Norwitz227b5332006-03-22 09:28:35 +0000861static PyTypeObject PyTclObject_Type = {
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862 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);
935 int size = PyUnicode_GET_SIZE(value);
936 /* 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;
940 int i;
941 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
942 if (!outbuf) {
943 PyErr_NoMemory();
944 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000945 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000946 for (i = 0; i < size; i++) {
947 if (inbuf[i] >= 0x10000) {
948 /* Tcl doesn't do UTF-16, yet. */
949 PyErr_SetString(PyExc_ValueError,
950 "unsupported character");
951 ckfree(FREECAST outbuf);
952 return NULL;
953 }
954 outbuf[i] = inbuf[i];
955 }
956 result = Tcl_NewUnicodeObj(outbuf, size);
957 ckfree(FREECAST outbuf);
958 return result;
959#else
960 return Tcl_NewUnicodeObj(inbuf, size);
961#endif
962
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000963 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000964#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965 else if(PyTclObject_Check(value)) {
966 Tcl_Obj *v = ((PyTclObject*)value)->value;
967 Tcl_IncrRefCount(v);
968 return v;
969 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000970 else {
971 PyObject *v = PyObject_Str(value);
972 if (!v)
973 return 0;
974 result = AsObj(v);
975 Py_DECREF(v);
976 return result;
977 }
978}
979
Martin v. Löwisffad6332002-11-26 09:28:05 +0000980static PyObject*
981FromObj(PyObject* tkapp, Tcl_Obj *value)
982{
983 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000984 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000985
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000986 if (value->typePtr == NULL) {
987 /* If the result contains any bytes with the top bit set,
988 it's UTF-8 and we should decode it to Unicode */
989#ifdef Py_USING_UNICODE
990 int i;
991 char *s = value->bytes;
992 int len = value->length;
993 for (i = 0; i < len; i++) {
994 if (value->bytes[i] & 0x80)
995 break;
996 }
997
998 if (i == value->length)
999 result = PyString_FromStringAndSize(s, len);
1000 else {
1001 /* Convert UTF-8 to Unicode string */
1002 result = PyUnicode_DecodeUTF8(s, len, "strict");
1003 if (result == NULL) {
1004 PyErr_Clear();
1005 result = PyString_FromStringAndSize(s, len);
1006 }
1007 }
1008#else
Martin v. Löwise2713be2005-03-08 15:03:08 +00001009 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001010#endif
1011 return result;
1012 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001013
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001014 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001015 result = value->internalRep.longValue ? Py_True : Py_False;
1016 Py_INCREF(result);
1017 return result;
1018 }
1019
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001020 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001021 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001022 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001023 return PyString_FromStringAndSize(data, size);
1024 }
1025
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001026 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001027 return PyFloat_FromDouble(value->internalRep.doubleValue);
1028 }
1029
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001030 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001031 return PyInt_FromLong(value->internalRep.longValue);
1032 }
1033
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001034 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035 int size;
1036 int i, status;
1037 PyObject *elem;
1038 Tcl_Obj *tcl_elem;
1039
1040 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1041 if (status == TCL_ERROR)
1042 return Tkinter_Error(tkapp);
1043 result = PyTuple_New(size);
1044 if (!result)
1045 return NULL;
1046 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001047 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001048 value, i, &tcl_elem);
1049 if (status == TCL_ERROR) {
1050 Py_DECREF(result);
1051 return Tkinter_Error(tkapp);
1052 }
1053 elem = FromObj(tkapp, tcl_elem);
1054 if (!elem) {
1055 Py_DECREF(result);
1056 return NULL;
1057 }
1058 PyTuple_SetItem(result, i, elem);
1059 }
1060 return result;
1061 }
1062
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001063 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001064 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001065 }
1066
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001067 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001068#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001069#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001070 PyObject *result;
1071 int size;
1072 Tcl_UniChar *input;
1073 Py_UNICODE *output;
1074
1075 size = Tcl_GetCharLength(value);
1076 result = PyUnicode_FromUnicode(NULL, size);
1077 if (!result)
1078 return NULL;
1079 input = Tcl_GetUnicode(value);
1080 output = PyUnicode_AS_UNICODE(result);
1081 while (size--)
1082 *output++ = *input++;
1083 return result;
1084#else
1085 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1086 Tcl_GetCharLength(value));
1087#endif
1088#else
1089 int size;
1090 char *c;
1091 c = Tcl_GetStringFromObj(value, &size);
1092 return PyString_FromStringAndSize(c, size);
1093#endif
1094 }
1095
1096 return newPyTclObject(value);
1097}
1098
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001099/* This mutex synchronizes inter-thread command calls. */
1100
1101TCL_DECLARE_MUTEX(call_mutex)
1102
1103typedef struct Tkapp_CallEvent {
1104 Tcl_Event ev; /* Must be first */
1105 TkappObject *self;
1106 PyObject *args;
1107 int flags;
1108 PyObject **res;
1109 PyObject **exc_type, **exc_value, **exc_tb;
1110 Tcl_Condition done;
1111} Tkapp_CallEvent;
1112
1113void
1114Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001115{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001116 int i;
1117 for (i = 0; i < objc; i++)
1118 Tcl_DecrRefCount(objv[i]);
1119 if (objv != objStore)
1120 ckfree(FREECAST objv);
1121}
Guido van Rossum18468821994-06-20 07:49:28 +00001122
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001123/* Convert Python objects to Tcl objects. This must happen in the
1124 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126static Tcl_Obj**
1127Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1128{
1129 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001130 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001131 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001132 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001133
Guido van Rossum212643f1998-04-29 16:22:14 +00001134 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001135 objv[0] = AsObj(args);
1136 if (objv[0] == 0)
1137 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001138 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001139 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001140 }
1141 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001142 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001143
Guido van Rossum632de272000-03-29 00:19:50 +00001144 if (objc > ARGSZ) {
1145 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1146 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001147 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001148 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001149 goto finally;
1150 }
1151 }
1152
Guido van Rossum632de272000-03-29 00:19:50 +00001153 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001154 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001155 if (v == Py_None) {
1156 objc = i;
1157 break;
1158 }
Guido van Rossum632de272000-03-29 00:19:50 +00001159 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001160 if (!objv[i]) {
1161 /* Reset objc, so it attempts to clear
1162 objects only up to i. */
1163 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001164 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001165 }
Guido van Rossum632de272000-03-29 00:19:50 +00001166 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001167 }
1168 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001169 *pobjc = objc;
1170 return objv;
1171finally:
1172 Tkapp_CallDeallocArgs(objv, objStore, objc);
1173 return NULL;
1174}
Guido van Rossum212643f1998-04-29 16:22:14 +00001175
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001176/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001178static PyObject*
1179Tkapp_CallResult(TkappObject *self)
1180{
1181 PyObject *res = NULL;
1182 if(self->wantobjects) {
1183 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001184 /* Not sure whether the IncrRef is necessary, but something
1185 may overwrite the interpreter result while we are
1186 converting it. */
1187 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001188 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001189 Tcl_DecrRefCount(value);
1190 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001191 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001192 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001193
Guido van Rossum990f5c62000-05-04 15:07:16 +00001194 /* If the result contains any bytes with the top bit set,
1195 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001196#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001197 while (*p != '\0') {
1198 if (*p & 0x80)
1199 break;
1200 p++;
1201 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001202
Guido van Rossum990f5c62000-05-04 15:07:16 +00001203 if (*p == '\0')
1204 res = PyString_FromStringAndSize(s, (int)(p-s));
1205 else {
1206 /* Convert UTF-8 to Unicode string */
1207 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001208 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1209 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001210 PyErr_Clear();
1211 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001212 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001213 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001214#else
1215 p = strchr(p, '\0');
1216 res = PyString_FromStringAndSize(s, (int)(p-s));
1217#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001218 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219 return res;
1220}
Guido van Rossum632de272000-03-29 00:19:50 +00001221
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001222/* Tkapp_CallProc is the event procedure that is executed in the context of
1223 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1224 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001225
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226static int
1227Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1228{
1229 Tcl_Obj *objStore[ARGSZ];
1230 Tcl_Obj **objv;
1231 int objc;
1232 int i;
1233 ENTER_PYTHON
1234 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1235 if (!objv) {
1236 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1237 *(e->res) = NULL;
1238 }
1239 LEAVE_PYTHON
1240 if (!objv)
1241 goto done;
1242 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1243 ENTER_PYTHON
1244 if (i == TCL_ERROR) {
1245 *(e->res) = NULL;
1246 *(e->exc_type) = NULL;
1247 *(e->exc_tb) = NULL;
1248 *(e->exc_value) = PyObject_CallFunction(
1249 Tkinter_TclError, "s",
1250 Tcl_GetStringResult(e->self->interp));
1251 }
1252 else {
1253 *(e->res) = Tkapp_CallResult(e->self);
1254 }
1255 LEAVE_PYTHON
1256 done:
1257 /* Wake up calling thread. */
1258 Tcl_MutexLock(&call_mutex);
1259 Tcl_ConditionNotify(&e->done);
1260 Tcl_MutexUnlock(&call_mutex);
1261 return 1;
1262}
1263
1264/* This is the main entry point for calling a Tcl command.
1265 It supports three cases, with regard to threading:
1266 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1267 the context of the calling thread.
1268 2. Tcl is threaded, caller of the command is in the interpreter thread:
1269 Execute the command in the calling thread. Since the Tcl lock will
1270 not be used, we can merge that with case 1.
1271 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1272 the interpreter thread. Allocation of Tcl objects needs to occur in the
1273 interpreter thread, so we ship the PyObject* args to the target thread,
1274 and perform processing there. */
1275
1276static PyObject *
1277Tkapp_Call(PyObject *_self, PyObject *args)
1278{
1279 Tcl_Obj *objStore[ARGSZ];
1280 Tcl_Obj **objv = NULL;
1281 int objc, i;
1282 PyObject *res = NULL;
1283 TkappObject *self = (TkappObject*)_self;
1284 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1285 int flags = TCL_EVAL_DIRECT;
1286
Martin v. Löwisa9656492003-03-30 08:44:58 +00001287#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001288 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1289 /* We cannot call the command directly. Instead, we must
1290 marshal the parameters to the interpreter thread. */
1291 Tkapp_CallEvent *ev;
1292 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001293 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1296 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1297 ev->self = self;
1298 ev->args = args;
1299 ev->res = &res;
1300 ev->exc_type = &exc_type;
1301 ev->exc_value = &exc_value;
1302 ev->exc_tb = &exc_tb;
1303 ev->done = (Tcl_Condition)0;
1304
1305 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1306
1307 if (res == NULL) {
1308 if (exc_type)
1309 PyErr_Restore(exc_type, exc_value, exc_tb);
1310 else
1311 PyErr_SetObject(Tkinter_TclError, exc_value);
1312 }
1313 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001314 else
1315#endif
1316 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001317
1318 objv = Tkapp_CallArgs(args, objStore, &objc);
1319 if (!objv)
1320 return NULL;
1321
1322 ENTER_TCL
1323
1324 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1325
1326 ENTER_OVERLAP
1327
1328 if (i == TCL_ERROR)
1329 Tkinter_Error(_self);
1330 else
1331 res = Tkapp_CallResult(self);
1332
1333 LEAVE_OVERLAP_TCL
1334
1335 Tkapp_CallDeallocArgs(objv, objStore, objc);
1336 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001337 return res;
1338}
1339
1340
1341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001342Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001343{
Guido van Rossum212643f1998-04-29 16:22:14 +00001344 /* Could do the same here as for Tkapp_Call(), but this is not used
1345 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1346 way for the user to do what all its Global* variants do (save and
1347 reset the scope pointer, call the local version, restore the saved
1348 scope pointer). */
1349
Guido van Rossum62320c91998-06-15 04:36:09 +00001350 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001351 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001352
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001353 CHECK_TCL_APPARTMENT;
1354
Guido van Rossum62320c91998-06-15 04:36:09 +00001355 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001356 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001357 int err;
1358 ENTER_TCL
1359 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001360 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001361 if (err == TCL_ERROR)
1362 res = Tkinter_Error(self);
1363 else
1364 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001365 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001366 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001367 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001368
1369 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001370}
1371
1372static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001373Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001374{
Barry Warsawfa701a81997-01-16 00:15:11 +00001375 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001376 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001377 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378
Guido van Rossum43713e52000-02-29 13:59:29 +00001379 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001380 return NULL;
1381
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382 CHECK_TCL_APPARTMENT;
1383
Guido van Rossum00d93061998-05-28 23:06:38 +00001384 ENTER_TCL
1385 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001386 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001387 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001388 res = Tkinter_Error(self);
1389 else
1390 res = PyString_FromString(Tkapp_Result(self));
1391 LEAVE_OVERLAP_TCL
1392 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001393}
1394
1395static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001396Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001397{
Barry Warsawfa701a81997-01-16 00:15:11 +00001398 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001399 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001400 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001401
Guido van Rossum43713e52000-02-29 13:59:29 +00001402 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001403 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001404
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405 CHECK_TCL_APPARTMENT;
1406
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 ENTER_TCL
1408 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001409 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001410 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001411 res = Tkinter_Error(self);
1412 else
1413 res = PyString_FromString(Tkapp_Result(self));
1414 LEAVE_OVERLAP_TCL
1415 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001416}
1417
1418static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001419Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001420{
Barry Warsawfa701a81997-01-16 00:15:11 +00001421 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001422 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001423 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001424
Guido van Rossum43713e52000-02-29 13:59:29 +00001425 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001426 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001427
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428 CHECK_TCL_APPARTMENT;
1429
Guido van Rossum00d93061998-05-28 23:06:38 +00001430 ENTER_TCL
1431 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001432 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001433 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001434 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001435
Guido van Rossum62320c91998-06-15 04:36:09 +00001436 else
1437 res = PyString_FromString(Tkapp_Result(self));
1438 LEAVE_OVERLAP_TCL
1439 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001440}
1441
1442static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001443Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001444{
Barry Warsawfa701a81997-01-16 00:15:11 +00001445 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001446 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001447 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001448
Guido van Rossum35d43371997-08-02 00:09:09 +00001449 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001450 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452 CHECK_TCL_APPARTMENT;
1453
Guido van Rossum00d93061998-05-28 23:06:38 +00001454 ENTER_TCL
1455 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001456 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001457 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001458 res = Tkinter_Error(self);
1459 else
1460 res = PyString_FromString(Tkapp_Result(self));
1461 LEAVE_OVERLAP_TCL
1462 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001463}
1464
1465static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001466Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001467{
Barry Warsawfa701a81997-01-16 00:15:11 +00001468 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001469
Guido van Rossum43713e52000-02-29 13:59:29 +00001470 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001471 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001472 CHECK_TCL_APPARTMENT;
1473
Guido van Rossum00d93061998-05-28 23:06:38 +00001474 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001476 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001477
Barry Warsawfa701a81997-01-16 00:15:11 +00001478 Py_INCREF(Py_None);
1479 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001480}
1481
Barry Warsawfa701a81997-01-16 00:15:11 +00001482
1483
Guido van Rossum18468821994-06-20 07:49:28 +00001484/** Tcl Variable **/
1485
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486TCL_DECLARE_MUTEX(var_mutex)
1487
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001488typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489typedef struct VarEvent {
1490 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491 PyObject *self;
1492 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001493 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001494 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001496 PyObject **exc_type;
1497 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001498 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499} VarEvent;
1500
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001501static int
1502varname_converter(PyObject *in, void *_out)
1503{
1504 char **out = (char**)_out;
1505 if (PyString_Check(in)) {
1506 *out = PyString_AsString(in);
1507 return 1;
1508 }
1509 if (PyTclObject_Check(in)) {
1510 *out = PyTclObject_TclString(in);
1511 return 1;
1512 }
1513 /* XXX: Should give diagnostics. */
1514 return 0;
1515}
1516
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001517void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001518var_perform(VarEvent *ev)
1519{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001520 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1521 if (!*(ev->res)) {
1522 PyObject *exc, *val, *tb;
1523 PyErr_Fetch(&exc, &val, &tb);
1524 PyErr_NormalizeException(&exc, &val, &tb);
1525 *(ev->exc_type) = exc;
1526 *(ev->exc_val) = val;
1527 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001529
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530}
1531
1532static int
1533var_proc(VarEvent* ev, int flags)
1534{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001536 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537 Tcl_MutexLock(&var_mutex);
1538 Tcl_ConditionNotify(&ev->cond);
1539 Tcl_MutexUnlock(&var_mutex);
1540 LEAVE_PYTHON
1541 return 1;
1542}
1543
1544static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001545var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001548#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001550 TkappObject *self = (TkappObject*)_self;
1551 VarEvent *ev;
1552 PyObject *res, *exc_type, *exc_val;
1553
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554 /* The current thread is not the interpreter thread. Marshal
1555 the call to the interpreter thread, then wait for
1556 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001557 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001559
1560 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1561
1562 ev->self = _self;
1563 ev->args = args;
1564 ev->flags = flags;
1565 ev->func = func;
1566 ev->res = &res;
1567 ev->exc_type = &exc_type;
1568 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001569 ev->cond = NULL;
1570 ev->ev.proc = (Tcl_EventProc*)var_proc;
1571 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001572 if (!res) {
1573 PyErr_SetObject(exc_type, exc_val);
1574 Py_DECREF(exc_type);
1575 Py_DECREF(exc_val);
1576 return NULL;
1577 }
1578 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001579 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001580#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001581 /* Tcl is not threaded, or this is the interpreter thread. */
1582 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001583}
1584
Guido van Rossum18468821994-06-20 07:49:28 +00001585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001586SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001587{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001588 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001589 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001590 PyObject *res = NULL;
1591 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001592
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001593 if (PyArg_ParseTuple(args, "O&O:setvar",
1594 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001595 /* XXX Acquire tcl lock??? */
1596 newval = AsObj(newValue);
1597 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001598 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001599 ENTER_TCL
1600 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1601 newval, flags);
1602 ENTER_OVERLAP
1603 if (!ok)
1604 Tkinter_Error(self);
1605 else {
1606 res = Py_None;
1607 Py_INCREF(res);
1608 }
1609 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001610 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001611 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001612 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001613 if (PyArg_ParseTuple(args, "ssO:setvar",
1614 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001615 /* XXX must hold tcl lock already??? */
1616 newval = AsObj(newValue);
1617 ENTER_TCL
1618 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1619 ENTER_OVERLAP
1620 if (!ok)
1621 Tkinter_Error(self);
1622 else {
1623 res = Py_None;
1624 Py_INCREF(res);
1625 }
1626 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001627 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001628 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001629 return NULL;
1630 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001631 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001632 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001633}
1634
1635static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001636Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001637{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001638 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001639}
1640
1641static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001642Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001643{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001644 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001645}
1646
Barry Warsawfa701a81997-01-16 00:15:11 +00001647
1648
Guido van Rossum18468821994-06-20 07:49:28 +00001649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001652 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001653 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001654 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001655
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001656 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1657 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001658 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001659
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001660 ENTER_TCL
1661 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1662 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001663 if (tres == NULL) {
1664 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1665 } else {
1666 if (((TkappObject*)self)->wantobjects) {
1667 res = FromObj(self, tres);
1668 }
1669 else {
1670 res = PyString_FromString(Tcl_GetString(tres));
1671 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001672 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001673 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001674 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001675}
1676
1677static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001678Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001679{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001681}
1682
1683static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001684Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001685{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001686 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001687}
1688
Barry Warsawfa701a81997-01-16 00:15:11 +00001689
1690
Guido van Rossum18468821994-06-20 07:49:28 +00001691static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001692UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001693{
Guido van Rossum35d43371997-08-02 00:09:09 +00001694 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001695 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001696 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001697
Guido van Rossum43713e52000-02-29 13:59:29 +00001698 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001699 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001700
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001701 ENTER_TCL
1702 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1703 ENTER_OVERLAP
1704 if (code == TCL_ERROR)
1705 res = Tkinter_Error(self);
1706 else {
1707 Py_INCREF(Py_None);
1708 res = Py_None;
1709 }
1710 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001711 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001712}
1713
1714static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001715Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001716{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001717 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001718}
1719
1720static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001721Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001722{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001723 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001724}
1725
Barry Warsawfa701a81997-01-16 00:15:11 +00001726
1727
Guido van Rossum18468821994-06-20 07:49:28 +00001728/** Tcl to Python **/
1729
1730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001731Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001732{
Barry Warsawfa701a81997-01-16 00:15:11 +00001733 char *s;
1734 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001735
Martin v. Löwisffad6332002-11-26 09:28:05 +00001736 if (PyTuple_Size(args) == 1) {
1737 PyObject* o = PyTuple_GetItem(args, 0);
1738 if (PyInt_Check(o)) {
1739 Py_INCREF(o);
1740 return o;
1741 }
1742 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001743 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001744 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001745 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001746 return Tkinter_Error(self);
1747 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001748}
1749
1750static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001751Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001752{
Barry Warsawfa701a81997-01-16 00:15:11 +00001753 char *s;
1754 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001755
Martin v. Löwisffad6332002-11-26 09:28:05 +00001756 if (PyTuple_Size(args) == 1) {
1757 PyObject *o = PyTuple_GetItem(args, 0);
1758 if (PyFloat_Check(o)) {
1759 Py_INCREF(o);
1760 return o;
1761 }
1762 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001763 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001764 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001765 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001766 return Tkinter_Error(self);
1767 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Barry Warsawfa701a81997-01-16 00:15:11 +00001773 char *s;
1774 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Martin v. Löwisffad6332002-11-26 09:28:05 +00001776 if (PyTuple_Size(args) == 1) {
1777 PyObject *o = PyTuple_GetItem(args, 0);
1778 if (PyInt_Check(o)) {
1779 Py_INCREF(o);
1780 return o;
1781 }
1782 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001783 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001784 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001785 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001787 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
1790static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001791Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001792{
Barry Warsawfa701a81997-01-16 00:15:11 +00001793 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001794 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001795 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001796
Guido van Rossum43713e52000-02-29 13:59:29 +00001797 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001798 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001799
1800 CHECK_TCL_APPARTMENT;
1801
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 ENTER_TCL
1803 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001804 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001805 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001806 res = Tkinter_Error(self);
1807 else
1808 res = Py_BuildValue("s", Tkapp_Result(self));
1809 LEAVE_OVERLAP_TCL
1810 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
1813static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001814Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Barry Warsawfa701a81997-01-16 00:15:11 +00001816 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001817 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001818 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001819 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001820
Guido van Rossum43713e52000-02-29 13:59:29 +00001821 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001822 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001823
1824 CHECK_TCL_APPARTMENT;
1825
Guido van Rossum00d93061998-05-28 23:06:38 +00001826 ENTER_TCL
1827 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001828 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001829 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001830 res = Tkinter_Error(self);
1831 else
1832 res = Py_BuildValue("l", v);
1833 LEAVE_OVERLAP_TCL
1834 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001835}
1836
1837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001838Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001839{
Barry Warsawfa701a81997-01-16 00:15:11 +00001840 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001841 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001842 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001843 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001844
Guido van Rossum43713e52000-02-29 13:59:29 +00001845 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001846 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001847 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001848 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001849 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001850 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001851 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001852 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001853 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001854 res = Tkinter_Error(self);
1855 else
1856 res = Py_BuildValue("d", v);
1857 LEAVE_OVERLAP_TCL
1858 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001859}
1860
1861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001862Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001863{
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001865 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001866 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Guido van Rossum43713e52000-02-29 13:59:29 +00001869 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001870 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001871 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001872 ENTER_TCL
1873 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001874 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001875 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001876 res = Tkinter_Error(self);
1877 else
1878 res = Py_BuildValue("i", v);
1879 LEAVE_OVERLAP_TCL
1880 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
Barry Warsawfa701a81997-01-16 00:15:11 +00001883
1884
Guido van Rossum18468821994-06-20 07:49:28 +00001885static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001886Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001887{
Barry Warsawfa701a81997-01-16 00:15:11 +00001888 char *list;
1889 int argc;
1890 char **argv;
1891 PyObject *v;
1892 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001893
Martin v. Löwisffad6332002-11-26 09:28:05 +00001894 if (PyTuple_Size(args) == 1) {
1895 v = PyTuple_GetItem(args, 0);
1896 if (PyTuple_Check(v)) {
1897 Py_INCREF(v);
1898 return v;
1899 }
1900 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001901 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001902 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001903
Neal Norwitzd1c55102003-05-29 00:17:03 +00001904 if (Tcl_SplitList(Tkapp_Interp(self), list,
1905 &argc, &argv) == TCL_ERROR) {
1906 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001908 }
Guido van Rossum18468821994-06-20 07:49:28 +00001909
Barry Warsawfa701a81997-01-16 00:15:11 +00001910 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001911 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001912
Barry Warsawfa701a81997-01-16 00:15:11 +00001913 for (i = 0; i < argc; i++) {
1914 PyObject *s = PyString_FromString(argv[i]);
1915 if (!s || PyTuple_SetItem(v, i, s)) {
1916 Py_DECREF(v);
1917 v = NULL;
1918 goto finally;
1919 }
1920 }
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Barry Warsawfa701a81997-01-16 00:15:11 +00001922 finally:
1923 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001924 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001925 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001926}
1927
1928static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001929Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001930{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001931 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001932 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001933
Martin v. Löwisffad6332002-11-26 09:28:05 +00001934 if (PyTuple_Size(args) == 1) {
1935 PyObject* o = PyTuple_GetItem(args, 0);
1936 if (PyTuple_Check(o)) {
1937 o = SplitObj(o);
1938 return o;
1939 }
1940 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001941 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001942 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001943 v = Split(list);
1944 PyMem_Free(list);
1945 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 char *s = Merge(args);
1952 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001953
Barry Warsawfa701a81997-01-16 00:15:11 +00001954 if (s) {
1955 res = PyString_FromString(s);
1956 ckfree(s);
1957 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001958
1959 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001960}
1961
Barry Warsawfa701a81997-01-16 00:15:11 +00001962
1963
Guido van Rossum18468821994-06-20 07:49:28 +00001964/** Tcl Command **/
1965
Guido van Rossum00d93061998-05-28 23:06:38 +00001966/* Client data struct */
1967typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001968 PyObject *self;
1969 PyObject *func;
1970} PythonCmd_ClientData;
1971
1972static int
Fred Drake509d79a2000-07-08 04:04:38 +00001973PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001974{
1975 errorInCmd = 1;
1976 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1977 LEAVE_PYTHON
1978 return TCL_ERROR;
1979}
1980
Guido van Rossum18468821994-06-20 07:49:28 +00001981/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001982 * function or method.
1983 */
Guido van Rossum18468821994-06-20 07:49:28 +00001984static int
Fred Drake509d79a2000-07-08 04:04:38 +00001985PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001986{
Guido van Rossum00d93061998-05-28 23:06:38 +00001987 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001988 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001989 int i, rv;
1990 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001991
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001992 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001993
Barry Warsawfa701a81997-01-16 00:15:11 +00001994 /* TBD: no error checking here since we know, via the
1995 * Tkapp_CreateCommand() that the client data is a two-tuple
1996 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001997 self = data->self;
1998 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001999
Barry Warsawfa701a81997-01-16 00:15:11 +00002000 /* Create argument list (argv1, ..., argvN) */
2001 if (!(arg = PyTuple_New(argc - 1)))
2002 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002003
Barry Warsawfa701a81997-01-16 00:15:11 +00002004 for (i = 0; i < (argc - 1); i++) {
2005 PyObject *s = PyString_FromString(argv[i + 1]);
2006 if (!s || PyTuple_SetItem(arg, i, s)) {
2007 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00002008 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00002009 }
2010 }
2011 res = PyEval_CallObject(func, arg);
2012 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002013
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 if (res == NULL)
2015 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Barry Warsawfa701a81997-01-16 00:15:11 +00002017 if (!(tmp = PyList_New(0))) {
2018 Py_DECREF(res);
2019 return PythonCmd_Error(interp);
2020 }
2021
Guido van Rossum2834b972000-10-06 16:58:26 +00002022 s = AsString(res, tmp);
2023 if (s == NULL) {
2024 rv = PythonCmd_Error(interp);
2025 }
2026 else {
2027 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2028 rv = TCL_OK;
2029 }
2030
Barry Warsawfa701a81997-01-16 00:15:11 +00002031 Py_DECREF(res);
2032 Py_DECREF(tmp);
2033
Guido van Rossum00d93061998-05-28 23:06:38 +00002034 LEAVE_PYTHON
2035
Guido van Rossum2834b972000-10-06 16:58:26 +00002036 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002037}
2038
2039static void
Fred Drake509d79a2000-07-08 04:04:38 +00002040PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002041{
Guido van Rossum00d93061998-05-28 23:06:38 +00002042 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2043
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002044 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002045 Py_XDECREF(data->self);
2046 Py_XDECREF(data->func);
2047 PyMem_DEL(data);
2048 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002049}
2050
Barry Warsawfa701a81997-01-16 00:15:11 +00002051
2052
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002053
2054TCL_DECLARE_MUTEX(command_mutex)
2055
2056typedef struct CommandEvent{
2057 Tcl_Event ev;
2058 Tcl_Interp* interp;
2059 char *name;
2060 int create;
2061 int *status;
2062 ClientData *data;
2063 Tcl_Condition done;
2064} CommandEvent;
2065
2066static int
2067Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002068{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002069 if (ev->create)
2070 *ev->status = Tcl_CreateCommand(
2071 ev->interp, ev->name, PythonCmd,
2072 ev->data, PythonCmdDelete) == NULL;
2073 else
2074 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2075 Tcl_MutexLock(&command_mutex);
2076 Tcl_ConditionNotify(&ev->done);
2077 Tcl_MutexUnlock(&command_mutex);
2078 return 1;
2079}
2080
2081static PyObject *
2082Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2083{
2084 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002085 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002086 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002087 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002089
Guido van Rossum43713e52000-02-29 13:59:29 +00002090 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002091 return NULL;
2092 if (!PyCallable_Check(func)) {
2093 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002094 return NULL;
2095 }
Guido van Rossum18468821994-06-20 07:49:28 +00002096
Martin v. Löwisa9656492003-03-30 08:44:58 +00002097#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002098 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002099 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002100 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002101#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002102
Guido van Rossum00d93061998-05-28 23:06:38 +00002103 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002104 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002105 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002106 Py_XINCREF(self);
2107 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002108 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002109 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002110
2111 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2112 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2113 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2114 ev->interp = self->interp;
2115 ev->create = 1;
2116 ev->name = cmdName;
2117 ev->data = (ClientData)data;
2118 ev->status = &err;
2119 ev->done = NULL;
2120 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2121 }
2122 else {
2123 ENTER_TCL
2124 err = Tcl_CreateCommand(
2125 Tkapp_Interp(self), cmdName, PythonCmd,
2126 (ClientData)data, PythonCmdDelete) == NULL;
2127 LEAVE_TCL
2128 }
2129 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002130 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002131 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002132 return NULL;
2133 }
Guido van Rossum18468821994-06-20 07:49:28 +00002134
Barry Warsawfa701a81997-01-16 00:15:11 +00002135 Py_INCREF(Py_None);
2136 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002137}
2138
Barry Warsawfa701a81997-01-16 00:15:11 +00002139
2140
Guido van Rossum18468821994-06-20 07:49:28 +00002141static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002142Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002143{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002144 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002145 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002146 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002147
Guido van Rossum43713e52000-02-29 13:59:29 +00002148 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002149 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002150 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2151 CommandEvent *ev;
2152 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2153 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2154 ev->interp = self->interp;
2155 ev->create = 0;
2156 ev->name = cmdName;
2157 ev->status = &err;
2158 ev->done = NULL;
2159 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2160 &command_mutex);
2161 }
2162 else {
2163 ENTER_TCL
2164 err = Tcl_DeleteCommand(self->interp, cmdName);
2165 LEAVE_TCL
2166 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002167 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002168 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2169 return NULL;
2170 }
2171 Py_INCREF(Py_None);
2172 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002173}
2174
Barry Warsawfa701a81997-01-16 00:15:11 +00002175
2176
Guido van Rossum00d93061998-05-28 23:06:38 +00002177#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002178/** File Handler **/
2179
Guido van Rossum00d93061998-05-28 23:06:38 +00002180typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002181 PyObject *func;
2182 PyObject *file;
2183 int id;
2184 struct _fhcdata *next;
2185} FileHandler_ClientData;
2186
2187static FileHandler_ClientData *HeadFHCD;
2188
2189static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002190NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002191{
2192 FileHandler_ClientData *p;
2193 p = PyMem_NEW(FileHandler_ClientData, 1);
2194 if (p != NULL) {
2195 Py_XINCREF(func);
2196 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002197 p->func = func;
2198 p->file = file;
2199 p->id = id;
2200 p->next = HeadFHCD;
2201 HeadFHCD = p;
2202 }
2203 return p;
2204}
2205
2206static void
Fred Drake509d79a2000-07-08 04:04:38 +00002207DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002208{
2209 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002210
2211 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002212 while ((p = *pp) != NULL) {
2213 if (p->id == id) {
2214 *pp = p->next;
2215 Py_XDECREF(p->func);
2216 Py_XDECREF(p->file);
2217 PyMem_DEL(p);
2218 }
2219 else
2220 pp = &p->next;
2221 }
2222}
2223
Guido van Rossuma597dde1995-01-10 20:56:29 +00002224static void
Fred Drake509d79a2000-07-08 04:04:38 +00002225FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002226{
Guido van Rossum00d93061998-05-28 23:06:38 +00002227 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002228 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002230 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002231 func = data->func;
2232 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002233
Barry Warsawfa701a81997-01-16 00:15:11 +00002234 arg = Py_BuildValue("(Oi)", file, (long) mask);
2235 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002236 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002237
2238 if (res == NULL) {
2239 errorInCmd = 1;
2240 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2241 }
2242 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002243 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002244}
2245
Guido van Rossum18468821994-06-20 07:49:28 +00002246static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002247Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2248 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002249{
Guido van Rossum00d93061998-05-28 23:06:38 +00002250 FileHandler_ClientData *data;
2251 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002252 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002253
Guido van Rossum2834b972000-10-06 16:58:26 +00002254 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2255 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002256 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002257
Martin v. Löwisa9656492003-03-30 08:44:58 +00002258#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002259 if (!self && !tcl_lock) {
2260 /* We don't have the Tcl lock since Tcl is threaded. */
2261 PyErr_SetString(PyExc_RuntimeError,
2262 "_tkinter.createfilehandler not supported "
2263 "for threaded Tcl");
2264 return NULL;
2265 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002266#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002267
2268 if (self) {
2269 CHECK_TCL_APPARTMENT;
2270 }
2271
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002272 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002273 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 return NULL;
2275 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002276 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002277 return NULL;
2278 }
2279
Guido van Rossuma80649b2000-03-28 20:07:05 +00002280 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002281 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002282 return NULL;
2283
Barry Warsawfa701a81997-01-16 00:15:11 +00002284 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002285 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002287 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002288 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002289 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002290}
2291
2292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002293Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002294{
Barry Warsawfa701a81997-01-16 00:15:11 +00002295 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002296 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002297
Guido van Rossum43713e52000-02-29 13:59:29 +00002298 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002299 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002300
Martin v. Löwisa9656492003-03-30 08:44:58 +00002301#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002302 if (!self && !tcl_lock) {
2303 /* We don't have the Tcl lock since Tcl is threaded. */
2304 PyErr_SetString(PyExc_RuntimeError,
2305 "_tkinter.deletefilehandler not supported "
2306 "for threaded Tcl");
2307 return NULL;
2308 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002309#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002310
2311 if (self) {
2312 CHECK_TCL_APPARTMENT;
2313 }
2314
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002315 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002316 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002317 return NULL;
2318
Guido van Rossuma80649b2000-03-28 20:07:05 +00002319 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002320
Barry Warsawfa701a81997-01-16 00:15:11 +00002321 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002322 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002324 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002325 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002326 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002327}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002328#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Barry Warsawfa701a81997-01-16 00:15:11 +00002330
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331/**** Tktt Object (timer token) ****/
2332
Jeremy Hylton938ace62002-07-17 16:30:39 +00002333static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002334
Guido van Rossum00d93061998-05-28 23:06:38 +00002335typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002336 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002337 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002338 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002339} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340
2341static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002342Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343{
Barry Warsawfa701a81997-01-16 00:15:11 +00002344 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002345 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002346
Guido van Rossum43713e52000-02-29 13:59:29 +00002347 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002348 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002349 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002350 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002351 v->token = NULL;
2352 }
2353 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002355 Py_DECREF(func);
2356 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002357 }
2358 Py_INCREF(Py_None);
2359 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002360}
2361
2362static PyMethodDef Tktt_methods[] =
2363{
Neal Norwitzb0493252002-03-31 14:44:22 +00002364 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002365 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002366};
2367
2368static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002369Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002370{
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002372
Guido van Rossumb18618d2000-05-03 23:44:39 +00002373 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002374 if (v == NULL)
2375 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002376
Guido van Rossum00d93061998-05-28 23:06:38 +00002377 Py_INCREF(func);
2378 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002379 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002380
2381 /* Extra reference, deleted when called or when handler is deleted */
2382 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002383 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002384}
2385
2386static void
Fred Drake509d79a2000-07-08 04:04:38 +00002387Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002388{
Guido van Rossum00d93061998-05-28 23:06:38 +00002389 TkttObject *v = (TkttObject *)self;
2390 PyObject *func = v->func;
2391
2392 Py_XDECREF(func);
2393
Guido van Rossumb18618d2000-05-03 23:44:39 +00002394 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002395}
2396
Guido van Rossum597ac201998-05-12 14:36:19 +00002397static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002398Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399{
Barry Warsawfa701a81997-01-16 00:15:11 +00002400 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002401 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402
Tim Peters885d4572001-11-28 20:27:42 +00002403 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002404 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002405 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002406}
2407
2408static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002409Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002410{
Barry Warsawfa701a81997-01-16 00:15:11 +00002411 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002412}
2413
2414static PyTypeObject Tktt_Type =
2415{
Guido van Rossum35d43371997-08-02 00:09:09 +00002416 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002417 0, /*ob_size */
2418 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002419 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002420 0, /*tp_itemsize */
2421 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002422 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002423 Tktt_GetAttr, /*tp_getattr */
2424 0, /*tp_setattr */
2425 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002426 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002427 0, /*tp_as_number */
2428 0, /*tp_as_sequence */
2429 0, /*tp_as_mapping */
2430 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002431};
2432
Barry Warsawfa701a81997-01-16 00:15:11 +00002433
2434
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002435/** Timer Handler **/
2436
2437static void
Fred Drake509d79a2000-07-08 04:04:38 +00002438TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002439{
Guido van Rossum00d93061998-05-28 23:06:38 +00002440 TkttObject *v = (TkttObject *)clientData;
2441 PyObject *func = v->func;
2442 PyObject *res;
2443
2444 if (func == NULL)
2445 return;
2446
2447 v->func = NULL;
2448
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002449 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002450
2451 res = PyEval_CallObject(func, NULL);
2452 Py_DECREF(func);
2453 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002454
Barry Warsawfa701a81997-01-16 00:15:11 +00002455 if (res == NULL) {
2456 errorInCmd = 1;
2457 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2458 }
2459 else
2460 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002461
2462 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002463}
2464
2465static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002466Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002467{
Barry Warsawfa701a81997-01-16 00:15:11 +00002468 int milliseconds;
2469 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002470 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002471
Guido van Rossum2834b972000-10-06 16:58:26 +00002472 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2473 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002474 return NULL;
2475 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002476 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002477 return NULL;
2478 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002479
Martin v. Löwisa9656492003-03-30 08:44:58 +00002480#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002481 if (!self && !tcl_lock) {
2482 /* We don't have the Tcl lock since Tcl is threaded. */
2483 PyErr_SetString(PyExc_RuntimeError,
2484 "_tkinter.createtimerhandler not supported "
2485 "for threaded Tcl");
2486 return NULL;
2487 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002488#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002489
2490 if (self) {
2491 CHECK_TCL_APPARTMENT;
2492 }
2493
Guido van Rossum00d93061998-05-28 23:06:38 +00002494 v = Tktt_New(func);
2495 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2496 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002497
Guido van Rossum00d93061998-05-28 23:06:38 +00002498 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002499}
2500
Barry Warsawfa701a81997-01-16 00:15:11 +00002501
Guido van Rossum18468821994-06-20 07:49:28 +00002502/** Event Loop **/
2503
Guido van Rossum18468821994-06-20 07:49:28 +00002504static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002505Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002506{
Barry Warsawfa701a81997-01-16 00:15:11 +00002507 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002508 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002509#ifdef WITH_THREAD
2510 PyThreadState *tstate = PyThreadState_Get();
2511#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002512
Guido van Rossum43713e52000-02-29 13:59:29 +00002513 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002514 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002515
Martin v. Löwisa9656492003-03-30 08:44:58 +00002516#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002517 if (!self && !tcl_lock) {
2518 /* We don't have the Tcl lock since Tcl is threaded. */
2519 PyErr_SetString(PyExc_RuntimeError,
2520 "_tkinter.mainloop not supported "
2521 "for threaded Tcl");
2522 return NULL;
2523 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002524#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002525
2526 if (self) {
2527 CHECK_TCL_APPARTMENT;
2528 self->dispatching = 1;
2529 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002530
Barry Warsawfa701a81997-01-16 00:15:11 +00002531 quitMainLoop = 0;
2532 while (Tk_GetNumMainWindows() > threshold &&
2533 !quitMainLoop &&
2534 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002535 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002536 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002537
2538#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002539 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002540 /* Allow other Python threads to run. */
2541 ENTER_TCL
2542 result = Tcl_DoOneEvent(0);
2543 LEAVE_TCL
2544 }
2545 else {
2546 Py_BEGIN_ALLOW_THREADS
2547 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2548 tcl_tstate = tstate;
2549 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2550 tcl_tstate = NULL;
2551 if(tcl_lock)PyThread_release_lock(tcl_lock);
2552 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002553 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002554 Py_END_ALLOW_THREADS
2555 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002556#else
2557 result = Tcl_DoOneEvent(0);
2558#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002559
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002560 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002561 if (self)
2562 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002563 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002564 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002565 if (result < 0)
2566 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002567 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002568 if (self)
2569 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002570 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002571
Barry Warsawfa701a81997-01-16 00:15:11 +00002572 if (errorInCmd) {
2573 errorInCmd = 0;
2574 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2575 excInCmd = valInCmd = trbInCmd = NULL;
2576 return NULL;
2577 }
2578 Py_INCREF(Py_None);
2579 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002580}
2581
2582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002583Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002584{
Guido van Rossum35d43371997-08-02 00:09:09 +00002585 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002586 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002587
Guido van Rossum43713e52000-02-29 13:59:29 +00002588 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002589 return NULL;
2590
Guido van Rossum00d93061998-05-28 23:06:38 +00002591 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002592 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002593 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002594 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002595}
2596
2597static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002598Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002599{
2600
Guido van Rossum43713e52000-02-29 13:59:29 +00002601 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002602 return NULL;
2603
2604 quitMainLoop = 1;
2605 Py_INCREF(Py_None);
2606 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002607}
2608
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002609static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002610Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002611{
2612
Guido van Rossum43713e52000-02-29 13:59:29 +00002613 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002614 return NULL;
2615
2616 return PyInt_FromLong((long)Tkapp_Interp(self));
2617}
2618
David Aschere2b4b322004-02-18 05:59:53 +00002619static PyObject *
2620Tkapp_TkInit(PyObject *self, PyObject *args)
2621{
2622 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002623 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002624 const char * _tk_exists = NULL;
2625 PyObject *res = NULL;
2626 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002627 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002628
2629 /* We want to guard against calling Tk_Init() multiple times */
2630 CHECK_TCL_APPARTMENT;
2631 ENTER_TCL
2632 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2633 ENTER_OVERLAP
2634 if (err == TCL_ERROR) {
Neal Norwitzd948a432006-01-08 01:08:55 +00002635 /* XXX: shouldn't we do something with res? */
David Aschere2b4b322004-02-18 05:59:53 +00002636 res = Tkinter_Error(self);
2637 } else {
2638 _tk_exists = Tkapp_Result(self);
2639 }
2640 LEAVE_OVERLAP_TCL
2641 if (err == TCL_ERROR) {
2642 return NULL;
2643 }
2644 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2645 if (Tk_Init(interp) == TCL_ERROR) {
2646 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2647 return NULL;
2648 }
2649 }
2650 Py_INCREF(Py_None);
2651 return Py_None;
2652}
Barry Warsawfa701a81997-01-16 00:15:11 +00002653
Martin v. Löwisffad6332002-11-26 09:28:05 +00002654static PyObject *
2655Tkapp_WantObjects(PyObject *self, PyObject *args)
2656{
2657
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002658 int wantobjects = -1;
2659 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002660 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002661 if (wantobjects == -1)
2662 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002663 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002664
2665 Py_INCREF(Py_None);
2666 return Py_None;
2667}
2668
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002669static PyObject *
2670Tkapp_WillDispatch(PyObject *self, PyObject *args)
2671{
2672
2673 ((TkappObject*)self)->dispatching = 1;
2674
2675 Py_INCREF(Py_None);
2676 return Py_None;
2677}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002678
Barry Warsawfa701a81997-01-16 00:15:11 +00002679
Guido van Rossum18468821994-06-20 07:49:28 +00002680/**** Tkapp Method List ****/
2681
2682static PyMethodDef Tkapp_methods[] =
2683{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002684 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002685 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002686 {"call", Tkapp_Call, METH_OLDARGS},
2687 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2688 {"eval", Tkapp_Eval, METH_VARARGS},
2689 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2690 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2691 {"record", Tkapp_Record, METH_VARARGS},
2692 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2693 {"setvar", Tkapp_SetVar, METH_VARARGS},
2694 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2695 {"getvar", Tkapp_GetVar, METH_VARARGS},
2696 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2697 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2698 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2699 {"getint", Tkapp_GetInt, METH_VARARGS},
2700 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2701 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2702 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2703 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2704 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2705 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2706 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2707 {"split", Tkapp_Split, METH_VARARGS},
2708 {"merge", Tkapp_Merge, METH_OLDARGS},
2709 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2710 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002711#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002712 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2713 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002714#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002715 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2716 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2717 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2718 {"quit", Tkapp_Quit, METH_VARARGS},
2719 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002720 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002721 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002722};
2723
Barry Warsawfa701a81997-01-16 00:15:11 +00002724
2725
Guido van Rossum18468821994-06-20 07:49:28 +00002726/**** Tkapp Type Methods ****/
2727
2728static void
Fred Drake509d79a2000-07-08 04:04:38 +00002729Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002730{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002731 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002732 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002733 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002734 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002735 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002736 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002737}
2738
2739static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002740Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002741{
Guido van Rossum35d43371997-08-02 00:09:09 +00002742 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002743}
2744
2745static PyTypeObject Tkapp_Type =
2746{
Guido van Rossum35d43371997-08-02 00:09:09 +00002747 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002748 0, /*ob_size */
2749 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002750 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002751 0, /*tp_itemsize */
2752 Tkapp_Dealloc, /*tp_dealloc */
2753 0, /*tp_print */
2754 Tkapp_GetAttr, /*tp_getattr */
2755 0, /*tp_setattr */
2756 0, /*tp_compare */
2757 0, /*tp_repr */
2758 0, /*tp_as_number */
2759 0, /*tp_as_sequence */
2760 0, /*tp_as_mapping */
2761 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002762};
2763
Barry Warsawfa701a81997-01-16 00:15:11 +00002764
2765
Guido van Rossum18468821994-06-20 07:49:28 +00002766/**** Tkinter Module ****/
2767
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002768typedef struct {
2769 PyObject* tuple;
2770 int size; /* current size */
2771 int maxsize; /* allocated size */
2772} FlattenContext;
2773
2774static int
2775_bump(FlattenContext* context, int size)
2776{
Guido van Rossum2834b972000-10-06 16:58:26 +00002777 /* expand tuple to hold (at least) size new items.
2778 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002779
2780 int maxsize = context->maxsize * 2;
2781
2782 if (maxsize < context->size + size)
2783 maxsize = context->size + size;
2784
2785 context->maxsize = maxsize;
2786
Tim Peters4324aa32001-05-28 22:30:08 +00002787 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002788}
2789
2790static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002791_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002792{
2793 /* add tuple or list to argument tuple (recursively) */
2794
2795 int i, size;
2796
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002797 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002798 PyErr_SetString(PyExc_ValueError,
2799 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002800 return 0;
2801 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002802 size = PyList_GET_SIZE(item);
2803 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002804 if (context->size + size > context->maxsize &&
2805 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002806 return 0;
2807 /* copy items to output tuple */
2808 for (i = 0; i < size; i++) {
2809 PyObject *o = PyList_GET_ITEM(item, i);
2810 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002811 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002812 return 0;
2813 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002814 if (context->size + 1 > context->maxsize &&
2815 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002816 return 0;
2817 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002818 PyTuple_SET_ITEM(context->tuple,
2819 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002820 }
2821 }
2822 } else if (PyTuple_Check(item)) {
2823 /* same, for tuples */
2824 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002825 if (context->size + size > context->maxsize &&
2826 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002827 return 0;
2828 for (i = 0; i < size; i++) {
2829 PyObject *o = PyTuple_GET_ITEM(item, i);
2830 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002831 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002832 return 0;
2833 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002834 if (context->size + 1 > context->maxsize &&
2835 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002836 return 0;
2837 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002838 PyTuple_SET_ITEM(context->tuple,
2839 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002840 }
2841 }
2842 } else {
2843 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2844 return 0;
2845 }
2846 return 1;
2847}
2848
2849static PyObject *
2850Tkinter_Flatten(PyObject* self, PyObject* args)
2851{
2852 FlattenContext context;
2853 PyObject* item;
2854
2855 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2856 return NULL;
2857
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002858 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002859 if (context.maxsize <= 0)
2860 return PyTuple_New(0);
2861
2862 context.tuple = PyTuple_New(context.maxsize);
2863 if (!context.tuple)
2864 return NULL;
2865
2866 context.size = 0;
2867
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002868 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002869 return NULL;
2870
Tim Peters4324aa32001-05-28 22:30:08 +00002871 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002872 return NULL;
2873
2874 return context.tuple;
2875}
2876
Guido van Rossum18468821994-06-20 07:49:28 +00002877static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002878Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002879{
Barry Warsawfa701a81997-01-16 00:15:11 +00002880 char *screenName = NULL;
2881 char *baseName = NULL;
2882 char *className = NULL;
2883 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002884 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002885 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002886 int sync = 0; /* pass -sync to wish */
2887 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002888
Guido van Rossum35d43371997-08-02 00:09:09 +00002889 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002890 if (baseName != NULL)
2891 baseName++;
2892 else
2893 baseName = Py_GetProgramName();
2894 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002895
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002896 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002897 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002898 &interactive, &wantobjects, &wantTk,
2899 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002900 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002901
Barry Warsawfa701a81997-01-16 00:15:11 +00002902 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002903 interactive, wantobjects, wantTk,
2904 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002905}
2906
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002907static PyObject *
2908Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2909{
2910 int new_val;
2911 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2912 return NULL;
2913 if (new_val < 0) {
2914 PyErr_SetString(PyExc_ValueError,
2915 "busywaitinterval must be >= 0");
2916 return NULL;
2917 }
2918 Tkinter_busywaitinterval = new_val;
2919 Py_INCREF(Py_None);
2920 return Py_None;
2921}
2922
2923static char setbusywaitinterval_doc[] =
2924"setbusywaitinterval(n) -> None\n\
2925\n\
2926Set the busy-wait interval in milliseconds between successive\n\
2927calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2928It should be set to a divisor of the maximum time between\n\
2929frames in an animation.";
2930
2931static PyObject *
2932Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2933{
2934 return PyInt_FromLong(Tkinter_busywaitinterval);
2935}
2936
2937static char getbusywaitinterval_doc[] =
2938"getbusywaitinterval() -> int\n\
2939\n\
2940Return the current busy-wait interval between successive\n\
2941calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2942
Guido van Rossum18468821994-06-20 07:49:28 +00002943static PyMethodDef moduleMethods[] =
2944{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002945 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2946 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002947#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002948 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2949 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002950#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002951 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2952 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2953 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2954 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002955 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2956 setbusywaitinterval_doc},
2957 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2958 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002959 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002960};
2961
Guido van Rossum7bf15641998-05-22 18:28:17 +00002962#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002963
2964static int stdin_ready = 0;
2965
Guido van Rossumad4db171998-06-13 13:56:28 +00002966#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002967static void
Fred Drake509d79a2000-07-08 04:04:38 +00002968MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002969{
2970 stdin_ready = 1;
2971}
Guido van Rossumad4db171998-06-13 13:56:28 +00002972#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002973
Martin v. Löwisa9656492003-03-30 08:44:58 +00002974#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002975static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002976#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002977
Guido van Rossum18468821994-06-20 07:49:28 +00002978static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002979EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002980{
Guido van Rossumad4db171998-06-13 13:56:28 +00002981#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002982 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002983#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002984#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002985 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002986#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002987 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002988 errorInCmd = 0;
2989#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002990 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002991 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002992#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002993 while (!errorInCmd && !stdin_ready) {
2994 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002995#ifdef MS_WINDOWS
2996 if (_kbhit()) {
2997 stdin_ready = 1;
2998 break;
2999 }
3000#endif
3001#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00003002 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003003 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00003004 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003005
Guido van Rossum00d93061998-05-28 23:06:38 +00003006 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003007
3008 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003009 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00003010 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003011 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00003012 Py_END_ALLOW_THREADS
3013#else
3014 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003015#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003016
3017 if (result < 0)
3018 break;
3019 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003020#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003021 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003022#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003023 if (errorInCmd) {
3024 errorInCmd = 0;
3025 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3026 excInCmd = valInCmd = trbInCmd = NULL;
3027 PyErr_Print();
3028 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003029#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003030 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003031#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003032 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003033}
Guido van Rossum18468821994-06-20 07:49:28 +00003034
Guido van Rossum00d93061998-05-28 23:06:38 +00003035#endif
3036
Guido van Rossum7bf15641998-05-22 18:28:17 +00003037static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003038EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003039{
Guido van Rossum00d93061998-05-28 23:06:38 +00003040#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003041 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003042#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003043 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003044#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003045 PyOS_InputHook = EventHook;
3046 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003047#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003048}
3049
3050static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003051DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003052{
Guido van Rossum00d93061998-05-28 23:06:38 +00003053#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003054 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3055 PyOS_InputHook = NULL;
3056 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003057#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003058}
3059
Barry Warsawfa701a81997-01-16 00:15:11 +00003060
3061/* all errors will be checked in one fell swoop in init_tkinter() */
3062static void
Fred Drake509d79a2000-07-08 04:04:38 +00003063ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003064{
3065 PyObject *v = PyInt_FromLong(val);
3066 if (v) {
3067 PyDict_SetItemString(d, name, v);
3068 Py_DECREF(v);
3069 }
3070}
3071static void
Fred Drake509d79a2000-07-08 04:04:38 +00003072ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003073{
3074 PyObject *v = PyString_FromString(val);
3075 if (v) {
3076 PyDict_SetItemString(d, name, v);
3077 Py_DECREF(v);
3078 }
3079}
3080
3081
Mark Hammond62b1ab12002-07-23 06:31:15 +00003082PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003083init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003084{
Barry Warsawfa701a81997-01-16 00:15:11 +00003085 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003086
Barry Warsawfa701a81997-01-16 00:15:11 +00003087 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003088
3089#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003090 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003091#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003092
Barry Warsawfa701a81997-01-16 00:15:11 +00003093 m = Py_InitModule("_tkinter", moduleMethods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00003094 if (m == NULL)
3095 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003096
Barry Warsawfa701a81997-01-16 00:15:11 +00003097 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003098 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003099 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003100
Guido van Rossum35d43371997-08-02 00:09:09 +00003101 ins_long(d, "READABLE", TCL_READABLE);
3102 ins_long(d, "WRITABLE", TCL_WRITABLE);
3103 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3104 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3105 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3106 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3107 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3108 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3109 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003110 ins_string(d, "TK_VERSION", TK_VERSION);
3111 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003112
Guido van Rossum83551bf1997-09-13 00:44:23 +00003113 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003114
3115 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003116 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3117
Martin v. Löwisffad6332002-11-26 09:28:05 +00003118 PyTclObject_Type.ob_type = &PyType_Type;
3119 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003120
3121#ifdef TK_AQUA
3122 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3123 * start waking up. Note that Tcl_FindExecutable will do this, this
3124 * code must be above it! The original warning from
3125 * tkMacOSXAppInit.c is copied below.
3126 *
3127 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3128 * Tcl interpreter for now. It probably should work to do this
3129 * in the other order, but for now it doesn't seem to.
3130 *
3131 */
3132 Tk_MacOSXSetupTkNotifier();
3133#endif
3134
3135
Guido van Rossume187b0e2000-03-27 21:46:29 +00003136 /* This helps the dynamic loader; in Unicode aware Tcl versions
3137 it also helps Tcl find its encodings. */
3138 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003139
Barry Warsawfa701a81997-01-16 00:15:11 +00003140 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003141 return;
3142
Guido van Rossum43ff8681998-07-14 18:02:13 +00003143#if 0
3144 /* This was not a good idea; through <Destroy> bindings,
3145 Tcl_Finalize() may invoke Python code but at that point the
3146 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003147 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003148#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003149
Guido van Rossum18468821994-06-20 07:49:28 +00003150}