blob: b8929b611f7080bb85f328c4f06acd0f4ac021aa [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
14 libraries.)
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000088 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000207 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000208
209#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219
220#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Christian Heimese93237d2007-12-19 02:37:44 +0000265#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000270(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000284
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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
308 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);
Guido van Rossum00d93061998-05-28 23:06:38 +0000311}
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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000319 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;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000338 if (PyString_Check(value))
339 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000340#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000353 else {
354 PyObject *v = PyObject_Str(value);
355 if (v == NULL)
356 return NULL;
357 if (PyList_Append(tmp, v) != 0) {
358 Py_DECREF(v);
359 return NULL;
360 }
361 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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000367
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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000373 PyObject *tmp = NULL;
374 char *argvStore[ARGSZ];
375 char **argv = NULL;
376 int fvStore[ARGSZ];
377 int *fv = NULL;
378 int argc = 0, fvc = 0, i;
379 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000380
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000381 if (!(tmp = PyList_New(0)))
382 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000384 argv = argvStore;
385 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000387 if (args == NULL)
388 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000389
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000390 else if (!PyTuple_Check(args)) {
391 argc = 1;
392 fv[0] = 0;
393 if (!(argv[0] = AsString(args, tmp)))
394 goto finally;
395 }
396 else {
397 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000398
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000399 if (argc > ARGSZ) {
400 argv = (char **)ckalloc(argc * sizeof(char *));
401 fv = (int *)ckalloc(argc * sizeof(int));
402 if (argv == NULL || fv == NULL) {
403 PyErr_NoMemory();
404 goto finally;
405 }
406 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000407
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000408 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;
414 fvc++;
415 }
416 else if (v == Py_None) {
417 argc = i;
418 break;
419 }
420 else {
421 fv[i] = 0;
422 if (!(argv[i] = AsString(v, tmp)))
423 goto finally;
424 fvc++;
425 }
426 }
427 }
428 res = Tcl_Merge(argc, argv);
429 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:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000433 for (i = 0; i < fvc; i++)
434 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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000447
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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000451 int argc;
452 char **argv;
453 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000454
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000455 if (list == NULL) {
456 Py_INCREF(Py_None);
457 return Py_None;
458 }
Guido van Rossum18468821994-06-20 07:49:28 +0000459
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000460 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
461 /* Not a list.
462 * Could be a quoted string containing funnies, e.g. {"}.
463 * Return the string itself.
464 */
465 return PyString_FromString(list);
466 }
Guido van Rossum18468821994-06-20 07:49:28 +0000467
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000468 if (argc == 0)
469 v = PyString_FromString("");
470 else if (argc == 1)
471 v = PyString_FromString(argv[0]);
472 else if ((v = PyTuple_New(argc)) != NULL) {
473 int i;
474 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000475
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000476 for (i = 0; i < argc; i++) {
477 if ((w = Split(argv[i])) == NULL) {
478 Py_DECREF(v);
479 v = NULL;
480 break;
481 }
482 PyTuple_SetItem(v, i, w);
483 }
484 }
485 Tcl_Free(FREECAST argv);
486 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
Martin v. Löwis111c1802008-06-13 07:47:47 +0000493static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000494SplitObj(PyObject *arg)
495{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000496 if (PyTuple_Check(arg)) {
497 int i, size;
498 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000499
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000500 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);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000537
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000538 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;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000549}
Barry Warsawfa701a81997-01-16 00:15:11 +0000550
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000551
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{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000558 Tk_Window main;
559 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000560
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000561 if (Tcl_Init(interp) == TCL_ERROR) {
562 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
563 return TCL_ERROR;
564 }
565 _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 }
572 }
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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000578
Barry Warsawfa701a81997-01-16 00:15:11 +0000579
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,
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000589 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000590{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000591 TkappObject *v;
592 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000593
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000594 v = PyObject_New(TkappObject, &Tkapp_Type);
595 if (v == NULL)
596 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000597
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000598 v->interp = Tcl_CreateInterp();
599 v->wantobjects = wantobjects;
600 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
601 TCL_GLOBAL_ONLY) != NULL;
602 v->thread_id = Tcl_GetCurrentThread();
603 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000604
605#ifndef TCL_THREADS
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000606 if (v->threaded) {
607 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
608 Py_DECREF(v);
609 return 0;
610 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000611#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000612#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000627
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000628 /* Delete the 'exit' command, which can screw things up */
629 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000630
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +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
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000648 strcpy(argv0, className);
649 if (isupper(Py_CHARMASK(argv0[0])))
650 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
651 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
652 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000653
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000654 if (! wantTk) {
655 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
656 }
David Aschere2b4b322004-02-18 05:59:53 +0000657
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000658 /* some initial arguments need to be in argv */
659 if (sync || use) {
660 char *args;
661 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000662
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000663 if (sync)
664 len += sizeof "-sync";
665 if (use)
666 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000668 args = (char*)ckalloc(len);
669 if (!args) {
670 PyErr_NoMemory();
671 Py_DECREF(v);
672 return NULL;
673 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000674
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000675 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 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000684
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000685 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
686 ckfree(args);
687 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000688
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000689 if (Tcl_AppInit(v->interp) != TCL_OK) {
690 PyObject *result = Tkinter_Error((PyObject *)v);
691 Py_DECREF((PyObject *)v);
692 return (TkappObject *)result;
693 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000694
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000695 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000696
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000697 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000698}
699
Barry Warsawfa701a81997-01-16 00:15:11 +0000700
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000701static void
702Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000703 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000705 Py_BEGIN_ALLOW_THREADS;
706 Tcl_MutexLock(mutex);
707 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
708 Tcl_ThreadAlert(self->thread_id);
709 Tcl_ConditionWait(cond, mutex, NULL);
710 Tcl_MutexUnlock(mutex);
711 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712}
713
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000714
Guido van Rossum18468821994-06-20 07:49:28 +0000715/** Tcl Eval **/
716
Martin v. Löwisffad6332002-11-26 09:28:05 +0000717typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000718 PyObject_HEAD
719 Tcl_Obj *value;
720 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000721} PyTclObject;
722
723staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000724#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000725
726static PyObject *
727newPyTclObject(Tcl_Obj *arg)
728{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000729 PyTclObject *self;
730 self = PyObject_New(PyTclObject, &PyTclObject_Type);
731 if (self == NULL)
732 return NULL;
733 Tcl_IncrRefCount(arg);
734 self->value = arg;
735 self->string = NULL;
736 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000737}
738
739static void
740PyTclObject_dealloc(PyTclObject *self)
741{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000742 Tcl_DecrRefCount(self->value);
743 Py_XDECREF(self->string);
744 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000745}
746
747static PyObject *
748PyTclObject_str(PyTclObject *self)
749{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000750 if (self->string && PyString_Check(self->string)) {
751 Py_INCREF(self->string);
752 return self->string;
753 }
754 /* XXX Could cache value if it is an ASCII string. */
755 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000756}
757
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000758static char*
759PyTclObject_TclString(PyObject *self)
760{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000761 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000762}
763
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000764/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000765PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000766"the string representation of this object, either as string or Unicode");
767
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000768static PyObject *
769PyTclObject_string(PyTclObject *self, void *ignored)
770{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000771 char *s;
772 int i, len;
773 if (!self->string) {
774 s = Tcl_GetStringFromObj(self->value, &len);
775 for (i = 0; i < len; i++)
776 if (s[i] & 0x80)
777 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000778#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000779 if (i == len)
780 /* It is an ASCII string. */
781 self->string = PyString_FromStringAndSize(s, len);
782 else {
783 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
784 if (!self->string) {
785 PyErr_Clear();
786 self->string = PyString_FromStringAndSize(s, len);
787 }
788 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000789#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000790 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000791#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000792 if (!self->string)
793 return NULL;
794 }
795 Py_INCREF(self->string);
796 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000797}
798
799#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000800PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
801
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000802static PyObject *
803PyTclObject_unicode(PyTclObject *self, void *ignored)
804{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000805 char *s;
806 int len;
807 if (self->string && PyUnicode_Check(self->string)) {
808 Py_INCREF(self->string);
809 return self->string;
810 }
811 /* XXX Could chache result if it is non-ASCII. */
812 s = Tcl_GetStringFromObj(self->value, &len);
813 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000814}
815#endif
816
Martin v. Löwisffad6332002-11-26 09:28:05 +0000817static PyObject *
818PyTclObject_repr(PyTclObject *self)
819{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000820 char buf[50];
821 PyOS_snprintf(buf, 50, "<%s object at %p>",
822 self->value->typePtr->name, self->value);
823 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000824}
825
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000826static int
827PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
828{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000829 int res;
830 res = strcmp(Tcl_GetString(self->value),
831 Tcl_GetString(other->value));
832 if (res < 0) return -1;
833 if (res > 0) return 1;
834 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000835}
836
Martin v. Löwis39195712003-01-04 00:33:13 +0000837PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
838
Martin v. Löwisffad6332002-11-26 09:28:05 +0000839static PyObject*
840get_typename(PyTclObject* obj, void* ignored)
841{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000842 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000843}
844
Martin v. Löwis39195712003-01-04 00:33:13 +0000845
Martin v. Löwisffad6332002-11-26 09:28:05 +0000846static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000847 {"typename", (getter)get_typename, NULL, get_typename__doc__},
848 {"string", (getter)PyTclObject_string, NULL,
849 PyTclObject_string__doc__},
850 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000851};
852
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000853static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000854#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000855 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
856 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000857#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000858 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000859};
860
Martin v. Löwisffad6332002-11-26 09:28:05 +0000861statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000862 PyObject_HEAD_INIT(NULL)
863 0, /*ob_size*/
864 "_tkinter.Tcl_Obj", /*tp_name*/
865 sizeof(PyTclObject), /*tp_basicsize*/
866 0, /*tp_itemsize*/
867 /* methods */
868 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
869 0, /*tp_print*/
870 0, /*tp_getattr*/
871 0, /*tp_setattr*/
872 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
873 (reprfunc)PyTclObject_repr, /*tp_repr*/
874 0, /*tp_as_number*/
875 0, /*tp_as_sequence*/
876 0, /*tp_as_mapping*/
877 0, /*tp_hash*/
878 0, /*tp_call*/
879 (reprfunc)PyTclObject_str, /*tp_str*/
880 PyObject_GenericGetAttr,/*tp_getattro*/
881 0, /*tp_setattro*/
882 0, /*tp_as_buffer*/
883 Py_TPFLAGS_DEFAULT, /*tp_flags*/
884 0, /*tp_doc*/
885 0, /*tp_traverse*/
886 0, /*tp_clear*/
887 0, /*tp_richcompare*/
888 0, /*tp_weaklistoffset*/
889 0, /*tp_iter*/
890 0, /*tp_iternext*/
891 PyTclObject_methods, /*tp_methods*/
892 0, /*tp_members*/
893 PyTclObject_getsetlist, /*tp_getset*/
894 0, /*tp_base*/
895 0, /*tp_dict*/
896 0, /*tp_descr_get*/
897 0, /*tp_descr_set*/
898 0, /*tp_dictoffset*/
899 0, /*tp_init*/
900 0, /*tp_alloc*/
901 0, /*tp_new*/
902 0, /*tp_free*/
903 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904};
905
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000906static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000907AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000908{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000909 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000910
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000911 if (PyString_Check(value))
912 return Tcl_NewStringObj(PyString_AS_STRING(value),
913 PyString_GET_SIZE(value));
914 else if (PyBool_Check(value))
915 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
916 else if (PyInt_Check(value))
917 return Tcl_NewLongObj(PyInt_AS_LONG(value));
918 else if (PyFloat_Check(value))
919 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
920 else if (PyTuple_Check(value)) {
921 Tcl_Obj **argv = (Tcl_Obj**)
922 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
923 int i;
924 if(!argv)
925 return 0;
926 for(i=0;i<PyTuple_Size(value);i++)
927 argv[i] = AsObj(PyTuple_GetItem(value,i));
928 result = Tcl_NewListObj(PyTuple_Size(value), argv);
929 ckfree(FREECAST argv);
930 return result;
931 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000932#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000933 else if (PyUnicode_Check(value)) {
934 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
935 Py_ssize_t size = PyUnicode_GET_SIZE(value);
936 /* This #ifdef assumes that Tcl uses UCS-2.
937 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000938#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000939 Tcl_UniChar *outbuf = NULL;
940 Py_ssize_t i;
941 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
942 if (allocsize >= size)
943 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
944 /* Else overflow occurred, and we take the next exit */
945 if (!outbuf) {
946 PyErr_NoMemory();
947 return NULL;
948 }
949 for (i = 0; i < size; i++) {
950 if (inbuf[i] >= 0x10000) {
951 /* Tcl doesn't do UTF-16, yet. */
952 PyErr_SetString(PyExc_ValueError,
953 "unsupported character");
954 ckfree(FREECAST outbuf);
955 return NULL;
956 }
957 outbuf[i] = inbuf[i];
958 }
959 result = Tcl_NewUnicodeObj(outbuf, size);
960 ckfree(FREECAST outbuf);
961 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000962#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000963 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +0000964#endif
965
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000966 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000967#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000968 else if(PyTclObject_Check(value)) {
969 Tcl_Obj *v = ((PyTclObject*)value)->value;
970 Tcl_IncrRefCount(v);
971 return v;
972 }
973 else {
974 PyObject *v = PyObject_Str(value);
975 if (!v)
976 return 0;
977 result = AsObj(v);
978 Py_DECREF(v);
979 return result;
980 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000981}
982
Martin v. Löwisffad6332002-11-26 09:28:05 +0000983static PyObject*
984FromObj(PyObject* tkapp, Tcl_Obj *value)
985{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000986 PyObject *result = NULL;
987 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000988
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000989 if (value->typePtr == NULL) {
990 /* If the result contains any bytes with the top bit set,
991 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +0000992#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +0000993 int i;
994 char *s = value->bytes;
995 int len = value->length;
996 for (i = 0; i < len; i++) {
997 if (value->bytes[i] & 0x80)
998 break;
999 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001000
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001001 if (i == value->length)
1002 result = PyString_FromStringAndSize(s, len);
1003 else {
1004 /* Convert UTF-8 to Unicode string */
1005 result = PyUnicode_DecodeUTF8(s, len, "strict");
1006 if (result == NULL) {
1007 PyErr_Clear();
1008 result = PyString_FromStringAndSize(s, len);
1009 }
1010 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001011#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001012 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001013#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001014 return result;
1015 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001016
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001017 if (value->typePtr == app->BooleanType) {
1018 result = value->internalRep.longValue ? Py_True : Py_False;
1019 Py_INCREF(result);
1020 return result;
1021 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001023 if (value->typePtr == app->ByteArrayType) {
1024 int size;
1025 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1026 return PyString_FromStringAndSize(data, size);
1027 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001028
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001029 if (value->typePtr == app->DoubleType) {
1030 return PyFloat_FromDouble(value->internalRep.doubleValue);
1031 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001032
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001033 if (value->typePtr == app->IntType) {
1034 return PyInt_FromLong(value->internalRep.longValue);
1035 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001037 if (value->typePtr == app->ListType) {
1038 int size;
1039 int i, status;
1040 PyObject *elem;
1041 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001042
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001043 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1044 if (status == TCL_ERROR)
1045 return Tkinter_Error(tkapp);
1046 result = PyTuple_New(size);
1047 if (!result)
1048 return NULL;
1049 for (i = 0; i < size; i++) {
1050 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1051 value, i, &tcl_elem);
1052 if (status == TCL_ERROR) {
1053 Py_DECREF(result);
1054 return Tkinter_Error(tkapp);
1055 }
1056 elem = FromObj(tkapp, tcl_elem);
1057 if (!elem) {
1058 Py_DECREF(result);
1059 return NULL;
1060 }
1061 PyTuple_SetItem(result, i, elem);
1062 }
1063 return result;
1064 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001065
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001066 if (value->typePtr == app->ProcBodyType) {
1067 /* fall through: return tcl object. */
1068 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001069
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001070 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001071#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001072#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001073 PyObject *result;
1074 int size;
1075 Tcl_UniChar *input;
1076 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001077
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001078 size = Tcl_GetCharLength(value);
1079 result = PyUnicode_FromUnicode(NULL, size);
1080 if (!result)
1081 return NULL;
1082 input = Tcl_GetUnicode(value);
1083 output = PyUnicode_AS_UNICODE(result);
1084 while (size--)
1085 *output++ = *input++;
1086 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001087#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001088 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1089 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001090#endif
1091#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001092 int size;
1093 char *c;
1094 c = Tcl_GetStringFromObj(value, &size);
1095 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001096#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001097 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001098
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001099 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001100}
1101
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001102/* This mutex synchronizes inter-thread command calls. */
1103
1104TCL_DECLARE_MUTEX(call_mutex)
1105
1106typedef struct Tkapp_CallEvent {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001107 Tcl_Event ev; /* Must be first */
1108 TkappObject *self;
1109 PyObject *args;
1110 int flags;
1111 PyObject **res;
1112 PyObject **exc_type, **exc_value, **exc_tb;
1113 Tcl_Condition done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001114} Tkapp_CallEvent;
1115
1116void
1117Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001118{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001119 int i;
1120 for (i = 0; i < objc; i++)
1121 Tcl_DecrRefCount(objv[i]);
1122 if (objv != objStore)
1123 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124}
Guido van Rossum18468821994-06-20 07:49:28 +00001125
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001126/* Convert Python objects to Tcl objects. This must happen in the
1127 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001128
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001129static Tcl_Obj**
1130Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1131{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001132 Tcl_Obj **objv = objStore;
1133 int objc = 0, i;
1134 if (args == NULL)
1135 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001136
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001137 else if (!PyTuple_Check(args)) {
1138 objv[0] = AsObj(args);
1139 if (objv[0] == 0)
1140 goto finally;
1141 objc = 1;
1142 Tcl_IncrRefCount(objv[0]);
1143 }
1144 else {
1145 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001146
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001147 if (objc > ARGSZ) {
1148 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1149 if (objv == NULL) {
1150 PyErr_NoMemory();
1151 objc = 0;
1152 goto finally;
1153 }
1154 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001155
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001156 for (i = 0; i < objc; i++) {
1157 PyObject *v = PyTuple_GetItem(args, i);
1158 if (v == Py_None) {
1159 objc = i;
1160 break;
1161 }
1162 objv[i] = AsObj(v);
1163 if (!objv[i]) {
1164 /* Reset objc, so it attempts to clear
1165 objects only up to i. */
1166 objc = i;
1167 goto finally;
1168 }
1169 Tcl_IncrRefCount(objv[i]);
1170 }
1171 }
1172 *pobjc = objc;
1173 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001174finally:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001175 Tkapp_CallDeallocArgs(objv, objStore, objc);
1176 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001177}
Guido van Rossum212643f1998-04-29 16:22:14 +00001178
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001179/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001180
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181static PyObject*
1182Tkapp_CallResult(TkappObject *self)
1183{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001184 PyObject *res = NULL;
1185 if(self->wantobjects) {
1186 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1187 /* Not sure whether the IncrRef is necessary, but something
1188 may overwrite the interpreter result while we are
1189 converting it. */
1190 Tcl_IncrRefCount(value);
1191 res = FromObj((PyObject*)self, value);
1192 Tcl_DecrRefCount(value);
1193 } else {
1194 const char *s = Tcl_GetStringResult(self->interp);
1195 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001196
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001197 /* If the result contains any bytes with the top bit set,
1198 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001199#ifdef Py_USING_UNICODE
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001200 while (*p != '\0') {
1201 if (*p & 0x80)
1202 break;
1203 p++;
1204 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001205
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001206 if (*p == '\0')
1207 res = PyString_FromStringAndSize(s, (int)(p-s));
1208 else {
1209 /* Convert UTF-8 to Unicode string */
1210 p = strchr(p, '\0');
1211 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1212 if (res == NULL) {
1213 PyErr_Clear();
1214 res = PyString_FromStringAndSize(s, (int)(p-s));
1215 }
1216 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001217#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001218 p = strchr(p, '\0');
1219 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001220#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001221 }
1222 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223}
Guido van Rossum632de272000-03-29 00:19:50 +00001224
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001225/* Tkapp_CallProc is the event procedure that is executed in the context of
1226 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1227 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001228
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001229static int
1230Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1231{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001232 Tcl_Obj *objStore[ARGSZ];
1233 Tcl_Obj **objv;
1234 int objc;
1235 int i;
1236 ENTER_PYTHON
1237 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1238 if (!objv) {
1239 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1240 *(e->res) = NULL;
1241 }
1242 LEAVE_PYTHON
1243 if (!objv)
1244 goto done;
1245 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1246 ENTER_PYTHON
1247 if (i == TCL_ERROR) {
1248 *(e->res) = NULL;
1249 *(e->exc_type) = NULL;
1250 *(e->exc_tb) = NULL;
1251 *(e->exc_value) = PyObject_CallFunction(
1252 Tkinter_TclError, "s",
1253 Tcl_GetStringResult(e->self->interp));
1254 }
1255 else {
1256 *(e->res) = Tkapp_CallResult(e->self);
1257 }
1258 LEAVE_PYTHON
Guilherme Poloc8a20da2009-02-06 22:52:31 +00001259
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001260 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Poloc8a20da2009-02-06 22:52:31 +00001261done:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001262 /* Wake up calling thread. */
1263 Tcl_MutexLock(&call_mutex);
1264 Tcl_ConditionNotify(&e->done);
1265 Tcl_MutexUnlock(&call_mutex);
1266 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001267}
1268
1269/* This is the main entry point for calling a Tcl command.
1270 It supports three cases, with regard to threading:
1271 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1272 the context of the calling thread.
1273 2. Tcl is threaded, caller of the command is in the interpreter thread:
1274 Execute the command in the calling thread. Since the Tcl lock will
1275 not be used, we can merge that with case 1.
1276 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1277 the interpreter thread. Allocation of Tcl objects needs to occur in the
1278 interpreter thread, so we ship the PyObject* args to the target thread,
1279 and perform processing there. */
1280
1281static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001282Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001283{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001284 Tcl_Obj *objStore[ARGSZ];
1285 Tcl_Obj **objv = NULL;
1286 int objc, i;
1287 PyObject *res = NULL;
1288 TkappObject *self = (TkappObject*)selfptr;
1289 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001291 /* If args is a single tuple, replace with contents of tuple */
1292 if (1 == PyTuple_Size(args)){
1293 PyObject* item = PyTuple_GetItem(args, 0);
1294 if (PyTuple_Check(item))
1295 args = item;
1296 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001297#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001298 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1299 /* We cannot call the command directly. Instead, we must
1300 marshal the parameters to the interpreter thread. */
1301 Tkapp_CallEvent *ev;
1302 PyObject *exc_type, *exc_value, *exc_tb;
1303 if (!WaitForMainloop(self))
1304 return NULL;
1305 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1306 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1307 ev->self = self;
1308 ev->args = args;
1309 ev->res = &res;
1310 ev->exc_type = &exc_type;
1311 ev->exc_value = &exc_value;
1312 ev->exc_tb = &exc_tb;
1313 ev->done = (Tcl_Condition)0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001315 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001317 if (res == NULL) {
1318 if (exc_type)
1319 PyErr_Restore(exc_type, exc_value, exc_tb);
1320 else
1321 PyErr_SetObject(Tkinter_TclError, exc_value);
1322 }
1323 }
1324 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001325#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001326 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001328 objv = Tkapp_CallArgs(args, objStore, &objc);
1329 if (!objv)
1330 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001332 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001333
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001334 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001336 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001337
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001338 if (i == TCL_ERROR)
1339 Tkinter_Error(selfptr);
1340 else
1341 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001343 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001344
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001345 Tkapp_CallDeallocArgs(objv, objStore, objc);
1346 }
1347 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001348}
1349
1350
1351static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001352Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001353{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001354 /* Could do the same here as for Tkapp_Call(), but this is not used
1355 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1356 way for the user to do what all its Global* variants do (save and
1357 reset the scope pointer, call the local version, restore the saved
1358 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001359
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001360 char *cmd;
1361 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001362
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001363 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001365 cmd = Merge(args);
1366 if (cmd) {
1367 int err;
1368 ENTER_TCL
1369 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1370 ENTER_OVERLAP
1371 if (err == TCL_ERROR)
1372 res = Tkinter_Error(self);
1373 else
1374 res = PyString_FromString(Tkapp_Result(self));
1375 LEAVE_OVERLAP_TCL
1376 ckfree(cmd);
1377 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001378
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001379 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001380}
1381
1382static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001383Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001384{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001385 char *script;
1386 PyObject *res = NULL;
1387 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001389 if (!PyArg_ParseTuple(args, "s:eval", &script))
1390 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001391
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001392 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001393
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001394 ENTER_TCL
1395 err = Tcl_Eval(Tkapp_Interp(self), script);
1396 ENTER_OVERLAP
1397 if (err == TCL_ERROR)
1398 res = Tkinter_Error(self);
1399 else
1400 res = PyString_FromString(Tkapp_Result(self));
1401 LEAVE_OVERLAP_TCL
1402 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001403}
1404
1405static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001406Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001407{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001408 char *script;
1409 PyObject *res = NULL;
1410 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001411
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001412 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1413 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001414
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001415 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001416
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001417 ENTER_TCL
1418 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1419 ENTER_OVERLAP
1420 if (err == TCL_ERROR)
1421 res = Tkinter_Error(self);
1422 else
1423 res = PyString_FromString(Tkapp_Result(self));
1424 LEAVE_OVERLAP_TCL
1425 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001426}
1427
1428static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001429Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001430{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001431 char *fileName;
1432 PyObject *res = NULL;
1433 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001434
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001435 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1436 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001437
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001438 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001440 ENTER_TCL
1441 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1442 ENTER_OVERLAP
1443 if (err == TCL_ERROR)
1444 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001445
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001446 else
1447 res = PyString_FromString(Tkapp_Result(self));
1448 LEAVE_OVERLAP_TCL
1449 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001450}
1451
1452static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001453Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001454{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001455 char *script;
1456 PyObject *res = NULL;
1457 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001458
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001459 if (!PyArg_ParseTuple(args, "s", &script))
1460 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001461
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001462 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001464 ENTER_TCL
1465 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1466 ENTER_OVERLAP
1467 if (err == TCL_ERROR)
1468 res = Tkinter_Error(self);
1469 else
1470 res = PyString_FromString(Tkapp_Result(self));
1471 LEAVE_OVERLAP_TCL
1472 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001473}
1474
1475static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001476Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001477{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001478 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001479
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001480 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1481 return NULL;
1482 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001484 ENTER_TCL
1485 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1486 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001487
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001488 Py_INCREF(Py_None);
1489 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001490}
1491
Barry Warsawfa701a81997-01-16 00:15:11 +00001492
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001493
Guido van Rossum18468821994-06-20 07:49:28 +00001494/** Tcl Variable **/
1495
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001496TCL_DECLARE_MUTEX(var_mutex)
1497
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001498typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499typedef struct VarEvent {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001500 Tcl_Event ev; /* must be first */
1501 PyObject *self;
1502 PyObject *args;
1503 int flags;
1504 EventFunc func;
1505 PyObject **res;
1506 PyObject **exc_type;
1507 PyObject **exc_val;
1508 Tcl_Condition cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509} VarEvent;
1510
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001511static int
1512varname_converter(PyObject *in, void *_out)
1513{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001514 char **out = (char**)_out;
1515 if (PyString_Check(in)) {
1516 *out = PyString_AsString(in);
1517 return 1;
1518 }
1519 if (PyTclObject_Check(in)) {
1520 *out = PyTclObject_TclString(in);
1521 return 1;
1522 }
1523 /* XXX: Should give diagnostics. */
1524 return 0;
1525}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001526
Martin v. Löwis111c1802008-06-13 07:47:47 +00001527static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528var_perform(VarEvent *ev)
1529{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001530 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1531 if (!*(ev->res)) {
1532 PyObject *exc, *val, *tb;
1533 PyErr_Fetch(&exc, &val, &tb);
1534 PyErr_NormalizeException(&exc, &val, &tb);
1535 *(ev->exc_type) = exc;
1536 *(ev->exc_val) = val;
1537 Py_DECREF(tb);
1538 }
1539
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540}
1541
1542static int
1543var_proc(VarEvent* ev, int flags)
1544{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001545 ENTER_PYTHON
1546 var_perform(ev);
1547 Tcl_MutexLock(&var_mutex);
1548 Tcl_ConditionNotify(&ev->cond);
1549 Tcl_MutexUnlock(&var_mutex);
1550 LEAVE_PYTHON
1551 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001552}
1553
1554static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001555var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001557 TkappObject *self = (TkappObject*)selfptr;
Martin v. Löwisa9656492003-03-30 08:44:58 +00001558#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001559 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1560 TkappObject *self = (TkappObject*)selfptr;
1561 VarEvent *ev;
1562 PyObject *res, *exc_type, *exc_val;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001563
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001564 /* The current thread is not the interpreter thread. Marshal
1565 the call to the interpreter thread, then wait for
1566 completion. */
1567 if (!WaitForMainloop(self))
1568 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001569
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001570 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1571
1572 ev->self = selfptr;
1573 ev->args = args;
1574 ev->flags = flags;
1575 ev->func = func;
1576 ev->res = &res;
1577 ev->exc_type = &exc_type;
1578 ev->exc_val = &exc_val;
1579 ev->cond = NULL;
1580 ev->ev.proc = (Tcl_EventProc*)var_proc;
1581 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1582 if (!res) {
1583 PyErr_SetObject(exc_type, exc_val);
1584 Py_DECREF(exc_type);
1585 Py_DECREF(exc_val);
1586 return NULL;
1587 }
1588 return res;
1589 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001590#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001591 /* Tcl is not threaded, or this is the interpreter thread. */
1592 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001593}
1594
Guido van Rossum18468821994-06-20 07:49:28 +00001595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001596SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001597{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001598 char *name1, *name2;
1599 PyObject *newValue;
1600 PyObject *res = NULL;
1601 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001602
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001603 if (PyArg_ParseTuple(args, "O&O:setvar",
1604 varname_converter, &name1, &newValue)) {
1605 /* XXX Acquire tcl lock??? */
1606 newval = AsObj(newValue);
1607 if (newval == NULL)
1608 return NULL;
1609 ENTER_TCL
1610 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1611 newval, flags);
1612 ENTER_OVERLAP
1613 if (!ok)
1614 Tkinter_Error(self);
1615 else {
1616 res = Py_None;
1617 Py_INCREF(res);
1618 }
1619 LEAVE_OVERLAP_TCL
1620 }
1621 else {
1622 PyErr_Clear();
1623 if (PyArg_ParseTuple(args, "ssO:setvar",
1624 &name1, &name2, &newValue)) {
1625 /* XXX must hold tcl lock already??? */
1626 newval = AsObj(newValue);
1627 ENTER_TCL
1628 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1629 ENTER_OVERLAP
1630 if (!ok)
1631 Tkinter_Error(self);
1632 else {
1633 res = Py_None;
1634 Py_INCREF(res);
1635 }
1636 LEAVE_OVERLAP_TCL
1637 }
1638 else {
1639 return NULL;
1640 }
1641 }
1642 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001643}
1644
1645static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001646Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001647{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001648 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001649}
1650
1651static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001652Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001653{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001654 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001655}
1656
Barry Warsawfa701a81997-01-16 00:15:11 +00001657
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001658
Guido van Rossum18468821994-06-20 07:49:28 +00001659static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001660GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001661{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001662 char *name1, *name2=NULL;
1663 PyObject *res = NULL;
1664 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001665
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001666 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1667 varname_converter, &name1, &name2))
1668 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001669
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001670 ENTER_TCL
1671 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1672 ENTER_OVERLAP
1673 if (tres == NULL) {
1674 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1675 } else {
1676 if (((TkappObject*)self)->wantobjects) {
1677 res = FromObj(self, tres);
1678 }
1679 else {
1680 res = PyString_FromString(Tcl_GetString(tres));
1681 }
1682 }
1683 LEAVE_OVERLAP_TCL
1684 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001685}
1686
1687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001688Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001689{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001690 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001691}
1692
1693static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001694Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001695{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001696 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
Barry Warsawfa701a81997-01-16 00:15:11 +00001699
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001700
Guido van Rossum18468821994-06-20 07:49:28 +00001701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001704 char *name1, *name2=NULL;
1705 int code;
1706 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001707
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001708 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1709 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001710
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001711 ENTER_TCL
1712 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1713 ENTER_OVERLAP
1714 if (code == TCL_ERROR)
1715 res = Tkinter_Error(self);
1716 else {
1717 Py_INCREF(Py_None);
1718 res = Py_None;
1719 }
1720 LEAVE_OVERLAP_TCL
1721 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001722}
1723
1724static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001725Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001726{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001727 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001728}
1729
1730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001731Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001732{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001733 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001734}
1735
Barry Warsawfa701a81997-01-16 00:15:11 +00001736
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001737
Guido van Rossum18468821994-06-20 07:49:28 +00001738/** Tcl to Python **/
1739
1740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001743 char *s;
1744 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001745
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001746 if (PyTuple_Size(args) == 1) {
1747 PyObject* o = PyTuple_GetItem(args, 0);
1748 if (PyInt_Check(o)) {
1749 Py_INCREF(o);
1750 return o;
1751 }
1752 }
1753 if (!PyArg_ParseTuple(args, "s:getint", &s))
1754 return NULL;
1755 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1756 return Tkinter_Error(self);
1757 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001758}
1759
1760static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001761Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001762{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001763 char *s;
1764 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001765
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001766 if (PyTuple_Size(args) == 1) {
1767 PyObject *o = PyTuple_GetItem(args, 0);
1768 if (PyFloat_Check(o)) {
1769 Py_INCREF(o);
1770 return o;
1771 }
1772 }
1773 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1774 return NULL;
1775 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1776 return Tkinter_Error(self);
1777 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001778}
1779
1780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001783 char *s;
1784 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001786 if (PyTuple_Size(args) == 1) {
1787 PyObject *o = PyTuple_GetItem(args, 0);
1788 if (PyInt_Check(o)) {
1789 Py_INCREF(o);
1790 return o;
1791 }
1792 }
1793 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1794 return NULL;
1795 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1796 return Tkinter_Error(self);
1797 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001798}
1799
1800static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001801Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001802{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001803 char *s;
1804 PyObject *res = NULL;
1805 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001806
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001807 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1808 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001809
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001810 CHECK_TCL_APPARTMENT;
1811
1812 ENTER_TCL
1813 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1814 ENTER_OVERLAP
1815 if (retval == TCL_ERROR)
1816 res = Tkinter_Error(self);
1817 else
1818 res = Py_BuildValue("s", Tkapp_Result(self));
1819 LEAVE_OVERLAP_TCL
1820 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001821}
1822
1823static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001824Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001825{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001826 char *s;
1827 PyObject *res = NULL;
1828 int retval;
1829 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001830
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001831 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1832 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001833
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001834 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001835
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001836 ENTER_TCL
1837 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1838 ENTER_OVERLAP
1839 if (retval == TCL_ERROR)
1840 res = Tkinter_Error(self);
1841 else
1842 res = Py_BuildValue("l", v);
1843 LEAVE_OVERLAP_TCL
1844 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001845}
1846
1847static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001848Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001849{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001850 char *s;
1851 PyObject *res = NULL;
1852 double v;
1853 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001854
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001855 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1856 return NULL;
1857 CHECK_TCL_APPARTMENT;
1858 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1859 ENTER_TCL
1860 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1861 ENTER_OVERLAP
1862 PyFPE_END_PROTECT(retval)
1863 if (retval == TCL_ERROR)
1864 res = Tkinter_Error(self);
1865 else
1866 res = Py_BuildValue("d", v);
1867 LEAVE_OVERLAP_TCL
1868 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001869}
1870
1871static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001872Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001873{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001874 char *s;
1875 PyObject *res = NULL;
1876 int retval;
1877 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001878
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001879 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1880 return NULL;
1881 CHECK_TCL_APPARTMENT;
1882 ENTER_TCL
1883 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1884 ENTER_OVERLAP
1885 if (retval == TCL_ERROR)
1886 res = Tkinter_Error(self);
1887 else
1888 res = Py_BuildValue("i", v);
1889 LEAVE_OVERLAP_TCL
1890 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001891}
1892
Barry Warsawfa701a81997-01-16 00:15:11 +00001893
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001894
Guido van Rossum18468821994-06-20 07:49:28 +00001895static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001896Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001897{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001898 char *list;
1899 int argc;
1900 char **argv;
1901 PyObject *v;
1902 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001903
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001904 if (PyTuple_Size(args) == 1) {
1905 v = PyTuple_GetItem(args, 0);
1906 if (PyTuple_Check(v)) {
1907 Py_INCREF(v);
1908 return v;
1909 }
1910 }
1911 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1912 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001913
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001914 if (Tcl_SplitList(Tkapp_Interp(self), list,
1915 &argc, &argv) == TCL_ERROR) {
1916 PyMem_Free(list);
1917 return Tkinter_Error(self);
1918 }
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001920 if (!(v = PyTuple_New(argc)))
1921 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001922
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001923 for (i = 0; i < argc; i++) {
1924 PyObject *s = PyString_FromString(argv[i]);
1925 if (!s || PyTuple_SetItem(v, i, s)) {
1926 Py_DECREF(v);
1927 v = NULL;
1928 goto finally;
1929 }
1930 }
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Barry Warsawfa701a81997-01-16 00:15:11 +00001932 finally:
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001933 ckfree(FREECAST argv);
1934 PyMem_Free(list);
1935 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001936}
1937
1938static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001939Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001940{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001941 PyObject *v;
1942 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001943
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001944 if (PyTuple_Size(args) == 1) {
1945 PyObject* o = PyTuple_GetItem(args, 0);
1946 if (PyTuple_Check(o)) {
1947 o = SplitObj(o);
1948 return o;
1949 }
1950 }
1951 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1952 return NULL;
1953 v = Split(list);
1954 PyMem_Free(list);
1955 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001956}
1957
1958static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001959Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001960{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001961 char *s = Merge(args);
1962 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001964 if (s) {
1965 res = PyString_FromString(s);
1966 ckfree(s);
1967 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001968
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001969 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001970}
1971
Barry Warsawfa701a81997-01-16 00:15:11 +00001972
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001973
Guido van Rossum18468821994-06-20 07:49:28 +00001974/** Tcl Command **/
1975
Guido van Rossum00d93061998-05-28 23:06:38 +00001976/* Client data struct */
1977typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001978 PyObject *self;
1979 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00001980} PythonCmd_ClientData;
1981
1982static int
Fred Drake509d79a2000-07-08 04:04:38 +00001983PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00001984{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001985 errorInCmd = 1;
1986 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1987 LEAVE_PYTHON
1988 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00001989}
1990
Guido van Rossum18468821994-06-20 07:49:28 +00001991/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00001992 * function or method.
1993 */
Guido van Rossum18468821994-06-20 07:49:28 +00001994static int
Fred Drake509d79a2000-07-08 04:04:38 +00001995PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00001996{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00001997 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1998 PyObject *self, *func, *arg, *res;
1999 int i, rv;
2000 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002001
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002002 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002003
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002004 /* TBD: no error checking here since we know, via the
2005 * Tkapp_CreateCommand() that the client data is a two-tuple
2006 */
2007 self = data->self;
2008 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002009
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002010 /* Create argument list (argv1, ..., argvN) */
2011 if (!(arg = PyTuple_New(argc - 1)))
2012 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002013
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002014 for (i = 0; i < (argc - 1); i++) {
2015 PyObject *s = PyString_FromString(argv[i + 1]);
2016 if (!s || PyTuple_SetItem(arg, i, s)) {
2017 Py_DECREF(arg);
2018 return PythonCmd_Error(interp);
2019 }
2020 }
2021 res = PyEval_CallObject(func, arg);
2022 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002023
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002024 if (res == NULL)
2025 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002027 obj_res = AsObj(res);
2028 if (obj_res == NULL) {
2029 Py_DECREF(res);
2030 return PythonCmd_Error(interp);
2031 }
2032 else {
2033 Tcl_SetObjResult(interp, obj_res);
2034 rv = TCL_OK;
2035 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002036
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002037 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002038
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002039 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002040
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002041 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002042}
2043
2044static void
Fred Drake509d79a2000-07-08 04:04:38 +00002045PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002046{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002047 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002048
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002049 ENTER_PYTHON
2050 Py_XDECREF(data->self);
2051 Py_XDECREF(data->func);
2052 PyMem_DEL(data);
2053 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002054}
2055
Barry Warsawfa701a81997-01-16 00:15:11 +00002056
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002057
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002058
2059TCL_DECLARE_MUTEX(command_mutex)
2060
2061typedef struct CommandEvent{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002062 Tcl_Event ev;
2063 Tcl_Interp* interp;
2064 char *name;
2065 int create;
2066 int *status;
2067 ClientData *data;
2068 Tcl_Condition done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002069} CommandEvent;
2070
2071static int
2072Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002073{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002074 if (ev->create)
2075 *ev->status = Tcl_CreateCommand(
2076 ev->interp, ev->name, PythonCmd,
2077 ev->data, PythonCmdDelete) == NULL;
2078 else
2079 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2080 Tcl_MutexLock(&command_mutex);
2081 Tcl_ConditionNotify(&ev->done);
2082 Tcl_MutexUnlock(&command_mutex);
2083 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002084}
2085
2086static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002087Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002089 TkappObject *self = (TkappObject*)selfptr;
2090 PythonCmd_ClientData *data;
2091 char *cmdName;
2092 PyObject *func;
2093 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002094
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002095 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2096 return NULL;
2097 if (!PyCallable_Check(func)) {
2098 PyErr_SetString(PyExc_TypeError, "command not callable");
2099 return NULL;
2100 }
Guido van Rossum18468821994-06-20 07:49:28 +00002101
Martin v. Löwisa9656492003-03-30 08:44:58 +00002102#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002103 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2104 !WaitForMainloop(self))
2105 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002106#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002107
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002108 data = PyMem_NEW(PythonCmd_ClientData, 1);
2109 if (!data)
2110 return PyErr_NoMemory();
2111 Py_INCREF(self);
2112 Py_INCREF(func);
2113 data->self = selfptr;
2114 data->func = func;
Guido van Rossum18468821994-06-20 07:49:28 +00002115
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002116 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2117 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2118 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2119 ev->interp = self->interp;
2120 ev->create = 1;
2121 ev->name = cmdName;
2122 ev->data = (ClientData)data;
2123 ev->status = &err;
2124 ev->done = NULL;
2125 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2126 }
2127 else {
2128 ENTER_TCL
2129 err = Tcl_CreateCommand(
2130 Tkapp_Interp(self), cmdName, PythonCmd,
2131 (ClientData)data, PythonCmdDelete) == NULL;
2132 LEAVE_TCL
2133 }
2134 if (err) {
2135 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2136 PyMem_DEL(data);
2137 return NULL;
2138 }
2139
2140 Py_INCREF(Py_None);
2141 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002142}
2143
Barry Warsawfa701a81997-01-16 00:15:11 +00002144
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002145
Guido van Rossum18468821994-06-20 07:49:28 +00002146static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002147Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002148{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002149 TkappObject *self = (TkappObject*)selfptr;
2150 char *cmdName;
2151 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002152
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002153 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2154 return NULL;
2155 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2156 CommandEvent *ev;
2157 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2158 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2159 ev->interp = self->interp;
2160 ev->create = 0;
2161 ev->name = cmdName;
2162 ev->status = &err;
2163 ev->done = NULL;
2164 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2165 &command_mutex);
2166 }
2167 else {
2168 ENTER_TCL
2169 err = Tcl_DeleteCommand(self->interp, cmdName);
2170 LEAVE_TCL
2171 }
2172 if (err == -1) {
2173 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2174 return NULL;
2175 }
2176 Py_INCREF(Py_None);
2177 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
2179
Barry Warsawfa701a81997-01-16 00:15:11 +00002180
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002181
Guido van Rossum00d93061998-05-28 23:06:38 +00002182#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002183/** File Handler **/
2184
Guido van Rossum00d93061998-05-28 23:06:38 +00002185typedef struct _fhcdata {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002186 PyObject *func;
2187 PyObject *file;
2188 int id;
2189 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002190} FileHandler_ClientData;
2191
2192static FileHandler_ClientData *HeadFHCD;
2193
2194static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002195NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002196{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002197 FileHandler_ClientData *p;
2198 p = PyMem_NEW(FileHandler_ClientData, 1);
2199 if (p != NULL) {
2200 Py_XINCREF(func);
2201 Py_XINCREF(file);
2202 p->func = func;
2203 p->file = file;
2204 p->id = id;
2205 p->next = HeadFHCD;
2206 HeadFHCD = p;
2207 }
2208 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002209}
2210
2211static void
Fred Drake509d79a2000-07-08 04:04:38 +00002212DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002213{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002214 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002215
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002216 pp = &HeadFHCD;
2217 while ((p = *pp) != NULL) {
2218 if (p->id == id) {
2219 *pp = p->next;
2220 Py_XDECREF(p->func);
2221 Py_XDECREF(p->file);
2222 PyMem_DEL(p);
2223 }
2224 else
2225 pp = &p->next;
2226 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002227}
2228
Guido van Rossuma597dde1995-01-10 20:56:29 +00002229static void
Fred Drake509d79a2000-07-08 04:04:38 +00002230FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002231{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002232 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2233 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002234
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002235 ENTER_PYTHON
2236 func = data->func;
2237 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002238
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002239 arg = Py_BuildValue("(Oi)", file, (long) mask);
2240 res = PyEval_CallObject(func, arg);
2241 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002242
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002243 if (res == NULL) {
2244 errorInCmd = 1;
2245 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2246 }
2247 Py_XDECREF(res);
2248 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002249}
2250
Guido van Rossum18468821994-06-20 07:49:28 +00002251static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002252Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2253 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002254{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002255 FileHandler_ClientData *data;
2256 PyObject *file, *func;
2257 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002258
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002259 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2260 &file, &mask, &func))
2261 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002262
Martin v. Löwisa9656492003-03-30 08:44:58 +00002263#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002264 if (!self && !tcl_lock) {
2265 /* We don't have the Tcl lock since Tcl is threaded. */
2266 PyErr_SetString(PyExc_RuntimeError,
2267 "_tkinter.createfilehandler not supported "
2268 "for threaded Tcl");
2269 return NULL;
2270 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002271#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002272
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002273 if (self) {
2274 CHECK_TCL_APPARTMENT;
2275 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002276
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002277 tfile = PyObject_AsFileDescriptor(file);
2278 if (tfile < 0)
2279 return NULL;
2280 if (!PyCallable_Check(func)) {
2281 PyErr_SetString(PyExc_TypeError, "bad argument list");
2282 return NULL;
2283 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002284
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002285 data = NewFHCD(func, file, tfile);
2286 if (data == NULL)
2287 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002288
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002289 /* Ought to check for null Tcl_File object... */
2290 ENTER_TCL
2291 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2292 LEAVE_TCL
2293 Py_INCREF(Py_None);
2294 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002295}
2296
2297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002298Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002299{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002300 PyObject *file;
2301 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002302
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002303 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2304 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002305
Martin v. Löwisa9656492003-03-30 08:44:58 +00002306#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002307 if (!self && !tcl_lock) {
2308 /* We don't have the Tcl lock since Tcl is threaded. */
2309 PyErr_SetString(PyExc_RuntimeError,
2310 "_tkinter.deletefilehandler not supported "
2311 "for threaded Tcl");
2312 return NULL;
2313 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002314#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002315
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002316 if (self) {
2317 CHECK_TCL_APPARTMENT;
2318 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002319
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002320 tfile = PyObject_AsFileDescriptor(file);
2321 if (tfile < 0)
2322 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002323
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002324 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002325
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002326 /* Ought to check for null Tcl_File object... */
2327 ENTER_TCL
2328 Tcl_DeleteFileHandler(tfile);
2329 LEAVE_TCL
2330 Py_INCREF(Py_None);
2331 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002332}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002333#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002334
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002335
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002336/**** Tktt Object (timer token) ****/
2337
Jeremy Hylton938ace62002-07-17 16:30:39 +00002338static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002339
Guido van Rossum00d93061998-05-28 23:06:38 +00002340typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002341 PyObject_HEAD
2342 Tcl_TimerToken token;
2343 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002344} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002345
2346static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002347Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002348{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002349 TkttObject *v = (TkttObject *)self;
2350 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002351
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002352 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2353 return NULL;
2354 if (v->token != NULL) {
2355 Tcl_DeleteTimerHandler(v->token);
2356 v->token = NULL;
2357 }
2358 if (func != NULL) {
2359 v->func = NULL;
2360 Py_DECREF(func);
2361 Py_DECREF(v); /* See Tktt_New() */
2362 }
2363 Py_INCREF(Py_None);
2364 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002365}
2366
2367static PyMethodDef Tktt_methods[] =
2368{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002369 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2370 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002371};
2372
2373static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002374Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002375{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002376 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002377
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002378 v = PyObject_New(TkttObject, &Tktt_Type);
2379 if (v == NULL)
2380 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002381
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002382 Py_INCREF(func);
2383 v->token = NULL;
2384 v->func = func;
2385
2386 /* Extra reference, deleted when called or when handler is deleted */
2387 Py_INCREF(v);
2388 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002389}
2390
2391static void
Fred Drake509d79a2000-07-08 04:04:38 +00002392Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002393{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002394 TkttObject *v = (TkttObject *)self;
2395 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002396
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002397 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002398
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002399 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002400}
2401
Guido van Rossum597ac201998-05-12 14:36:19 +00002402static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002403Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002404{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002405 TkttObject *v = (TkttObject *)self;
2406 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002407
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002408 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2409 v->func == NULL ? ", handler deleted" : "");
2410 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411}
2412
2413static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002414Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002415{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002416 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417}
2418
2419static PyTypeObject Tktt_Type =
2420{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002421 PyVarObject_HEAD_INIT(NULL, 0)
2422 "tktimertoken", /*tp_name */
2423 sizeof(TkttObject), /*tp_basicsize */
2424 0, /*tp_itemsize */
2425 Tktt_Dealloc, /*tp_dealloc */
2426 0, /*tp_print */
2427 Tktt_GetAttr, /*tp_getattr */
2428 0, /*tp_setattr */
2429 0, /*tp_compare */
2430 Tktt_Repr, /*tp_repr */
2431 0, /*tp_as_number */
2432 0, /*tp_as_sequence */
2433 0, /*tp_as_mapping */
2434 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002435};
2436
Barry Warsawfa701a81997-01-16 00:15:11 +00002437
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002438
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002439/** Timer Handler **/
2440
2441static void
Fred Drake509d79a2000-07-08 04:04:38 +00002442TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002444 TkttObject *v = (TkttObject *)clientData;
2445 PyObject *func = v->func;
2446 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002447
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002448 if (func == NULL)
2449 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002450
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002451 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002452
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002453 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002454
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002455 res = PyEval_CallObject(func, NULL);
2456 Py_DECREF(func);
2457 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002459 if (res == NULL) {
2460 errorInCmd = 1;
2461 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2462 }
2463 else
2464 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002465
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002466 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002467}
2468
2469static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002470Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002471{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002472 int milliseconds;
2473 PyObject *func;
2474 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002475
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002476 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2477 &milliseconds, &func))
2478 return NULL;
2479 if (!PyCallable_Check(func)) {
2480 PyErr_SetString(PyExc_TypeError, "bad argument list");
2481 return NULL;
2482 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002483
Martin v. Löwisa9656492003-03-30 08:44:58 +00002484#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002485 if (!self && !tcl_lock) {
2486 /* We don't have the Tcl lock since Tcl is threaded. */
2487 PyErr_SetString(PyExc_RuntimeError,
2488 "_tkinter.createtimerhandler not supported "
2489 "for threaded Tcl");
2490 return NULL;
2491 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002492#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002493
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002494 if (self) {
2495 CHECK_TCL_APPARTMENT;
2496 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002497
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002498 v = Tktt_New(func);
2499 if (v) {
2500 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2501 (ClientData)v);
2502 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002503
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002504 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002505}
2506
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002507
Guido van Rossum18468821994-06-20 07:49:28 +00002508/** Event Loop **/
2509
Guido van Rossum18468821994-06-20 07:49:28 +00002510static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002511Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002512{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002513 int threshold = 0;
2514 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002515#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002516 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002517#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002518
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002519 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2520 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002521
Martin v. Löwisa9656492003-03-30 08:44:58 +00002522#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002523 if (!self && !tcl_lock) {
2524 /* We don't have the Tcl lock since Tcl is threaded. */
2525 PyErr_SetString(PyExc_RuntimeError,
2526 "_tkinter.mainloop not supported "
2527 "for threaded Tcl");
2528 return NULL;
2529 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002530#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002531
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002532 if (self) {
2533 CHECK_TCL_APPARTMENT;
2534 self->dispatching = 1;
2535 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002536
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002537 quitMainLoop = 0;
2538 while (Tk_GetNumMainWindows() > threshold &&
2539 !quitMainLoop &&
2540 !errorInCmd)
2541 {
2542 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002543
2544#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002545 if (self && self->threaded) {
2546 /* Allow other Python threads to run. */
2547 ENTER_TCL
2548 result = Tcl_DoOneEvent(0);
2549 LEAVE_TCL
2550 }
2551 else {
2552 Py_BEGIN_ALLOW_THREADS
2553 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2554 tcl_tstate = tstate;
2555 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2556 tcl_tstate = NULL;
2557 if(tcl_lock)PyThread_release_lock(tcl_lock);
2558 if (result == 0)
2559 Sleep(Tkinter_busywaitinterval);
2560 Py_END_ALLOW_THREADS
2561 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002562#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002563 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002564#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002565
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002566 if (PyErr_CheckSignals() != 0) {
2567 if (self)
2568 self->dispatching = 0;
2569 return NULL;
2570 }
2571 if (result < 0)
2572 break;
2573 }
2574 if (self)
2575 self->dispatching = 0;
2576 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002577
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002578 if (errorInCmd) {
2579 errorInCmd = 0;
2580 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2581 excInCmd = valInCmd = trbInCmd = NULL;
2582 return NULL;
2583 }
2584 Py_INCREF(Py_None);
2585 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002586}
2587
2588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002589Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002590{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002591 int flags = 0;
2592 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002593
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002594 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2595 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002596
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002597 ENTER_TCL
2598 rv = Tcl_DoOneEvent(flags);
2599 LEAVE_TCL
2600 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002601}
2602
2603static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002604Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002605{
2606
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002607 if (!PyArg_ParseTuple(args, ":quit"))
2608 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002609
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002610 quitMainLoop = 1;
2611 Py_INCREF(Py_None);
2612 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002613}
2614
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002615static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002616Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002617{
2618
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002619 if (!PyArg_ParseTuple(args, ":interpaddr"))
2620 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002621
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002622 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002623}
2624
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002625static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002626Tkapp_TkInit(PyObject *self, PyObject *args)
2627{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002628 static int has_failed;
2629 Tcl_Interp *interp = Tkapp_Interp(self);
2630 Tk_Window main_window;
2631 const char * _tk_exists = NULL;
2632 int err;
2633 main_window = Tk_MainWindow(interp);
David Aschere2b4b322004-02-18 05:59:53 +00002634
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002635 /* In all current versions of Tk (including 8.4.13), Tk_Init
2636 deadlocks on the second call when the first call failed.
2637 To avoid the deadlock, we just refuse the second call through
2638 a static variable. */
2639 if (has_failed) {
2640 PyErr_SetString(Tkinter_TclError,
2641 "Calling Tk_Init again after a previous call failed might deadlock");
2642 return NULL;
2643 }
2644
2645 /* We want to guard against calling Tk_Init() multiple times */
2646 CHECK_TCL_APPARTMENT;
2647 ENTER_TCL
2648 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2649 ENTER_OVERLAP
2650 if (err == TCL_ERROR) {
2651 /* This sets an exception, but we cannot return right
2652 away because we need to exit the overlap first. */
2653 Tkinter_Error(self);
2654 } else {
2655 _tk_exists = Tkapp_Result(self);
2656 }
2657 LEAVE_OVERLAP_TCL
2658 if (err == TCL_ERROR) {
2659 return NULL;
2660 }
2661 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2662 if (Tk_Init(interp) == TCL_ERROR) {
2663 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2664 has_failed = 1;
2665 return NULL;
2666 }
2667 }
2668 Py_INCREF(Py_None);
2669 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002670}
Barry Warsawfa701a81997-01-16 00:15:11 +00002671
Martin v. Löwisffad6332002-11-26 09:28:05 +00002672static PyObject *
2673Tkapp_WantObjects(PyObject *self, PyObject *args)
2674{
2675
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002676 int wantobjects = -1;
2677 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2678 return NULL;
2679 if (wantobjects == -1)
2680 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2681 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002682
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002683 Py_INCREF(Py_None);
2684 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002685}
2686
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002687static PyObject *
2688Tkapp_WillDispatch(PyObject *self, PyObject *args)
2689{
2690
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002691 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002692
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002693 Py_INCREF(Py_None);
2694 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002695}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002696
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002697
Guido van Rossum18468821994-06-20 07:49:28 +00002698/**** Tkapp Method List ****/
2699
2700static PyMethodDef Tkapp_methods[] =
2701{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002702 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2703 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2704 {"call", Tkapp_Call, METH_VARARGS},
2705 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2706 {"eval", Tkapp_Eval, METH_VARARGS},
2707 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2708 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2709 {"record", Tkapp_Record, METH_VARARGS},
2710 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2711 {"setvar", Tkapp_SetVar, METH_VARARGS},
2712 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2713 {"getvar", Tkapp_GetVar, METH_VARARGS},
2714 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2715 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2716 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2717 {"getint", Tkapp_GetInt, METH_VARARGS},
2718 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2719 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2720 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2721 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2722 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2723 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2724 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2725 {"split", Tkapp_Split, METH_VARARGS},
2726 {"merge", Tkapp_Merge, METH_VARARGS},
2727 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2728 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002729#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002730 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2731 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002732#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002733 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2734 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2735 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2736 {"quit", Tkapp_Quit, METH_VARARGS},
2737 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2738 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2739 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002740};
2741
Barry Warsawfa701a81997-01-16 00:15:11 +00002742
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002743
Guido van Rossum18468821994-06-20 07:49:28 +00002744/**** Tkapp Type Methods ****/
2745
2746static void
Fred Drake509d79a2000-07-08 04:04:38 +00002747Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002748{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002749 /*CHECK_TCL_APPARTMENT;*/
2750 ENTER_TCL
2751 Tcl_DeleteInterp(Tkapp_Interp(self));
2752 LEAVE_TCL
2753 PyObject_Del(self);
2754 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002755}
2756
2757static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002758Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002759{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002760 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002761}
2762
2763static PyTypeObject Tkapp_Type =
2764{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002765 PyVarObject_HEAD_INIT(NULL, 0)
2766 "tkapp", /*tp_name */
2767 sizeof(TkappObject), /*tp_basicsize */
2768 0, /*tp_itemsize */
2769 Tkapp_Dealloc, /*tp_dealloc */
2770 0, /*tp_print */
2771 Tkapp_GetAttr, /*tp_getattr */
2772 0, /*tp_setattr */
2773 0, /*tp_compare */
2774 0, /*tp_repr */
2775 0, /*tp_as_number */
2776 0, /*tp_as_sequence */
2777 0, /*tp_as_mapping */
2778 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002779};
2780
Barry Warsawfa701a81997-01-16 00:15:11 +00002781
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002782
Guido van Rossum18468821994-06-20 07:49:28 +00002783/**** Tkinter Module ****/
2784
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002785typedef struct {
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002786 PyObject* tuple;
2787 int size; /* current size */
2788 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002789} FlattenContext;
2790
2791static int
2792_bump(FlattenContext* context, int size)
2793{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002794 /* expand tuple to hold (at least) size new items.
2795 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002796
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002797 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002798
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002799 if (maxsize < context->size + size)
2800 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002801
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002802 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002803
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002804 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002805}
2806
2807static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002808_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002809{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002810 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002811
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002812 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002813
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002814 if (depth > 1000) {
2815 PyErr_SetString(PyExc_ValueError,
2816 "nesting too deep in _flatten");
2817 return 0;
2818 } else if (PyList_Check(item)) {
2819 size = PyList_GET_SIZE(item);
2820 /* preallocate (assume no nesting) */
2821 if (context->size + size > context->maxsize &&
2822 !_bump(context, size))
2823 return 0;
2824 /* copy items to output tuple */
2825 for (i = 0; i < size; i++) {
2826 PyObject *o = PyList_GET_ITEM(item, i);
2827 if (PyList_Check(o) || PyTuple_Check(o)) {
2828 if (!_flatten1(context, o, depth + 1))
2829 return 0;
2830 } else if (o != Py_None) {
2831 if (context->size + 1 > context->maxsize &&
2832 !_bump(context, 1))
2833 return 0;
2834 Py_INCREF(o);
2835 PyTuple_SET_ITEM(context->tuple,
2836 context->size++, o);
2837 }
2838 }
2839 } else if (PyTuple_Check(item)) {
2840 /* same, for tuples */
2841 size = PyTuple_GET_SIZE(item);
2842 if (context->size + size > context->maxsize &&
2843 !_bump(context, size))
2844 return 0;
2845 for (i = 0; i < size; i++) {
2846 PyObject *o = PyTuple_GET_ITEM(item, i);
2847 if (PyList_Check(o) || PyTuple_Check(o)) {
2848 if (!_flatten1(context, o, depth + 1))
2849 return 0;
2850 } else if (o != Py_None) {
2851 if (context->size + 1 > context->maxsize &&
2852 !_bump(context, 1))
2853 return 0;
2854 Py_INCREF(o);
2855 PyTuple_SET_ITEM(context->tuple,
2856 context->size++, o);
2857 }
2858 }
2859 } else {
2860 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2861 return 0;
2862 }
2863 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002864}
2865
2866static PyObject *
2867Tkinter_Flatten(PyObject* self, PyObject* args)
2868{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002869 FlattenContext context;
2870 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002871
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002872 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2873 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002874
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002875 context.maxsize = PySequence_Size(item);
2876 if (context.maxsize <= 0)
2877 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002878
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002879 context.tuple = PyTuple_New(context.maxsize);
2880 if (!context.tuple)
2881 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002882
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002883 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002884
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002885 if (!_flatten1(&context, item,0))
2886 return NULL;
2887
2888 if (_PyTuple_Resize(&context.tuple, context.size))
2889 return NULL;
2890
2891 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002892}
2893
Guido van Rossum18468821994-06-20 07:49:28 +00002894static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002895Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002896{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002897 char *screenName = NULL;
2898 char *baseName = NULL;
2899 char *className = NULL;
2900 int interactive = 0;
2901 int wantobjects = 0;
2902 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2903 int sync = 0; /* pass -sync to wish */
2904 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002905
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002906 baseName = strrchr(Py_GetProgramName(), '/');
2907 if (baseName != NULL)
2908 baseName++;
2909 else
2910 baseName = Py_GetProgramName();
2911 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00002912
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002913 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2914 &screenName, &baseName, &className,
2915 &interactive, &wantobjects, &wantTk,
2916 &sync, &use))
2917 return NULL;
2918
2919 return (PyObject *) Tkapp_New(screenName, baseName, className,
2920 interactive, wantobjects, wantTk,
2921 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002922}
2923
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002924static PyObject *
2925Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2926{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002927 int new_val;
2928 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2929 return NULL;
2930 if (new_val < 0) {
2931 PyErr_SetString(PyExc_ValueError,
2932 "busywaitinterval must be >= 0");
2933 return NULL;
2934 }
2935 Tkinter_busywaitinterval = new_val;
2936 Py_INCREF(Py_None);
2937 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002938}
2939
2940static char setbusywaitinterval_doc[] =
2941"setbusywaitinterval(n) -> None\n\
2942\n\
2943Set the busy-wait interval in milliseconds between successive\n\
2944calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2945It should be set to a divisor of the maximum time between\n\
2946frames in an animation.";
2947
2948static PyObject *
2949Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2950{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002951 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002952}
2953
2954static char getbusywaitinterval_doc[] =
2955"getbusywaitinterval() -> int\n\
2956\n\
2957Return the current busy-wait interval between successive\n\
2958calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2959
Guido van Rossum18468821994-06-20 07:49:28 +00002960static PyMethodDef moduleMethods[] =
2961{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002962 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2963 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002964#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002965 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2966 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002967#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002968 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2969 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2970 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2971 {"quit", Tkapp_Quit, METH_VARARGS},
2972 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2973 setbusywaitinterval_doc},
2974 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2975 METH_NOARGS, getbusywaitinterval_doc},
2976 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002977};
2978
Guido van Rossum7bf15641998-05-22 18:28:17 +00002979#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00002980
2981static int stdin_ready = 0;
2982
Guido van Rossumad4db171998-06-13 13:56:28 +00002983#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00002984static void
Fred Drake509d79a2000-07-08 04:04:38 +00002985MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00002986{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002987 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00002988}
Guido van Rossumad4db171998-06-13 13:56:28 +00002989#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00002990
Martin v. Löwisa9656492003-03-30 08:44:58 +00002991#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00002992static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002993#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00002994
Guido van Rossum18468821994-06-20 07:49:28 +00002995static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002996EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00002997{
Guido van Rossumad4db171998-06-13 13:56:28 +00002998#ifndef MS_WINDOWS
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00002999 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003000#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003001#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003002 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003003#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003004 stdin_ready = 0;
3005 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003006#ifndef MS_WINDOWS
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003007 tfile = fileno(stdin);
3008 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003009#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003010 while (!errorInCmd && !stdin_ready) {
3011 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003012#ifdef MS_WINDOWS
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003013 if (_kbhit()) {
3014 stdin_ready = 1;
3015 break;
3016 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003017#endif
3018#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003019 Py_BEGIN_ALLOW_THREADS
3020 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3021 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003022
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003023 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003024
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003025 tcl_tstate = NULL;
3026 if(tcl_lock)PyThread_release_lock(tcl_lock);
3027 if (result == 0)
3028 Sleep(Tkinter_busywaitinterval);
3029 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003030#else
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003031 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003032#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003033
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003034 if (result < 0)
3035 break;
3036 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003037#ifndef MS_WINDOWS
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003038 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003039#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003040 if (errorInCmd) {
3041 errorInCmd = 0;
3042 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3043 excInCmd = valInCmd = trbInCmd = NULL;
3044 PyErr_Print();
3045 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003046#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003047 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003048#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003049 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003050}
Guido van Rossum18468821994-06-20 07:49:28 +00003051
Guido van Rossum00d93061998-05-28 23:06:38 +00003052#endif
3053
Guido van Rossum7bf15641998-05-22 18:28:17 +00003054static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003055EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003056{
Guido van Rossum00d93061998-05-28 23:06:38 +00003057#ifdef WAIT_FOR_STDIN
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003058 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003059#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003060 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003061#endif
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003062 PyOS_InputHook = EventHook;
3063 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003064#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003065}
3066
3067static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003068DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003069{
Guido van Rossum00d93061998-05-28 23:06:38 +00003070#ifdef WAIT_FOR_STDIN
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003071 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3072 PyOS_InputHook = NULL;
3073 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003074#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003075}
3076
Barry Warsawfa701a81997-01-16 00:15:11 +00003077
3078/* all errors will be checked in one fell swoop in init_tkinter() */
3079static void
Fred Drake509d79a2000-07-08 04:04:38 +00003080ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003081{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003082 PyObject *v = PyInt_FromLong(val);
3083 if (v) {
3084 PyDict_SetItemString(d, name, v);
3085 Py_DECREF(v);
3086 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003087}
3088static void
Fred Drake509d79a2000-07-08 04:04:38 +00003089ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003090{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003091 PyObject *v = PyString_FromString(val);
3092 if (v) {
3093 PyDict_SetItemString(d, name, v);
3094 Py_DECREF(v);
3095 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003096}
3097
3098
Mark Hammond62b1ab12002-07-23 06:31:15 +00003099PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003100init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003101{
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003102 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003103
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003104 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003105
3106#ifdef WITH_THREAD
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003107 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003108#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003109
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003110 m = Py_InitModule("_tkinter", moduleMethods);
3111 if (m == NULL)
3112 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003113
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003114 d = PyModule_GetDict(m);
3115 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3116 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003117
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003118 ins_long(d, "READABLE", TCL_READABLE);
3119 ins_long(d, "WRITABLE", TCL_WRITABLE);
3120 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3121 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3122 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3123 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3124 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3125 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3126 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3127 ins_string(d, "TK_VERSION", TK_VERSION);
3128 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003129
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003130 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003131
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003132 Py_TYPE(&Tktt_Type) = &PyType_Type;
3133 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003134
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003135 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3136 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003137
3138#ifdef TK_AQUA
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003139 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3140 * start waking up. Note that Tcl_FindExecutable will do this, this
3141 * code must be above it! The original warning from
3142 * tkMacOSXAppInit.c is copied below.
3143 *
3144 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3145 * Tcl interpreter for now. It probably should work to do this
3146 * in the other order, but for now it doesn't seem to.
3147 *
3148 */
3149 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003150#endif
3151
3152
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003153 /* This helps the dynamic loader; in Unicode aware Tcl versions
3154 it also helps Tcl find its encodings. */
3155 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003156
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003157 if (PyErr_Occurred())
3158 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003159
Guido van Rossum43ff8681998-07-14 18:02:13 +00003160#if 0
Antoine Pitrouc7c96a92010-05-09 15:15:40 +00003161 /* This was not a good idea; through <Destroy> bindings,
3162 Tcl_Finalize() may invoke Python code but at that point the
3163 interpreter and thread state have already been destroyed! */
3164 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003165#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003166
Guido van Rossum18468821994-06-20 07:49:28 +00003167}