blob: c3015b9f8a5388b7c1d731b7acf9dbf6b8b3345e [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
Barry Warsawfa701a81997-01-16 00:15:11 +0000689 if (Tcl_AppInit(v->interp) != TCL_OK)
Guido van Rossumc821d1e1998-07-07 22:25:47 +0000690 return (TkappObject *)Tkinter_Error((PyObject *)v);
Barry Warsawfa701a81997-01-16 00:15:11 +0000691
Guido van Rossum7bf15641998-05-22 18:28:17 +0000692 EnableEventHook();
693
Barry Warsawfa701a81997-01-16 00:15:11 +0000694 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000695}
696
Barry Warsawfa701a81997-01-16 00:15:11 +0000697
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000698static void
699Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
700 Tcl_Condition *cond, Tcl_Mutex *mutex)
701{
702 Py_BEGIN_ALLOW_THREADS;
703 Tcl_MutexLock(mutex);
704 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
705 Tcl_ThreadAlert(self->thread_id);
706 Tcl_ConditionWait(cond, mutex, NULL);
707 Tcl_MutexUnlock(mutex);
708 Py_END_ALLOW_THREADS
709}
710
Barry Warsawfa701a81997-01-16 00:15:11 +0000711
Guido van Rossum18468821994-06-20 07:49:28 +0000712/** Tcl Eval **/
713
Martin v. Löwisffad6332002-11-26 09:28:05 +0000714typedef struct {
715 PyObject_HEAD
716 Tcl_Obj *value;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000717 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000718} PyTclObject;
719
720staticforward PyTypeObject PyTclObject_Type;
721#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
722
723static PyObject *
724newPyTclObject(Tcl_Obj *arg)
725{
726 PyTclObject *self;
727 self = PyObject_New(PyTclObject, &PyTclObject_Type);
728 if (self == NULL)
729 return NULL;
730 Tcl_IncrRefCount(arg);
731 self->value = arg;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000732 self->string = NULL;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000733 return (PyObject*)self;
734}
735
736static void
737PyTclObject_dealloc(PyTclObject *self)
738{
739 Tcl_DecrRefCount(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000740 Py_XDECREF(self->string);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000741 PyObject_Del(self);
742}
743
744static PyObject *
745PyTclObject_str(PyTclObject *self)
746{
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000747 if (self->string && PyString_Check(self->string)) {
748 Py_INCREF(self->string);
749 return self->string;
750 }
751 /* XXX Could cache value if it is an ASCII string. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000752 return PyString_FromString(Tcl_GetString(self->value));
753}
754
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000755static char*
756PyTclObject_TclString(PyObject *self)
757{
758 return Tcl_GetString(((PyTclObject*)self)->value);
759}
760
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000761/* Like _str, but create Unicode if necessary. */
Martin v. Löwis39195712003-01-04 00:33:13 +0000762PyDoc_STRVAR(PyTclObject_string__doc__,
763"the string representation of this object, either as string or Unicode");
764
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765static PyObject *
766PyTclObject_string(PyTclObject *self, void *ignored)
767{
768 char *s;
769 int i, len;
770 if (!self->string) {
771 s = Tcl_GetStringFromObj(self->value, &len);
772 for (i = 0; i < len; i++)
773 if (s[i] & 0x80)
774 break;
775#ifdef Py_USING_UNICODE
776 if (i == len)
777 /* It is an ASCII string. */
778 self->string = PyString_FromStringAndSize(s, len);
779 else {
780 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
781 if (!self->string) {
782 PyErr_Clear();
783 self->string = PyString_FromStringAndSize(s, len);
784 }
785 }
786#else
787 self->string = PyString_FromStringAndSize(s, len);
788#endif
789 if (!self->string)
790 return NULL;
791 }
792 Py_INCREF(self->string);
793 return self->string;
794}
795
796#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000797PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
798
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000799static PyObject *
800PyTclObject_unicode(PyTclObject *self, void *ignored)
801{
802 char *s;
803 int len;
804 if (self->string && PyUnicode_Check(self->string)) {
805 Py_INCREF(self->string);
806 return self->string;
807 }
808 /* XXX Could chache result if it is non-ASCII. */
809 s = Tcl_GetStringFromObj(self->value, &len);
810 return PyUnicode_DecodeUTF8(s, len, "strict");
811}
812#endif
813
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814static PyObject *
815PyTclObject_repr(PyTclObject *self)
816{
817 char buf[50];
Martin v. Löwisfba73692004-11-13 11:13:35 +0000818 PyOS_snprintf(buf, 50, "<%s object at %p>",
819 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000820 return PyString_FromString(buf);
821}
822
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000823static int
824PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
825{
826 int res;
827 res = strcmp(Tcl_GetString(self->value),
828 Tcl_GetString(other->value));
829 if (res < 0) return -1;
830 if (res > 0) return 1;
831 return 0;
832}
833
Martin v. Löwis39195712003-01-04 00:33:13 +0000834PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
835
Martin v. Löwisffad6332002-11-26 09:28:05 +0000836static PyObject*
837get_typename(PyTclObject* obj, void* ignored)
838{
839 return PyString_FromString(obj->value->typePtr->name);
840}
841
Martin v. Löwis39195712003-01-04 00:33:13 +0000842
Martin v. Löwisffad6332002-11-26 09:28:05 +0000843static PyGetSetDef PyTclObject_getsetlist[] = {
Martin v. Löwis39195712003-01-04 00:33:13 +0000844 {"typename", (getter)get_typename, NULL, get_typename__doc__},
845 {"string", (getter)PyTclObject_string, NULL,
846 PyTclObject_string__doc__},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000847 {0},
848};
849
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000850static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000851#ifdef Py_USING_UNICODE
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000852 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
Martin v. Löwis39195712003-01-04 00:33:13 +0000853 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000854#endif
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000855 {0}
856};
857
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858statichere PyTypeObject PyTclObject_Type = {
859 PyObject_HEAD_INIT(NULL)
860 0, /*ob_size*/
861 "_tkinter.Tcl_Obj", /*tp_name*/
862 sizeof(PyTclObject), /*tp_basicsize*/
863 0, /*tp_itemsize*/
864 /* methods */
865 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
866 0, /*tp_print*/
867 0, /*tp_getattr*/
868 0, /*tp_setattr*/
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000869 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000870 (reprfunc)PyTclObject_repr, /*tp_repr*/
871 0, /*tp_as_number*/
872 0, /*tp_as_sequence*/
873 0, /*tp_as_mapping*/
874 0, /*tp_hash*/
875 0, /*tp_call*/
876 (reprfunc)PyTclObject_str, /*tp_str*/
Jason Tishlerfb8595d2003-01-06 12:41:26 +0000877 PyObject_GenericGetAttr,/*tp_getattro*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000878 0, /*tp_setattro*/
879 0, /*tp_as_buffer*/
880 Py_TPFLAGS_DEFAULT, /*tp_flags*/
881 0, /*tp_doc*/
882 0, /*tp_traverse*/
883 0, /*tp_clear*/
884 0, /*tp_richcompare*/
885 0, /*tp_weaklistoffset*/
886 0, /*tp_iter*/
887 0, /*tp_iternext*/
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000888 PyTclObject_methods, /*tp_methods*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889 0, /*tp_members*/
890 PyTclObject_getsetlist, /*tp_getset*/
891 0, /*tp_base*/
892 0, /*tp_dict*/
893 0, /*tp_descr_get*/
894 0, /*tp_descr_set*/
895 0, /*tp_dictoffset*/
896 0, /*tp_init*/
897 0, /*tp_alloc*/
898 0, /*tp_new*/
899 0, /*tp_free*/
900 0, /*tp_is_gc*/
901};
902
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000903static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000904AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000905{
906 Tcl_Obj *result;
907
908 if (PyString_Check(value))
909 return Tcl_NewStringObj(PyString_AS_STRING(value),
910 PyString_GET_SIZE(value));
Martin v. Löwis70c3dda2003-01-22 09:17:38 +0000911 else if (PyBool_Check(value))
912 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000913 else if (PyInt_Check(value))
914 return Tcl_NewLongObj(PyInt_AS_LONG(value));
915 else if (PyFloat_Check(value))
916 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
917 else if (PyTuple_Check(value)) {
918 Tcl_Obj **argv = (Tcl_Obj**)
919 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
920 int i;
921 if(!argv)
922 return 0;
923 for(i=0;i<PyTuple_Size(value);i++)
924 argv[i] = AsObj(PyTuple_GetItem(value,i));
925 result = Tcl_NewListObj(PyTuple_Size(value), argv);
926 ckfree(FREECAST argv);
927 return result;
928 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000929#ifdef Py_USING_UNICODE
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000930 else if (PyUnicode_Check(value)) {
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000931 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
932 int size = PyUnicode_GET_SIZE(value);
933 /* This #ifdef assumes that Tcl uses UCS-2.
934 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000935#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000936 Tcl_UniChar *outbuf;
937 int i;
938 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
939 if (!outbuf) {
940 PyErr_NoMemory();
941 return NULL;
Guido van Rossum990f5c62000-05-04 15:07:16 +0000942 }
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000943 for (i = 0; i < size; i++) {
944 if (inbuf[i] >= 0x10000) {
945 /* Tcl doesn't do UTF-16, yet. */
946 PyErr_SetString(PyExc_ValueError,
947 "unsupported character");
948 ckfree(FREECAST outbuf);
949 return NULL;
950 }
951 outbuf[i] = inbuf[i];
952 }
953 result = Tcl_NewUnicodeObj(outbuf, size);
954 ckfree(FREECAST outbuf);
955 return result;
956#else
957 return Tcl_NewUnicodeObj(inbuf, size);
958#endif
959
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000960 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000961#endif
Martin v. Löwisffad6332002-11-26 09:28:05 +0000962 else if(PyTclObject_Check(value)) {
963 Tcl_Obj *v = ((PyTclObject*)value)->value;
964 Tcl_IncrRefCount(v);
965 return v;
966 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000967 else {
968 PyObject *v = PyObject_Str(value);
969 if (!v)
970 return 0;
971 result = AsObj(v);
972 Py_DECREF(v);
973 return result;
974 }
975}
976
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977static PyObject*
978FromObj(PyObject* tkapp, Tcl_Obj *value)
979{
980 PyObject *result = NULL;
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000981 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000982
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000983 if (value->typePtr == NULL) {
984 /* If the result contains any bytes with the top bit set,
985 it's UTF-8 and we should decode it to Unicode */
986#ifdef Py_USING_UNICODE
987 int i;
988 char *s = value->bytes;
989 int len = value->length;
990 for (i = 0; i < len; i++) {
991 if (value->bytes[i] & 0x80)
992 break;
993 }
994
995 if (i == value->length)
996 result = PyString_FromStringAndSize(s, len);
997 else {
998 /* Convert UTF-8 to Unicode string */
999 result = PyUnicode_DecodeUTF8(s, len, "strict");
1000 if (result == NULL) {
1001 PyErr_Clear();
1002 result = PyString_FromStringAndSize(s, len);
1003 }
1004 }
1005#else
Martin v. Löwise2713be2005-03-08 15:03:08 +00001006 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001007#endif
1008 return result;
1009 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001010
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001011 if (value->typePtr == app->BooleanType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001012 result = value->internalRep.longValue ? Py_True : Py_False;
1013 Py_INCREF(result);
1014 return result;
1015 }
1016
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001017 if (value->typePtr == app->ByteArrayType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001018 int size;
Martin v. Löwis33ec3ba2002-12-07 14:57:11 +00001019 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001020 return PyString_FromStringAndSize(data, size);
1021 }
1022
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001023 if (value->typePtr == app->DoubleType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024 return PyFloat_FromDouble(value->internalRep.doubleValue);
1025 }
1026
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001027 if (value->typePtr == app->IntType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028 return PyInt_FromLong(value->internalRep.longValue);
1029 }
1030
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001031 if (value->typePtr == app->ListType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032 int size;
1033 int i, status;
1034 PyObject *elem;
1035 Tcl_Obj *tcl_elem;
1036
1037 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1038 if (status == TCL_ERROR)
1039 return Tkinter_Error(tkapp);
1040 result = PyTuple_New(size);
1041 if (!result)
1042 return NULL;
1043 for (i = 0; i < size; i++) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001044 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
Martin v. Löwisffad6332002-11-26 09:28:05 +00001045 value, i, &tcl_elem);
1046 if (status == TCL_ERROR) {
1047 Py_DECREF(result);
1048 return Tkinter_Error(tkapp);
1049 }
1050 elem = FromObj(tkapp, tcl_elem);
1051 if (!elem) {
1052 Py_DECREF(result);
1053 return NULL;
1054 }
1055 PyTuple_SetItem(result, i, elem);
1056 }
1057 return result;
1058 }
1059
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001060 if (value->typePtr == app->ProcBodyType) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001061 /* fall through: return tcl object. */
Martin v. Löwisffad6332002-11-26 09:28:05 +00001062 }
1063
Martin v. Löwis4ec2e702002-11-26 22:12:12 +00001064 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001065#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001066#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Martin v. Löwisffad6332002-11-26 09:28:05 +00001067 PyObject *result;
1068 int size;
1069 Tcl_UniChar *input;
1070 Py_UNICODE *output;
1071
1072 size = Tcl_GetCharLength(value);
1073 result = PyUnicode_FromUnicode(NULL, size);
1074 if (!result)
1075 return NULL;
1076 input = Tcl_GetUnicode(value);
1077 output = PyUnicode_AS_UNICODE(result);
1078 while (size--)
1079 *output++ = *input++;
1080 return result;
1081#else
1082 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1083 Tcl_GetCharLength(value));
1084#endif
1085#else
1086 int size;
1087 char *c;
1088 c = Tcl_GetStringFromObj(value, &size);
1089 return PyString_FromStringAndSize(c, size);
1090#endif
1091 }
1092
1093 return newPyTclObject(value);
1094}
1095
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001096/* This mutex synchronizes inter-thread command calls. */
1097
1098TCL_DECLARE_MUTEX(call_mutex)
1099
1100typedef struct Tkapp_CallEvent {
1101 Tcl_Event ev; /* Must be first */
1102 TkappObject *self;
1103 PyObject *args;
1104 int flags;
1105 PyObject **res;
1106 PyObject **exc_type, **exc_value, **exc_tb;
1107 Tcl_Condition done;
1108} Tkapp_CallEvent;
1109
1110void
1111Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001112{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001113 int i;
1114 for (i = 0; i < objc; i++)
1115 Tcl_DecrRefCount(objv[i]);
1116 if (objv != objStore)
1117 ckfree(FREECAST objv);
1118}
Guido van Rossum18468821994-06-20 07:49:28 +00001119
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001120/* Convert Python objects to Tcl objects. This must happen in the
1121 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001122
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001123static Tcl_Obj**
1124Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1125{
1126 Tcl_Obj **objv = objStore;
Martin v. Löwis7d134952002-12-12 19:05:48 +00001127 int objc = 0, i;
Guido van Rossum212643f1998-04-29 16:22:14 +00001128 if (args == NULL)
Martin v. Löwis02956012000-10-29 00:44:43 +00001129 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001130
Guido van Rossum212643f1998-04-29 16:22:14 +00001131 else if (!PyTuple_Check(args)) {
Guido van Rossum632de272000-03-29 00:19:50 +00001132 objv[0] = AsObj(args);
1133 if (objv[0] == 0)
1134 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001135 objc = 1;
Guido van Rossum632de272000-03-29 00:19:50 +00001136 Tcl_IncrRefCount(objv[0]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001137 }
1138 else {
Guido van Rossum632de272000-03-29 00:19:50 +00001139 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001140
Guido van Rossum632de272000-03-29 00:19:50 +00001141 if (objc > ARGSZ) {
1142 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1143 if (objv == NULL) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001144 PyErr_NoMemory();
Martin v. Löwis02956012000-10-29 00:44:43 +00001145 objc = 0;
Guido van Rossum212643f1998-04-29 16:22:14 +00001146 goto finally;
1147 }
1148 }
1149
Guido van Rossum632de272000-03-29 00:19:50 +00001150 for (i = 0; i < objc; i++) {
Guido van Rossum212643f1998-04-29 16:22:14 +00001151 PyObject *v = PyTuple_GetItem(args, i);
Guido van Rossum64231e52000-03-31 03:29:39 +00001152 if (v == Py_None) {
1153 objc = i;
1154 break;
1155 }
Guido van Rossum632de272000-03-29 00:19:50 +00001156 objv[i] = AsObj(v);
Martin v. Löwis02956012000-10-29 00:44:43 +00001157 if (!objv[i]) {
1158 /* Reset objc, so it attempts to clear
1159 objects only up to i. */
1160 objc = i;
Guido van Rossum632de272000-03-29 00:19:50 +00001161 goto finally;
Martin v. Löwis02956012000-10-29 00:44:43 +00001162 }
Guido van Rossum632de272000-03-29 00:19:50 +00001163 Tcl_IncrRefCount(objv[i]);
Guido van Rossum212643f1998-04-29 16:22:14 +00001164 }
1165 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001166 *pobjc = objc;
1167 return objv;
1168finally:
1169 Tkapp_CallDeallocArgs(objv, objStore, objc);
1170 return NULL;
1171}
Guido van Rossum212643f1998-04-29 16:22:14 +00001172
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001173/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001174
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001175static PyObject*
1176Tkapp_CallResult(TkappObject *self)
1177{
1178 PyObject *res = NULL;
1179 if(self->wantobjects) {
1180 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001181 /* Not sure whether the IncrRef is necessary, but something
1182 may overwrite the interpreter result while we are
1183 converting it. */
1184 Tcl_IncrRefCount(value);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001185 res = FromObj((PyObject*)self, value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001186 Tcl_DecrRefCount(value);
1187 } else {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001188 const char *s = Tcl_GetStringResult(self->interp);
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001189 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001190
Guido van Rossum990f5c62000-05-04 15:07:16 +00001191 /* If the result contains any bytes with the top bit set,
1192 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001193#ifdef Py_USING_UNICODE
Guido van Rossum990f5c62000-05-04 15:07:16 +00001194 while (*p != '\0') {
1195 if (*p & 0x80)
1196 break;
1197 p++;
1198 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001199
Guido van Rossum990f5c62000-05-04 15:07:16 +00001200 if (*p == '\0')
1201 res = PyString_FromStringAndSize(s, (int)(p-s));
1202 else {
1203 /* Convert UTF-8 to Unicode string */
1204 p = strchr(p, '\0');
Guido van Rossum69529ad2000-05-04 15:55:17 +00001205 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1206 if (res == NULL) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001207 PyErr_Clear();
1208 res = PyString_FromStringAndSize(s, (int)(p-s));
Guido van Rossum69529ad2000-05-04 15:55:17 +00001209 }
Guido van Rossum990f5c62000-05-04 15:07:16 +00001210 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001211#else
1212 p = strchr(p, '\0');
1213 res = PyString_FromStringAndSize(s, (int)(p-s));
1214#endif
Guido van Rossum990f5c62000-05-04 15:07:16 +00001215 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216 return res;
1217}
Guido van Rossum632de272000-03-29 00:19:50 +00001218
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001219/* Tkapp_CallProc is the event procedure that is executed in the context of
1220 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1221 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001222
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223static int
1224Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1225{
1226 Tcl_Obj *objStore[ARGSZ];
1227 Tcl_Obj **objv;
1228 int objc;
1229 int i;
1230 ENTER_PYTHON
1231 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1232 if (!objv) {
1233 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1234 *(e->res) = NULL;
1235 }
1236 LEAVE_PYTHON
1237 if (!objv)
1238 goto done;
1239 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1240 ENTER_PYTHON
1241 if (i == TCL_ERROR) {
1242 *(e->res) = NULL;
1243 *(e->exc_type) = NULL;
1244 *(e->exc_tb) = NULL;
1245 *(e->exc_value) = PyObject_CallFunction(
1246 Tkinter_TclError, "s",
1247 Tcl_GetStringResult(e->self->interp));
1248 }
1249 else {
1250 *(e->res) = Tkapp_CallResult(e->self);
1251 }
1252 LEAVE_PYTHON
1253 done:
1254 /* Wake up calling thread. */
1255 Tcl_MutexLock(&call_mutex);
1256 Tcl_ConditionNotify(&e->done);
1257 Tcl_MutexUnlock(&call_mutex);
1258 return 1;
1259}
1260
1261/* This is the main entry point for calling a Tcl command.
1262 It supports three cases, with regard to threading:
1263 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1264 the context of the calling thread.
1265 2. Tcl is threaded, caller of the command is in the interpreter thread:
1266 Execute the command in the calling thread. Since the Tcl lock will
1267 not be used, we can merge that with case 1.
1268 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1269 the interpreter thread. Allocation of Tcl objects needs to occur in the
1270 interpreter thread, so we ship the PyObject* args to the target thread,
1271 and perform processing there. */
1272
1273static PyObject *
1274Tkapp_Call(PyObject *_self, PyObject *args)
1275{
1276 Tcl_Obj *objStore[ARGSZ];
1277 Tcl_Obj **objv = NULL;
1278 int objc, i;
1279 PyObject *res = NULL;
1280 TkappObject *self = (TkappObject*)_self;
1281 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1282 int flags = TCL_EVAL_DIRECT;
1283
Martin v. Löwisa9656492003-03-30 08:44:58 +00001284#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001285 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1286 /* We cannot call the command directly. Instead, we must
1287 marshal the parameters to the interpreter thread. */
1288 Tkapp_CallEvent *ev;
1289 PyObject *exc_type, *exc_value, *exc_tb;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001290 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1293 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1294 ev->self = self;
1295 ev->args = args;
1296 ev->res = &res;
1297 ev->exc_type = &exc_type;
1298 ev->exc_value = &exc_value;
1299 ev->exc_tb = &exc_tb;
1300 ev->done = (Tcl_Condition)0;
1301
1302 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1303
1304 if (res == NULL) {
1305 if (exc_type)
1306 PyErr_Restore(exc_type, exc_value, exc_tb);
1307 else
1308 PyErr_SetObject(Tkinter_TclError, exc_value);
1309 }
1310 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001311 else
1312#endif
1313 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
1315 objv = Tkapp_CallArgs(args, objStore, &objc);
1316 if (!objv)
1317 return NULL;
1318
1319 ENTER_TCL
1320
1321 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1322
1323 ENTER_OVERLAP
1324
1325 if (i == TCL_ERROR)
1326 Tkinter_Error(_self);
1327 else
1328 res = Tkapp_CallResult(self);
1329
1330 LEAVE_OVERLAP_TCL
1331
1332 Tkapp_CallDeallocArgs(objv, objStore, objc);
1333 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001334 return res;
1335}
1336
1337
1338static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001339Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001340{
Guido van Rossum212643f1998-04-29 16:22:14 +00001341 /* Could do the same here as for Tkapp_Call(), but this is not used
1342 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1343 way for the user to do what all its Global* variants do (save and
1344 reset the scope pointer, call the local version, restore the saved
1345 scope pointer). */
1346
Guido van Rossum62320c91998-06-15 04:36:09 +00001347 char *cmd;
Barry Warsawfa701a81997-01-16 00:15:11 +00001348 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001349
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001350 CHECK_TCL_APPARTMENT;
1351
Guido van Rossum62320c91998-06-15 04:36:09 +00001352 cmd = Merge(args);
Guido van Rossum2834b972000-10-06 16:58:26 +00001353 if (cmd) {
Guido van Rossum00d93061998-05-28 23:06:38 +00001354 int err;
1355 ENTER_TCL
1356 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
Guido van Rossum62320c91998-06-15 04:36:09 +00001357 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001358 if (err == TCL_ERROR)
1359 res = Tkinter_Error(self);
1360 else
1361 res = PyString_FromString(Tkapp_Result(self));
Guido van Rossum62320c91998-06-15 04:36:09 +00001362 LEAVE_OVERLAP_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001363 ckfree(cmd);
Guido van Rossum2834b972000-10-06 16:58:26 +00001364 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001365
1366 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001367}
1368
1369static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001370Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001371{
Barry Warsawfa701a81997-01-16 00:15:11 +00001372 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001373 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001374 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001375
Guido van Rossum43713e52000-02-29 13:59:29 +00001376 if (!PyArg_ParseTuple(args, "s:eval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001377 return NULL;
1378
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001379 CHECK_TCL_APPARTMENT;
1380
Guido van Rossum00d93061998-05-28 23:06:38 +00001381 ENTER_TCL
1382 err = Tcl_Eval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001383 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001384 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001385 res = Tkinter_Error(self);
1386 else
1387 res = PyString_FromString(Tkapp_Result(self));
1388 LEAVE_OVERLAP_TCL
1389 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001390}
1391
1392static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001393Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001394{
Barry Warsawfa701a81997-01-16 00:15:11 +00001395 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001396 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001397 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001398
Guido van Rossum43713e52000-02-29 13:59:29 +00001399 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001400 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001401
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001402 CHECK_TCL_APPARTMENT;
1403
Guido van Rossum00d93061998-05-28 23:06:38 +00001404 ENTER_TCL
1405 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
Guido van Rossum62320c91998-06-15 04:36:09 +00001406 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001407 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001408 res = Tkinter_Error(self);
1409 else
1410 res = PyString_FromString(Tkapp_Result(self));
1411 LEAVE_OVERLAP_TCL
1412 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001413}
1414
1415static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001416Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001417{
Barry Warsawfa701a81997-01-16 00:15:11 +00001418 char *fileName;
Guido van Rossum62320c91998-06-15 04:36:09 +00001419 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001420 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001421
Guido van Rossum43713e52000-02-29 13:59:29 +00001422 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
Barry Warsawfa701a81997-01-16 00:15:11 +00001423 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001424
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425 CHECK_TCL_APPARTMENT;
1426
Guido van Rossum00d93061998-05-28 23:06:38 +00001427 ENTER_TCL
1428 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
Guido van Rossum62320c91998-06-15 04:36:09 +00001429 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001430 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001431 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001432
Guido van Rossum62320c91998-06-15 04:36:09 +00001433 else
1434 res = PyString_FromString(Tkapp_Result(self));
1435 LEAVE_OVERLAP_TCL
1436 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001437}
1438
1439static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001440Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001441{
Barry Warsawfa701a81997-01-16 00:15:11 +00001442 char *script;
Guido van Rossum62320c91998-06-15 04:36:09 +00001443 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001444 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001445
Guido van Rossum35d43371997-08-02 00:09:09 +00001446 if (!PyArg_ParseTuple(args, "s", &script))
Barry Warsawfa701a81997-01-16 00:15:11 +00001447 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001448
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449 CHECK_TCL_APPARTMENT;
1450
Guido van Rossum00d93061998-05-28 23:06:38 +00001451 ENTER_TCL
1452 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
Guido van Rossum62320c91998-06-15 04:36:09 +00001453 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001454 if (err == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001455 res = Tkinter_Error(self);
1456 else
1457 res = PyString_FromString(Tkapp_Result(self));
1458 LEAVE_OVERLAP_TCL
1459 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001460}
1461
1462static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001463Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001464{
Barry Warsawfa701a81997-01-16 00:15:11 +00001465 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001466
Guido van Rossum43713e52000-02-29 13:59:29 +00001467 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
Barry Warsawfa701a81997-01-16 00:15:11 +00001468 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469 CHECK_TCL_APPARTMENT;
1470
Guido van Rossum00d93061998-05-28 23:06:38 +00001471 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00001472 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
Guido van Rossum00d93061998-05-28 23:06:38 +00001473 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001474
Barry Warsawfa701a81997-01-16 00:15:11 +00001475 Py_INCREF(Py_None);
1476 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001477}
1478
Barry Warsawfa701a81997-01-16 00:15:11 +00001479
1480
Guido van Rossum18468821994-06-20 07:49:28 +00001481/** Tcl Variable **/
1482
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483TCL_DECLARE_MUTEX(var_mutex)
1484
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001485typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486typedef struct VarEvent {
1487 Tcl_Event ev; /* must be first */
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001488 PyObject *self;
1489 PyObject *args;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490 int flags;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001491 EventFunc func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001492 PyObject **res;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001493 PyObject **exc_type;
1494 PyObject **exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496} VarEvent;
1497
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001498static int
1499varname_converter(PyObject *in, void *_out)
1500{
1501 char **out = (char**)_out;
1502 if (PyString_Check(in)) {
1503 *out = PyString_AsString(in);
1504 return 1;
1505 }
1506 if (PyTclObject_Check(in)) {
1507 *out = PyTclObject_TclString(in);
1508 return 1;
1509 }
1510 /* XXX: Should give diagnostics. */
1511 return 0;
1512}
1513
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001514void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001515var_perform(VarEvent *ev)
1516{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001517 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1518 if (!*(ev->res)) {
1519 PyObject *exc, *val, *tb;
1520 PyErr_Fetch(&exc, &val, &tb);
1521 PyErr_NormalizeException(&exc, &val, &tb);
1522 *(ev->exc_type) = exc;
1523 *(ev->exc_val) = val;
1524 Py_DECREF(tb);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001525 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001526
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001527}
1528
1529static int
1530var_proc(VarEvent* ev, int flags)
1531{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532 ENTER_PYTHON
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001533 var_perform(ev);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534 Tcl_MutexLock(&var_mutex);
1535 Tcl_ConditionNotify(&ev->cond);
1536 Tcl_MutexUnlock(&var_mutex);
1537 LEAVE_PYTHON
1538 return 1;
1539}
1540
1541static PyObject*
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001542var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001543{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544 TkappObject *self = (TkappObject*)_self;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001545#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001547 TkappObject *self = (TkappObject*)_self;
1548 VarEvent *ev;
1549 PyObject *res, *exc_type, *exc_val;
1550
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001551 /* The current thread is not the interpreter thread. Marshal
1552 the call to the interpreter thread, then wait for
1553 completion. */
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00001554 if (!WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001555 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001556
1557 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1558
1559 ev->self = _self;
1560 ev->args = args;
1561 ev->flags = flags;
1562 ev->func = func;
1563 ev->res = &res;
1564 ev->exc_type = &exc_type;
1565 ev->exc_val = &exc_val;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001566 ev->cond = NULL;
1567 ev->ev.proc = (Tcl_EventProc*)var_proc;
1568 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001569 if (!res) {
1570 PyErr_SetObject(exc_type, exc_val);
1571 Py_DECREF(exc_type);
1572 Py_DECREF(exc_val);
1573 return NULL;
1574 }
1575 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001576 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001577#endif
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001578 /* Tcl is not threaded, or this is the interpreter thread. */
1579 return func(_self, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001580}
1581
Guido van Rossum18468821994-06-20 07:49:28 +00001582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001583SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001584{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001585 char *name1, *name2;
Barry Warsawfa701a81997-01-16 00:15:11 +00001586 PyObject *newValue;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001587 PyObject *res = NULL;
1588 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001589
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001590 if (PyArg_ParseTuple(args, "O&O:setvar",
1591 varname_converter, &name1, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001592 /* XXX Acquire tcl lock??? */
1593 newval = AsObj(newValue);
1594 if (newval == NULL)
Guido van Rossum2834b972000-10-06 16:58:26 +00001595 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001596 ENTER_TCL
1597 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1598 newval, flags);
1599 ENTER_OVERLAP
1600 if (!ok)
1601 Tkinter_Error(self);
1602 else {
1603 res = Py_None;
1604 Py_INCREF(res);
1605 }
1606 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001607 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001608 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001609 PyErr_Clear();
Guido van Rossum2834b972000-10-06 16:58:26 +00001610 if (PyArg_ParseTuple(args, "ssO:setvar",
1611 &name1, &name2, &newValue)) {
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001612 /* XXX must hold tcl lock already??? */
1613 newval = AsObj(newValue);
1614 ENTER_TCL
1615 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1616 ENTER_OVERLAP
1617 if (!ok)
1618 Tkinter_Error(self);
1619 else {
1620 res = Py_None;
1621 Py_INCREF(res);
1622 }
1623 LEAVE_OVERLAP_TCL
Guido van Rossum00d93061998-05-28 23:06:38 +00001624 }
Guido van Rossum35d43371997-08-02 00:09:09 +00001625 else {
Guido van Rossum35d43371997-08-02 00:09:09 +00001626 return NULL;
1627 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001628 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001629 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
1632static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001633Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001634{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001635 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001636}
1637
1638static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001639Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001640{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001641 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001642}
1643
Barry Warsawfa701a81997-01-16 00:15:11 +00001644
1645
Guido van Rossum18468821994-06-20 07:49:28 +00001646static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001647GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001648{
Martin v. Löwis71e25a02002-10-01 18:08:06 +00001649 char *name1, *name2=NULL;
Guido van Rossum62320c91998-06-15 04:36:09 +00001650 PyObject *res = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001651 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001652
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001653 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1654 varname_converter, &name1, &name2))
Guido van Rossum35d43371997-08-02 00:09:09 +00001655 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001656
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001657 ENTER_TCL
1658 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1659 ENTER_OVERLAP
Martin v. Löwisd46e6842003-10-03 17:12:26 +00001660 if (tres == NULL) {
1661 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1662 } else {
1663 if (((TkappObject*)self)->wantobjects) {
1664 res = FromObj(self, tres);
1665 }
1666 else {
1667 res = PyString_FromString(Tcl_GetString(tres));
1668 }
Martin v. Löwis8fd86cc2003-05-19 19:57:42 +00001669 }
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001670 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001671 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001672}
1673
1674static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001675Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001676{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001677 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001678}
1679
1680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001681Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001682{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001683 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001684}
1685
Barry Warsawfa701a81997-01-16 00:15:11 +00001686
1687
Guido van Rossum18468821994-06-20 07:49:28 +00001688static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001689UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001690{
Guido van Rossum35d43371997-08-02 00:09:09 +00001691 char *name1, *name2=NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001692 int code;
Guido van Rossum62320c91998-06-15 04:36:09 +00001693 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001694
Guido van Rossum43713e52000-02-29 13:59:29 +00001695 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
Barry Warsawfa701a81997-01-16 00:15:11 +00001696 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001697
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001698 ENTER_TCL
1699 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1700 ENTER_OVERLAP
1701 if (code == TCL_ERROR)
1702 res = Tkinter_Error(self);
1703 else {
1704 Py_INCREF(Py_None);
1705 res = Py_None;
1706 }
1707 LEAVE_OVERLAP_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +00001708 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
1711static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001712Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001713{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001714 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001715}
1716
1717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001718Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001719{
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001720 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001721}
1722
Barry Warsawfa701a81997-01-16 00:15:11 +00001723
1724
Guido van Rossum18468821994-06-20 07:49:28 +00001725/** Tcl to Python **/
1726
1727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Barry Warsawfa701a81997-01-16 00:15:11 +00001730 char *s;
1731 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001732
Martin v. Löwisffad6332002-11-26 09:28:05 +00001733 if (PyTuple_Size(args) == 1) {
1734 PyObject* o = PyTuple_GetItem(args, 0);
1735 if (PyInt_Check(o)) {
1736 Py_INCREF(o);
1737 return o;
1738 }
1739 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001740 if (!PyArg_ParseTuple(args, "s:getint", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001741 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001742 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001743 return Tkinter_Error(self);
1744 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001745}
1746
1747static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001748Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001749{
Barry Warsawfa701a81997-01-16 00:15:11 +00001750 char *s;
1751 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001752
Martin v. Löwisffad6332002-11-26 09:28:05 +00001753 if (PyTuple_Size(args) == 1) {
1754 PyObject *o = PyTuple_GetItem(args, 0);
1755 if (PyFloat_Check(o)) {
1756 Py_INCREF(o);
1757 return o;
1758 }
1759 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001760 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001761 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001762 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
Barry Warsawfa701a81997-01-16 00:15:11 +00001763 return Tkinter_Error(self);
1764 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001765}
1766
1767static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001768Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001769{
Barry Warsawfa701a81997-01-16 00:15:11 +00001770 char *s;
1771 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001772
Martin v. Löwisffad6332002-11-26 09:28:05 +00001773 if (PyTuple_Size(args) == 1) {
1774 PyObject *o = PyTuple_GetItem(args, 0);
1775 if (PyInt_Check(o)) {
1776 Py_INCREF(o);
1777 return o;
1778 }
1779 }
Guido van Rossum43713e52000-02-29 13:59:29 +00001780 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001781 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001782 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1783 return Tkinter_Error(self);
Martin v. Löwis70c3dda2003-01-22 09:17:38 +00001784 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001785}
1786
1787static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001788Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001789{
Barry Warsawfa701a81997-01-16 00:15:11 +00001790 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001791 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001792 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001793
Guido van Rossum43713e52000-02-29 13:59:29 +00001794 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001795 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001796
1797 CHECK_TCL_APPARTMENT;
1798
Guido van Rossum00d93061998-05-28 23:06:38 +00001799 ENTER_TCL
1800 retval = Tcl_ExprString(Tkapp_Interp(self), s);
Guido van Rossum62320c91998-06-15 04:36:09 +00001801 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001802 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001803 res = Tkinter_Error(self);
1804 else
1805 res = Py_BuildValue("s", Tkapp_Result(self));
1806 LEAVE_OVERLAP_TCL
1807 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
1810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Barry Warsawfa701a81997-01-16 00:15:11 +00001813 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001814 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001815 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001816 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001817
Guido van Rossum43713e52000-02-29 13:59:29 +00001818 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001819 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001820
1821 CHECK_TCL_APPARTMENT;
1822
Guido van Rossum00d93061998-05-28 23:06:38 +00001823 ENTER_TCL
1824 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001825 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001826 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001827 res = Tkinter_Error(self);
1828 else
1829 res = Py_BuildValue("l", v);
1830 LEAVE_OVERLAP_TCL
1831 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001832}
1833
1834static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001835Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001836{
Barry Warsawfa701a81997-01-16 00:15:11 +00001837 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001838 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001839 double v;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001840 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001841
Guido van Rossum43713e52000-02-29 13:59:29 +00001842 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001843 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001844 CHECK_TCL_APPARTMENT;
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001845 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
Guido van Rossum00d93061998-05-28 23:06:38 +00001846 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00001847 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001848 ENTER_OVERLAP
Guido van Rossum45b83911997-03-14 04:32:50 +00001849 PyFPE_END_PROTECT(retval)
Guido van Rossum52fa3a61997-02-14 22:59:58 +00001850 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001851 res = Tkinter_Error(self);
1852 else
1853 res = Py_BuildValue("d", v);
1854 LEAVE_OVERLAP_TCL
1855 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001856}
1857
1858static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001859Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001860{
Barry Warsawfa701a81997-01-16 00:15:11 +00001861 char *s;
Guido van Rossum62320c91998-06-15 04:36:09 +00001862 PyObject *res = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00001863 int retval;
Barry Warsawfa701a81997-01-16 00:15:11 +00001864 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001865
Guido van Rossum43713e52000-02-29 13:59:29 +00001866 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
Barry Warsawfa701a81997-01-16 00:15:11 +00001867 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001868 CHECK_TCL_APPARTMENT;
Guido van Rossum00d93061998-05-28 23:06:38 +00001869 ENTER_TCL
1870 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
Guido van Rossum62320c91998-06-15 04:36:09 +00001871 ENTER_OVERLAP
Guido van Rossum00d93061998-05-28 23:06:38 +00001872 if (retval == TCL_ERROR)
Guido van Rossum62320c91998-06-15 04:36:09 +00001873 res = Tkinter_Error(self);
1874 else
1875 res = Py_BuildValue("i", v);
1876 LEAVE_OVERLAP_TCL
1877 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001878}
1879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880
1881
Guido van Rossum18468821994-06-20 07:49:28 +00001882static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001883Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Barry Warsawfa701a81997-01-16 00:15:11 +00001885 char *list;
1886 int argc;
1887 char **argv;
1888 PyObject *v;
1889 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001890
Martin v. Löwisffad6332002-11-26 09:28:05 +00001891 if (PyTuple_Size(args) == 1) {
1892 v = PyTuple_GetItem(args, 0);
1893 if (PyTuple_Check(v)) {
1894 Py_INCREF(v);
1895 return v;
1896 }
1897 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001898 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001899 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001900
Neal Norwitzd1c55102003-05-29 00:17:03 +00001901 if (Tcl_SplitList(Tkapp_Interp(self), list,
1902 &argc, &argv) == TCL_ERROR) {
1903 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001904 return Tkinter_Error(self);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001905 }
Guido van Rossum18468821994-06-20 07:49:28 +00001906
Barry Warsawfa701a81997-01-16 00:15:11 +00001907 if (!(v = PyTuple_New(argc)))
Neal Norwitzd1c55102003-05-29 00:17:03 +00001908 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001909
Barry Warsawfa701a81997-01-16 00:15:11 +00001910 for (i = 0; i < argc; i++) {
1911 PyObject *s = PyString_FromString(argv[i]);
1912 if (!s || PyTuple_SetItem(v, i, s)) {
1913 Py_DECREF(v);
1914 v = NULL;
1915 goto finally;
1916 }
1917 }
Guido van Rossum18468821994-06-20 07:49:28 +00001918
Barry Warsawfa701a81997-01-16 00:15:11 +00001919 finally:
1920 ckfree(FREECAST argv);
Neal Norwitzd1c55102003-05-29 00:17:03 +00001921 PyMem_Free(list);
Barry Warsawfa701a81997-01-16 00:15:11 +00001922 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001923}
1924
1925static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001926Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Neal Norwitzd1c55102003-05-29 00:17:03 +00001928 PyObject *v;
Barry Warsawfa701a81997-01-16 00:15:11 +00001929 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001930
Martin v. Löwisffad6332002-11-26 09:28:05 +00001931 if (PyTuple_Size(args) == 1) {
1932 PyObject* o = PyTuple_GetItem(args, 0);
1933 if (PyTuple_Check(o)) {
1934 o = SplitObj(o);
1935 return o;
1936 }
1937 }
Martin v. Löwis84432eb2002-01-26 20:21:50 +00001938 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
Barry Warsawfa701a81997-01-16 00:15:11 +00001939 return NULL;
Neal Norwitzd1c55102003-05-29 00:17:03 +00001940 v = Split(list);
1941 PyMem_Free(list);
1942 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001943}
1944
1945static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001946Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001947{
Barry Warsawfa701a81997-01-16 00:15:11 +00001948 char *s = Merge(args);
1949 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001950
Barry Warsawfa701a81997-01-16 00:15:11 +00001951 if (s) {
1952 res = PyString_FromString(s);
1953 ckfree(s);
1954 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001955
1956 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001957}
1958
Barry Warsawfa701a81997-01-16 00:15:11 +00001959
1960
Guido van Rossum18468821994-06-20 07:49:28 +00001961/** Tcl Command **/
1962
Guido van Rossum00d93061998-05-28 23:06:38 +00001963/* Client data struct */
1964typedef struct {
Guido van Rossum00d93061998-05-28 23:06:38 +00001965 PyObject *self;
1966 PyObject *func;
1967} PythonCmd_ClientData;
1968
1969static int
Fred Drake509d79a2000-07-08 04:04:38 +00001970PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001971{
1972 errorInCmd = 1;
1973 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1974 LEAVE_PYTHON
1975 return TCL_ERROR;
1976}
1977
Guido van Rossum18468821994-06-20 07:49:28 +00001978/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001979 * function or method.
1980 */
Guido van Rossum18468821994-06-20 07:49:28 +00001981static int
Fred Drake509d79a2000-07-08 04:04:38 +00001982PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001983{
Guido van Rossum00d93061998-05-28 23:06:38 +00001984 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00001985 PyObject *self, *func, *arg, *res, *tmp;
Guido van Rossum2834b972000-10-06 16:58:26 +00001986 int i, rv;
1987 char *s;
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Guido van Rossumdc1adab1998-10-09 20:51:18 +00001989 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00001990
Barry Warsawfa701a81997-01-16 00:15:11 +00001991 /* TBD: no error checking here since we know, via the
1992 * Tkapp_CreateCommand() that the client data is a two-tuple
1993 */
Guido van Rossum00d93061998-05-28 23:06:38 +00001994 self = data->self;
1995 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Barry Warsawfa701a81997-01-16 00:15:11 +00001997 /* Create argument list (argv1, ..., argvN) */
1998 if (!(arg = PyTuple_New(argc - 1)))
1999 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002000
Barry Warsawfa701a81997-01-16 00:15:11 +00002001 for (i = 0; i < (argc - 1); i++) {
2002 PyObject *s = PyString_FromString(argv[i + 1]);
2003 if (!s || PyTuple_SetItem(arg, i, s)) {
2004 Py_DECREF(arg);
Guido van Rossumf766e231998-06-19 04:28:10 +00002005 return PythonCmd_Error(interp);
Barry Warsawfa701a81997-01-16 00:15:11 +00002006 }
2007 }
2008 res = PyEval_CallObject(func, arg);
2009 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002010
Barry Warsawfa701a81997-01-16 00:15:11 +00002011 if (res == NULL)
2012 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002013
Barry Warsawfa701a81997-01-16 00:15:11 +00002014 if (!(tmp = PyList_New(0))) {
2015 Py_DECREF(res);
2016 return PythonCmd_Error(interp);
2017 }
2018
Guido van Rossum2834b972000-10-06 16:58:26 +00002019 s = AsString(res, tmp);
2020 if (s == NULL) {
2021 rv = PythonCmd_Error(interp);
2022 }
2023 else {
2024 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2025 rv = TCL_OK;
2026 }
2027
Barry Warsawfa701a81997-01-16 00:15:11 +00002028 Py_DECREF(res);
2029 Py_DECREF(tmp);
2030
Guido van Rossum00d93061998-05-28 23:06:38 +00002031 LEAVE_PYTHON
2032
Guido van Rossum2834b972000-10-06 16:58:26 +00002033 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002034}
2035
2036static void
Fred Drake509d79a2000-07-08 04:04:38 +00002037PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002038{
Guido van Rossum00d93061998-05-28 23:06:38 +00002039 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2040
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002041 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002042 Py_XDECREF(data->self);
2043 Py_XDECREF(data->func);
2044 PyMem_DEL(data);
2045 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002046}
2047
Barry Warsawfa701a81997-01-16 00:15:11 +00002048
2049
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002050
2051TCL_DECLARE_MUTEX(command_mutex)
2052
2053typedef struct CommandEvent{
2054 Tcl_Event ev;
2055 Tcl_Interp* interp;
2056 char *name;
2057 int create;
2058 int *status;
2059 ClientData *data;
2060 Tcl_Condition done;
2061} CommandEvent;
2062
2063static int
2064Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002065{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002066 if (ev->create)
2067 *ev->status = Tcl_CreateCommand(
2068 ev->interp, ev->name, PythonCmd,
2069 ev->data, PythonCmdDelete) == NULL;
2070 else
2071 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2072 Tcl_MutexLock(&command_mutex);
2073 Tcl_ConditionNotify(&ev->done);
2074 Tcl_MutexUnlock(&command_mutex);
2075 return 1;
2076}
2077
2078static PyObject *
2079Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2080{
2081 TkappObject *self = (TkappObject*)_self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002082 PythonCmd_ClientData *data;
Barry Warsawfa701a81997-01-16 00:15:11 +00002083 char *cmdName;
Barry Warsawfa701a81997-01-16 00:15:11 +00002084 PyObject *func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002085 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002086
Guido van Rossum43713e52000-02-29 13:59:29 +00002087 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
Guido van Rossum35d43371997-08-02 00:09:09 +00002088 return NULL;
2089 if (!PyCallable_Check(func)) {
2090 PyErr_SetString(PyExc_TypeError, "command not callable");
Barry Warsawfa701a81997-01-16 00:15:11 +00002091 return NULL;
2092 }
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Martin v. Löwisa9656492003-03-30 08:44:58 +00002094#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002095 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002096 !WaitForMainloop(self))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002097 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002098#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002099
Guido van Rossum00d93061998-05-28 23:06:38 +00002100 data = PyMem_NEW(PythonCmd_ClientData, 1);
Barry Warsawfa701a81997-01-16 00:15:11 +00002101 if (!data)
Neal Norwitzec74f2f2003-02-11 23:05:40 +00002102 return PyErr_NoMemory();
Guido van Rossum00d93061998-05-28 23:06:38 +00002103 Py_XINCREF(self);
2104 Py_XINCREF(func);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002105 data->self = _self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002106 data->func = func;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
2108 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2109 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2110 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2111 ev->interp = self->interp;
2112 ev->create = 1;
2113 ev->name = cmdName;
2114 ev->data = (ClientData)data;
2115 ev->status = &err;
2116 ev->done = NULL;
2117 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2118 }
2119 else {
2120 ENTER_TCL
2121 err = Tcl_CreateCommand(
2122 Tkapp_Interp(self), cmdName, PythonCmd,
2123 (ClientData)data, PythonCmdDelete) == NULL;
2124 LEAVE_TCL
2125 }
2126 if (err) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002127 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
Guido van Rossum00d93061998-05-28 23:06:38 +00002128 PyMem_DEL(data);
Guido van Rossum35d43371997-08-02 00:09:09 +00002129 return NULL;
2130 }
Guido van Rossum18468821994-06-20 07:49:28 +00002131
Barry Warsawfa701a81997-01-16 00:15:11 +00002132 Py_INCREF(Py_None);
2133 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002134}
2135
Barry Warsawfa701a81997-01-16 00:15:11 +00002136
2137
Guido van Rossum18468821994-06-20 07:49:28 +00002138static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002139Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002140{
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002141 TkappObject *self = (TkappObject*)_self;
Barry Warsawfa701a81997-01-16 00:15:11 +00002142 char *cmdName;
Guido van Rossum00d93061998-05-28 23:06:38 +00002143 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002144
Guido van Rossum43713e52000-02-29 13:59:29 +00002145 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
Barry Warsawfa701a81997-01-16 00:15:11 +00002146 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002147 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2148 CommandEvent *ev;
2149 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2150 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2151 ev->interp = self->interp;
2152 ev->create = 0;
2153 ev->name = cmdName;
2154 ev->status = &err;
2155 ev->done = NULL;
2156 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2157 &command_mutex);
2158 }
2159 else {
2160 ENTER_TCL
2161 err = Tcl_DeleteCommand(self->interp, cmdName);
2162 LEAVE_TCL
2163 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002164 if (err == -1) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002165 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2166 return NULL;
2167 }
2168 Py_INCREF(Py_None);
2169 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002170}
2171
Barry Warsawfa701a81997-01-16 00:15:11 +00002172
2173
Guido van Rossum00d93061998-05-28 23:06:38 +00002174#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002175/** File Handler **/
2176
Guido van Rossum00d93061998-05-28 23:06:38 +00002177typedef struct _fhcdata {
Guido van Rossum00d93061998-05-28 23:06:38 +00002178 PyObject *func;
2179 PyObject *file;
2180 int id;
2181 struct _fhcdata *next;
2182} FileHandler_ClientData;
2183
2184static FileHandler_ClientData *HeadFHCD;
2185
2186static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002187NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002188{
2189 FileHandler_ClientData *p;
2190 p = PyMem_NEW(FileHandler_ClientData, 1);
2191 if (p != NULL) {
2192 Py_XINCREF(func);
2193 Py_XINCREF(file);
Guido van Rossum00d93061998-05-28 23:06:38 +00002194 p->func = func;
2195 p->file = file;
2196 p->id = id;
2197 p->next = HeadFHCD;
2198 HeadFHCD = p;
2199 }
2200 return p;
2201}
2202
2203static void
Fred Drake509d79a2000-07-08 04:04:38 +00002204DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002205{
2206 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002207
2208 pp = &HeadFHCD;
Guido van Rossum00d93061998-05-28 23:06:38 +00002209 while ((p = *pp) != NULL) {
2210 if (p->id == id) {
2211 *pp = p->next;
2212 Py_XDECREF(p->func);
2213 Py_XDECREF(p->file);
2214 PyMem_DEL(p);
2215 }
2216 else
2217 pp = &p->next;
2218 }
2219}
2220
Guido van Rossuma597dde1995-01-10 20:56:29 +00002221static void
Fred Drake509d79a2000-07-08 04:04:38 +00002222FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002223{
Guido van Rossum00d93061998-05-28 23:06:38 +00002224 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
Barry Warsawfa701a81997-01-16 00:15:11 +00002225 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002226
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002227 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002228 func = data->func;
2229 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002230
Barry Warsawfa701a81997-01-16 00:15:11 +00002231 arg = Py_BuildValue("(Oi)", file, (long) mask);
2232 res = PyEval_CallObject(func, arg);
Guido van Rossum35d43371997-08-02 00:09:09 +00002233 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002234
2235 if (res == NULL) {
2236 errorInCmd = 1;
2237 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2238 }
2239 Py_XDECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002240 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002241}
2242
Guido van Rossum18468821994-06-20 07:49:28 +00002243static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002244Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2245 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002246{
Guido van Rossum00d93061998-05-28 23:06:38 +00002247 FileHandler_ClientData *data;
2248 PyObject *file, *func;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002249 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002250
Guido van Rossum2834b972000-10-06 16:58:26 +00002251 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2252 &file, &mask, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002253 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002254
Martin v. Löwisa9656492003-03-30 08:44:58 +00002255#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002256 if (!self && !tcl_lock) {
2257 /* We don't have the Tcl lock since Tcl is threaded. */
2258 PyErr_SetString(PyExc_RuntimeError,
2259 "_tkinter.createfilehandler not supported "
2260 "for threaded Tcl");
2261 return NULL;
2262 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002263#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002264
2265 if (self) {
2266 CHECK_TCL_APPARTMENT;
2267 }
2268
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002269 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002270 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002271 return NULL;
2272 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002273 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002274 return NULL;
2275 }
2276
Guido van Rossuma80649b2000-03-28 20:07:05 +00002277 data = NewFHCD(func, file, tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002278 if (data == NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002279 return NULL;
2280
Barry Warsawfa701a81997-01-16 00:15:11 +00002281 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002282 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002283 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
Guido van Rossum00d93061998-05-28 23:06:38 +00002284 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002285 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002286 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002287}
2288
2289static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002290Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002291{
Barry Warsawfa701a81997-01-16 00:15:11 +00002292 PyObject *file;
Guido van Rossuma80649b2000-03-28 20:07:05 +00002293 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002294
Guido van Rossum43713e52000-02-29 13:59:29 +00002295 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
Barry Warsawfa701a81997-01-16 00:15:11 +00002296 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002297
Martin v. Löwisa9656492003-03-30 08:44:58 +00002298#ifdef WITH_THREAD
Neal Norwitz12e22172003-03-03 21:16:39 +00002299 if (!self && !tcl_lock) {
2300 /* We don't have the Tcl lock since Tcl is threaded. */
2301 PyErr_SetString(PyExc_RuntimeError,
2302 "_tkinter.deletefilehandler not supported "
2303 "for threaded Tcl");
2304 return NULL;
2305 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002306#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002307
2308 if (self) {
2309 CHECK_TCL_APPARTMENT;
2310 }
2311
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +00002312 tfile = PyObject_AsFileDescriptor(file);
Guido van Rossuma80649b2000-03-28 20:07:05 +00002313 if (tfile < 0)
Barry Warsawfa701a81997-01-16 00:15:11 +00002314 return NULL;
2315
Guido van Rossuma80649b2000-03-28 20:07:05 +00002316 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002317
Barry Warsawfa701a81997-01-16 00:15:11 +00002318 /* Ought to check for null Tcl_File object... */
Guido van Rossum00d93061998-05-28 23:06:38 +00002319 ENTER_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002320 Tcl_DeleteFileHandler(tfile);
Guido van Rossum00d93061998-05-28 23:06:38 +00002321 LEAVE_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002322 Py_INCREF(Py_None);
Barry Warsawfa701a81997-01-16 00:15:11 +00002323 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002324}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002325#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002326
Barry Warsawfa701a81997-01-16 00:15:11 +00002327
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002328/**** Tktt Object (timer token) ****/
2329
Jeremy Hylton938ace62002-07-17 16:30:39 +00002330static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002331
Guido van Rossum00d93061998-05-28 23:06:38 +00002332typedef struct {
Barry Warsawfa701a81997-01-16 00:15:11 +00002333 PyObject_HEAD
Guido van Rossum35d43371997-08-02 00:09:09 +00002334 Tcl_TimerToken token;
Barry Warsawfa701a81997-01-16 00:15:11 +00002335 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002336} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002337
2338static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002339Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002340{
Barry Warsawfa701a81997-01-16 00:15:11 +00002341 TkttObject *v = (TkttObject *)self;
Guido van Rossum00d93061998-05-28 23:06:38 +00002342 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002343
Guido van Rossum43713e52000-02-29 13:59:29 +00002344 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002345 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002346 if (v->token != NULL) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002347 Tcl_DeleteTimerHandler(v->token);
Guido van Rossum00d93061998-05-28 23:06:38 +00002348 v->token = NULL;
2349 }
2350 if (func != NULL) {
Barry Warsawfa701a81997-01-16 00:15:11 +00002351 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002352 Py_DECREF(func);
2353 Py_DECREF(v); /* See Tktt_New() */
Barry Warsawfa701a81997-01-16 00:15:11 +00002354 }
2355 Py_INCREF(Py_None);
2356 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002357}
2358
2359static PyMethodDef Tktt_methods[] =
2360{
Neal Norwitzb0493252002-03-31 14:44:22 +00002361 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002362 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002363};
2364
2365static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002366Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002367{
Barry Warsawfa701a81997-01-16 00:15:11 +00002368 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002369
Guido van Rossumb18618d2000-05-03 23:44:39 +00002370 v = PyObject_New(TkttObject, &Tktt_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +00002371 if (v == NULL)
2372 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002373
Guido van Rossum00d93061998-05-28 23:06:38 +00002374 Py_INCREF(func);
2375 v->token = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002376 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002377
2378 /* Extra reference, deleted when called or when handler is deleted */
2379 Py_INCREF(v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002380 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002381}
2382
2383static void
Fred Drake509d79a2000-07-08 04:04:38 +00002384Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002385{
Guido van Rossum00d93061998-05-28 23:06:38 +00002386 TkttObject *v = (TkttObject *)self;
2387 PyObject *func = v->func;
2388
2389 Py_XDECREF(func);
2390
Guido van Rossumb18618d2000-05-03 23:44:39 +00002391 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002392}
2393
Guido van Rossum597ac201998-05-12 14:36:19 +00002394static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002395Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002396{
Barry Warsawfa701a81997-01-16 00:15:11 +00002397 TkttObject *v = (TkttObject *)self;
Guido van Rossum597ac201998-05-12 14:36:19 +00002398 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399
Tim Peters885d4572001-11-28 20:27:42 +00002400 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
Jack Jansencb852442001-12-09 23:15:56 +00002401 v->func == NULL ? ", handler deleted" : "");
Guido van Rossum597ac201998-05-12 14:36:19 +00002402 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002403}
2404
2405static PyObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002406Tktt_GetAttr(PyObject *self, const char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407{
Barry Warsawfa701a81997-01-16 00:15:11 +00002408 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002409}
2410
2411static PyTypeObject Tktt_Type =
2412{
Guido van Rossum35d43371997-08-02 00:09:09 +00002413 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002414 0, /*ob_size */
2415 "tktimertoken", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002416 sizeof(TkttObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002417 0, /*tp_itemsize */
2418 Tktt_Dealloc, /*tp_dealloc */
Guido van Rossum597ac201998-05-12 14:36:19 +00002419 0, /*tp_print */
Barry Warsawfa701a81997-01-16 00:15:11 +00002420 Tktt_GetAttr, /*tp_getattr */
2421 0, /*tp_setattr */
2422 0, /*tp_compare */
Guido van Rossum597ac201998-05-12 14:36:19 +00002423 Tktt_Repr, /*tp_repr */
Barry Warsawfa701a81997-01-16 00:15:11 +00002424 0, /*tp_as_number */
2425 0, /*tp_as_sequence */
2426 0, /*tp_as_mapping */
2427 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428};
2429
Barry Warsawfa701a81997-01-16 00:15:11 +00002430
2431
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002432/** Timer Handler **/
2433
2434static void
Fred Drake509d79a2000-07-08 04:04:38 +00002435TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002436{
Guido van Rossum00d93061998-05-28 23:06:38 +00002437 TkttObject *v = (TkttObject *)clientData;
2438 PyObject *func = v->func;
2439 PyObject *res;
2440
2441 if (func == NULL)
2442 return;
2443
2444 v->func = NULL;
2445
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002446 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002447
2448 res = PyEval_CallObject(func, NULL);
2449 Py_DECREF(func);
2450 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002451
Barry Warsawfa701a81997-01-16 00:15:11 +00002452 if (res == NULL) {
2453 errorInCmd = 1;
2454 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2455 }
2456 else
2457 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002458
2459 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460}
2461
2462static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002463Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002464{
Barry Warsawfa701a81997-01-16 00:15:11 +00002465 int milliseconds;
2466 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002467 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002468
Guido van Rossum2834b972000-10-06 16:58:26 +00002469 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2470 &milliseconds, &func))
Barry Warsawfa701a81997-01-16 00:15:11 +00002471 return NULL;
2472 if (!PyCallable_Check(func)) {
Guido van Rossum35d43371997-08-02 00:09:09 +00002473 PyErr_SetString(PyExc_TypeError, "bad argument list");
Barry Warsawfa701a81997-01-16 00:15:11 +00002474 return NULL;
2475 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002476
Martin v. Löwisa9656492003-03-30 08:44:58 +00002477#ifdef WITH_THREAD
Martin v. Löwis7f134892003-03-03 10:40:01 +00002478 if (!self && !tcl_lock) {
2479 /* We don't have the Tcl lock since Tcl is threaded. */
2480 PyErr_SetString(PyExc_RuntimeError,
2481 "_tkinter.createtimerhandler not supported "
2482 "for threaded Tcl");
2483 return NULL;
2484 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002485#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002486
2487 if (self) {
2488 CHECK_TCL_APPARTMENT;
2489 }
2490
Guido van Rossum00d93061998-05-28 23:06:38 +00002491 v = Tktt_New(func);
2492 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2493 (ClientData)v);
Barry Warsawfa701a81997-01-16 00:15:11 +00002494
Guido van Rossum00d93061998-05-28 23:06:38 +00002495 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002496}
2497
Barry Warsawfa701a81997-01-16 00:15:11 +00002498
Guido van Rossum18468821994-06-20 07:49:28 +00002499/** Event Loop **/
2500
Guido van Rossum18468821994-06-20 07:49:28 +00002501static PyObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502Tkapp_MainLoop(PyObject *_self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002503{
Barry Warsawfa701a81997-01-16 00:15:11 +00002504 int threshold = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002505 TkappObject *self = (TkappObject*)_self;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002506#ifdef WITH_THREAD
2507 PyThreadState *tstate = PyThreadState_Get();
2508#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002509
Guido van Rossum43713e52000-02-29 13:59:29 +00002510 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
Barry Warsawfa701a81997-01-16 00:15:11 +00002511 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002512
Martin v. Löwisa9656492003-03-30 08:44:58 +00002513#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002514 if (!self && !tcl_lock) {
2515 /* We don't have the Tcl lock since Tcl is threaded. */
2516 PyErr_SetString(PyExc_RuntimeError,
2517 "_tkinter.mainloop not supported "
2518 "for threaded Tcl");
2519 return NULL;
2520 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002521#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002522
2523 if (self) {
2524 CHECK_TCL_APPARTMENT;
2525 self->dispatching = 1;
2526 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002527
Barry Warsawfa701a81997-01-16 00:15:11 +00002528 quitMainLoop = 0;
2529 while (Tk_GetNumMainWindows() > threshold &&
2530 !quitMainLoop &&
2531 !errorInCmd)
Guido van Rossum18468821994-06-20 07:49:28 +00002532 {
Guido van Rossum35d43371997-08-02 00:09:09 +00002533 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002534
2535#ifdef WITH_THREAD
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002536 if (self && self->threaded) {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002537 /* Allow other Python threads to run. */
2538 ENTER_TCL
2539 result = Tcl_DoOneEvent(0);
2540 LEAVE_TCL
2541 }
2542 else {
2543 Py_BEGIN_ALLOW_THREADS
2544 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2545 tcl_tstate = tstate;
2546 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2547 tcl_tstate = NULL;
2548 if(tcl_lock)PyThread_release_lock(tcl_lock);
2549 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002550 Sleep(Tkinter_busywaitinterval);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002551 Py_END_ALLOW_THREADS
2552 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002553#else
2554 result = Tcl_DoOneEvent(0);
2555#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002556
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002557 if (PyErr_CheckSignals() != 0) {
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002558 if (self)
2559 self->dispatching = 0;
Guido van Rossum35d43371997-08-02 00:09:09 +00002560 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002561 }
Guido van Rossum35d43371997-08-02 00:09:09 +00002562 if (result < 0)
2563 break;
Guido van Rossum18468821994-06-20 07:49:28 +00002564 }
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002565 if (self)
2566 self->dispatching = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002567 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002568
Barry Warsawfa701a81997-01-16 00:15:11 +00002569 if (errorInCmd) {
2570 errorInCmd = 0;
2571 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2572 excInCmd = valInCmd = trbInCmd = NULL;
2573 return NULL;
2574 }
2575 Py_INCREF(Py_None);
2576 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002577}
2578
2579static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002580Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002581{
Guido van Rossum35d43371997-08-02 00:09:09 +00002582 int flags = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +00002583 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002584
Guido van Rossum43713e52000-02-29 13:59:29 +00002585 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
Barry Warsawfa701a81997-01-16 00:15:11 +00002586 return NULL;
2587
Guido van Rossum00d93061998-05-28 23:06:38 +00002588 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002589 rv = Tcl_DoOneEvent(flags);
Guido van Rossum00d93061998-05-28 23:06:38 +00002590 LEAVE_TCL
Barry Warsawfa701a81997-01-16 00:15:11 +00002591 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002592}
2593
2594static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002595Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002596{
2597
Guido van Rossum43713e52000-02-29 13:59:29 +00002598 if (!PyArg_ParseTuple(args, ":quit"))
Barry Warsawfa701a81997-01-16 00:15:11 +00002599 return NULL;
2600
2601 quitMainLoop = 1;
2602 Py_INCREF(Py_None);
2603 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002604}
2605
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002606static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002607Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002608{
2609
Guido van Rossum43713e52000-02-29 13:59:29 +00002610 if (!PyArg_ParseTuple(args, ":interpaddr"))
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002611 return NULL;
2612
2613 return PyInt_FromLong((long)Tkapp_Interp(self));
2614}
2615
David Aschere2b4b322004-02-18 05:59:53 +00002616static PyObject *
2617Tkapp_TkInit(PyObject *self, PyObject *args)
2618{
2619 Tcl_Interp *interp = Tkapp_Interp(self);
Neal Norwitz44dbae82004-02-19 02:44:22 +00002620 Tk_Window main_window;
David Aschere2b4b322004-02-18 05:59:53 +00002621 const char * _tk_exists = NULL;
2622 PyObject *res = NULL;
2623 int err;
Neal Norwitz44dbae82004-02-19 02:44:22 +00002624 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002625
2626 /* We want to guard against calling Tk_Init() multiple times */
2627 CHECK_TCL_APPARTMENT;
2628 ENTER_TCL
2629 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2630 ENTER_OVERLAP
2631 if (err == TCL_ERROR) {
Neal Norwitzd948a432006-01-08 01:08:55 +00002632 /* XXX: shouldn't we do something with res? */
David Aschere2b4b322004-02-18 05:59:53 +00002633 res = Tkinter_Error(self);
2634 } else {
2635 _tk_exists = Tkapp_Result(self);
2636 }
2637 LEAVE_OVERLAP_TCL
2638 if (err == TCL_ERROR) {
2639 return NULL;
2640 }
2641 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2642 if (Tk_Init(interp) == TCL_ERROR) {
2643 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2644 return NULL;
2645 }
2646 }
2647 Py_INCREF(Py_None);
2648 return Py_None;
2649}
Barry Warsawfa701a81997-01-16 00:15:11 +00002650
Martin v. Löwisffad6332002-11-26 09:28:05 +00002651static PyObject *
2652Tkapp_WantObjects(PyObject *self, PyObject *args)
2653{
2654
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002655 int wantobjects = -1;
2656 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
Martin v. Löwisffad6332002-11-26 09:28:05 +00002657 return NULL;
Martin v. Löwisd6efae52003-06-14 21:34:32 +00002658 if (wantobjects == -1)
2659 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002660 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002661
2662 Py_INCREF(Py_None);
2663 return Py_None;
2664}
2665
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002666static PyObject *
2667Tkapp_WillDispatch(PyObject *self, PyObject *args)
2668{
2669
2670 ((TkappObject*)self)->dispatching = 1;
2671
2672 Py_INCREF(Py_None);
2673 return Py_None;
2674}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002675
Barry Warsawfa701a81997-01-16 00:15:11 +00002676
Guido van Rossum18468821994-06-20 07:49:28 +00002677/**** Tkapp Method List ****/
2678
2679static PyMethodDef Tkapp_methods[] =
2680{
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002681 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
Martin v. Löwisffad6332002-11-26 09:28:05 +00002682 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002683 {"call", Tkapp_Call, METH_OLDARGS},
2684 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2685 {"eval", Tkapp_Eval, METH_VARARGS},
2686 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2687 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2688 {"record", Tkapp_Record, METH_VARARGS},
2689 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2690 {"setvar", Tkapp_SetVar, METH_VARARGS},
2691 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2692 {"getvar", Tkapp_GetVar, METH_VARARGS},
2693 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2694 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2695 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2696 {"getint", Tkapp_GetInt, METH_VARARGS},
2697 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2698 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2699 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2700 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2701 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2702 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2703 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2704 {"split", Tkapp_Split, METH_VARARGS},
2705 {"merge", Tkapp_Merge, METH_OLDARGS},
2706 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2707 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002708#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002709 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2710 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002711#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002712 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2713 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2714 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2715 {"quit", Tkapp_Quit, METH_VARARGS},
2716 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
Neal Norwitz44dbae82004-02-19 02:44:22 +00002717 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Barry Warsawfa701a81997-01-16 00:15:11 +00002718 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002719};
2720
Barry Warsawfa701a81997-01-16 00:15:11 +00002721
2722
Guido van Rossum18468821994-06-20 07:49:28 +00002723/**** Tkapp Type Methods ****/
2724
2725static void
Fred Drake509d79a2000-07-08 04:04:38 +00002726Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002727{
Martin v. Löwisba2f8752002-12-31 17:34:30 +00002728 /*CHECK_TCL_APPARTMENT;*/
Guido van Rossum00d93061998-05-28 23:06:38 +00002729 ENTER_TCL
Guido van Rossum35d43371997-08-02 00:09:09 +00002730 Tcl_DeleteInterp(Tkapp_Interp(self));
Guido van Rossum00d93061998-05-28 23:06:38 +00002731 LEAVE_TCL
Guido van Rossumb18618d2000-05-03 23:44:39 +00002732 PyObject_Del(self);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002733 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002734}
2735
2736static PyObject *
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002737Tkapp_GetAttr(PyObject *self, const char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002738{
Guido van Rossum35d43371997-08-02 00:09:09 +00002739 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002740}
2741
2742static PyTypeObject Tkapp_Type =
2743{
Guido van Rossum35d43371997-08-02 00:09:09 +00002744 PyObject_HEAD_INIT(NULL)
Barry Warsawfa701a81997-01-16 00:15:11 +00002745 0, /*ob_size */
2746 "tkapp", /*tp_name */
Guido van Rossum35d43371997-08-02 00:09:09 +00002747 sizeof(TkappObject), /*tp_basicsize */
Barry Warsawfa701a81997-01-16 00:15:11 +00002748 0, /*tp_itemsize */
2749 Tkapp_Dealloc, /*tp_dealloc */
2750 0, /*tp_print */
2751 Tkapp_GetAttr, /*tp_getattr */
2752 0, /*tp_setattr */
2753 0, /*tp_compare */
2754 0, /*tp_repr */
2755 0, /*tp_as_number */
2756 0, /*tp_as_sequence */
2757 0, /*tp_as_mapping */
2758 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002759};
2760
Barry Warsawfa701a81997-01-16 00:15:11 +00002761
2762
Guido van Rossum18468821994-06-20 07:49:28 +00002763/**** Tkinter Module ****/
2764
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002765typedef struct {
2766 PyObject* tuple;
2767 int size; /* current size */
2768 int maxsize; /* allocated size */
2769} FlattenContext;
2770
2771static int
2772_bump(FlattenContext* context, int size)
2773{
Guido van Rossum2834b972000-10-06 16:58:26 +00002774 /* expand tuple to hold (at least) size new items.
2775 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002776
2777 int maxsize = context->maxsize * 2;
2778
2779 if (maxsize < context->size + size)
2780 maxsize = context->size + size;
2781
2782 context->maxsize = maxsize;
2783
Tim Peters4324aa32001-05-28 22:30:08 +00002784 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785}
2786
2787static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002788_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789{
2790 /* add tuple or list to argument tuple (recursively) */
2791
2792 int i, size;
2793
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002794 if (depth > 1000) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002795 PyErr_SetString(PyExc_ValueError,
2796 "nesting too deep in _flatten");
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002797 return 0;
2798 } else if (PyList_Check(item)) {
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002799 size = PyList_GET_SIZE(item);
2800 /* preallocate (assume no nesting) */
Guido van Rossum2834b972000-10-06 16:58:26 +00002801 if (context->size + size > context->maxsize &&
2802 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002803 return 0;
2804 /* copy items to output tuple */
2805 for (i = 0; i < size; i++) {
2806 PyObject *o = PyList_GET_ITEM(item, i);
2807 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002808 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002809 return 0;
2810 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002811 if (context->size + 1 > context->maxsize &&
2812 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002813 return 0;
2814 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002815 PyTuple_SET_ITEM(context->tuple,
2816 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002817 }
2818 }
2819 } else if (PyTuple_Check(item)) {
2820 /* same, for tuples */
2821 size = PyTuple_GET_SIZE(item);
Guido van Rossum2834b972000-10-06 16:58:26 +00002822 if (context->size + size > context->maxsize &&
2823 !_bump(context, size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002824 return 0;
2825 for (i = 0; i < size; i++) {
2826 PyObject *o = PyTuple_GET_ITEM(item, i);
2827 if (PyList_Check(o) || PyTuple_Check(o)) {
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002828 if (!_flatten1(context, o, depth + 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002829 return 0;
2830 } else if (o != Py_None) {
Guido van Rossum2834b972000-10-06 16:58:26 +00002831 if (context->size + 1 > context->maxsize &&
2832 !_bump(context, 1))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002833 return 0;
2834 Py_INCREF(o);
Guido van Rossum2834b972000-10-06 16:58:26 +00002835 PyTuple_SET_ITEM(context->tuple,
2836 context->size++, o);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002837 }
2838 }
2839 } else {
2840 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2841 return 0;
2842 }
2843 return 1;
2844}
2845
2846static PyObject *
2847Tkinter_Flatten(PyObject* self, PyObject* args)
2848{
2849 FlattenContext context;
2850 PyObject* item;
2851
2852 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2853 return NULL;
2854
Jeremy Hylton03657cf2000-07-12 13:05:33 +00002855 context.maxsize = PySequence_Size(item);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002856 if (context.maxsize <= 0)
2857 return PyTuple_New(0);
2858
2859 context.tuple = PyTuple_New(context.maxsize);
2860 if (!context.tuple)
2861 return NULL;
2862
2863 context.size = 0;
2864
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002865 if (!_flatten1(&context, item,0))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002866 return NULL;
2867
Tim Peters4324aa32001-05-28 22:30:08 +00002868 if (_PyTuple_Resize(&context.tuple, context.size))
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002869 return NULL;
2870
2871 return context.tuple;
2872}
2873
Guido van Rossum18468821994-06-20 07:49:28 +00002874static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002875Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002876{
Barry Warsawfa701a81997-01-16 00:15:11 +00002877 char *screenName = NULL;
2878 char *baseName = NULL;
2879 char *className = NULL;
2880 int interactive = 0;
Martin v. Löwis8c8aa5d2002-11-26 21:39:48 +00002881 int wantobjects = 0;
David Aschere2b4b322004-02-18 05:59:53 +00002882 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002883 int sync = 0; /* pass -sync to wish */
2884 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002885
Guido van Rossum35d43371997-08-02 00:09:09 +00002886 baseName = strrchr(Py_GetProgramName(), '/');
Barry Warsawfa701a81997-01-16 00:15:11 +00002887 if (baseName != NULL)
2888 baseName++;
2889 else
2890 baseName = Py_GetProgramName();
2891 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002892
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002893 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
Barry Warsawfa701a81997-01-16 00:15:11 +00002894 &screenName, &baseName, &className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002895 &interactive, &wantobjects, &wantTk,
2896 &sync, &use))
Barry Warsawfa701a81997-01-16 00:15:11 +00002897 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002898
Barry Warsawfa701a81997-01-16 00:15:11 +00002899 return (PyObject *) Tkapp_New(screenName, baseName, className,
Martin v. Löwis1fa649f2004-08-03 18:45:31 +00002900 interactive, wantobjects, wantTk,
2901 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002902}
2903
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002904static PyObject *
2905Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2906{
2907 int new_val;
2908 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2909 return NULL;
2910 if (new_val < 0) {
2911 PyErr_SetString(PyExc_ValueError,
2912 "busywaitinterval must be >= 0");
2913 return NULL;
2914 }
2915 Tkinter_busywaitinterval = new_val;
2916 Py_INCREF(Py_None);
2917 return Py_None;
2918}
2919
2920static char setbusywaitinterval_doc[] =
2921"setbusywaitinterval(n) -> None\n\
2922\n\
2923Set the busy-wait interval in milliseconds between successive\n\
2924calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2925It should be set to a divisor of the maximum time between\n\
2926frames in an animation.";
2927
2928static PyObject *
2929Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2930{
2931 return PyInt_FromLong(Tkinter_busywaitinterval);
2932}
2933
2934static char getbusywaitinterval_doc[] =
2935"getbusywaitinterval() -> int\n\
2936\n\
2937Return the current busy-wait interval between successive\n\
2938calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2939
Guido van Rossum18468821994-06-20 07:49:28 +00002940static PyMethodDef moduleMethods[] =
2941{
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002942 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2943 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002944#ifdef HAVE_CREATEFILEHANDLER
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002945 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2946 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002947#endif
Martin v. Löwis43b936d2002-01-17 23:15:58 +00002948 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2949 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2950 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2951 {"quit", Tkapp_Quit, METH_VARARGS},
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002952 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2953 setbusywaitinterval_doc},
2954 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2955 METH_NOARGS, getbusywaitinterval_doc},
Barry Warsawfa701a81997-01-16 00:15:11 +00002956 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002957};
2958
Guido van Rossum7bf15641998-05-22 18:28:17 +00002959#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002960
2961static int stdin_ready = 0;
2962
Guido van Rossumad4db171998-06-13 13:56:28 +00002963#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002964static void
Fred Drake509d79a2000-07-08 04:04:38 +00002965MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002966{
2967 stdin_ready = 1;
2968}
Guido van Rossumad4db171998-06-13 13:56:28 +00002969#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002970
Martin v. Löwisa9656492003-03-30 08:44:58 +00002971#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002972static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002973#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002974
Guido van Rossum18468821994-06-20 07:49:28 +00002975static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002976EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002977{
Guido van Rossumad4db171998-06-13 13:56:28 +00002978#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002979 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00002980#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002981#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00002982 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00002983#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984 stdin_ready = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00002985 errorInCmd = 0;
2986#ifndef MS_WINDOWS
Guido van Rossuma80649b2000-03-28 20:07:05 +00002987 tfile = fileno(stdin);
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002990 while (!errorInCmd && !stdin_ready) {
2991 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00002992#ifdef MS_WINDOWS
2993 if (_kbhit()) {
2994 stdin_ready = 1;
2995 break;
2996 }
2997#endif
2998#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Guido van Rossum62320c91998-06-15 04:36:09 +00002999 Py_BEGIN_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003000 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
Guido van Rossum41f0a981998-10-12 16:26:22 +00003001 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003002
Guido van Rossum00d93061998-05-28 23:06:38 +00003003 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003004
3005 tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003006 if(tcl_lock)PyThread_release_lock(tcl_lock);
Guido van Rossum00d93061998-05-28 23:06:38 +00003007 if (result == 0)
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003008 Sleep(Tkinter_busywaitinterval);
Guido van Rossum00d93061998-05-28 23:06:38 +00003009 Py_END_ALLOW_THREADS
3010#else
3011 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003012#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003013
3014 if (result < 0)
3015 break;
3016 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003017#ifndef MS_WINDOWS
Guido van Rossum00d93061998-05-28 23:06:38 +00003018 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003019#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003020 if (errorInCmd) {
3021 errorInCmd = 0;
3022 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3023 excInCmd = valInCmd = trbInCmd = NULL;
3024 PyErr_Print();
3025 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003026#ifdef WITH_THREAD
Guido van Rossumad4db171998-06-13 13:56:28 +00003027 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003028#endif
Barry Warsawfa701a81997-01-16 00:15:11 +00003029 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003030}
Guido van Rossum18468821994-06-20 07:49:28 +00003031
Guido van Rossum00d93061998-05-28 23:06:38 +00003032#endif
3033
Guido van Rossum7bf15641998-05-22 18:28:17 +00003034static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003035EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003036{
Guido van Rossum00d93061998-05-28 23:06:38 +00003037#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003038 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003039#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003040 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003041#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003042 PyOS_InputHook = EventHook;
3043 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003044#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003045}
3046
3047static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003048DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003049{
Guido van Rossum00d93061998-05-28 23:06:38 +00003050#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003051 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3052 PyOS_InputHook = NULL;
3053 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003054#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003055}
3056
Barry Warsawfa701a81997-01-16 00:15:11 +00003057
3058/* all errors will be checked in one fell swoop in init_tkinter() */
3059static void
Fred Drake509d79a2000-07-08 04:04:38 +00003060ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003061{
3062 PyObject *v = PyInt_FromLong(val);
3063 if (v) {
3064 PyDict_SetItemString(d, name, v);
3065 Py_DECREF(v);
3066 }
3067}
3068static void
Fred Drake509d79a2000-07-08 04:04:38 +00003069ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003070{
3071 PyObject *v = PyString_FromString(val);
3072 if (v) {
3073 PyDict_SetItemString(d, name, v);
3074 Py_DECREF(v);
3075 }
3076}
3077
3078
Mark Hammond62b1ab12002-07-23 06:31:15 +00003079PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003080init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003081{
Barry Warsawfa701a81997-01-16 00:15:11 +00003082 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003083
Barry Warsawfa701a81997-01-16 00:15:11 +00003084 Tkapp_Type.ob_type = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003085
3086#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +00003087 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003088#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003089
Barry Warsawfa701a81997-01-16 00:15:11 +00003090 m = Py_InitModule("_tkinter", moduleMethods);
Guido van Rossum18468821994-06-20 07:49:28 +00003091
Barry Warsawfa701a81997-01-16 00:15:11 +00003092 d = PyModule_GetDict(m);
Neal Norwitzb5b5a262002-06-04 17:14:07 +00003093 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
Barry Warsawfa701a81997-01-16 00:15:11 +00003094 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003095
Guido van Rossum35d43371997-08-02 00:09:09 +00003096 ins_long(d, "READABLE", TCL_READABLE);
3097 ins_long(d, "WRITABLE", TCL_WRITABLE);
3098 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3099 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3100 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3101 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3102 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3103 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3104 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
Barry Warsawfa701a81997-01-16 00:15:11 +00003105 ins_string(d, "TK_VERSION", TK_VERSION);
3106 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003107
Guido van Rossum83551bf1997-09-13 00:44:23 +00003108 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003109
3110 Tktt_Type.ob_type = &PyType_Type;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003111 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3112
Martin v. Löwisffad6332002-11-26 09:28:05 +00003113 PyTclObject_Type.ob_type = &PyType_Type;
3114 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003115
3116#ifdef TK_AQUA
3117 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3118 * start waking up. Note that Tcl_FindExecutable will do this, this
3119 * code must be above it! The original warning from
3120 * tkMacOSXAppInit.c is copied below.
3121 *
3122 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3123 * Tcl interpreter for now. It probably should work to do this
3124 * in the other order, but for now it doesn't seem to.
3125 *
3126 */
3127 Tk_MacOSXSetupTkNotifier();
3128#endif
3129
3130
Guido van Rossume187b0e2000-03-27 21:46:29 +00003131 /* This helps the dynamic loader; in Unicode aware Tcl versions
3132 it also helps Tcl find its encodings. */
3133 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003134
Barry Warsawfa701a81997-01-16 00:15:11 +00003135 if (PyErr_Occurred())
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003136 return;
3137
Guido van Rossum43ff8681998-07-14 18:02:13 +00003138#if 0
3139 /* This was not a good idea; through <Destroy> bindings,
3140 Tcl_Finalize() may invoke Python code but at that point the
3141 interpreter and thread state have already been destroyed! */
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003142 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003143#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003144
Guido van Rossum18468821994-06-20 07:49:28 +00003145}