blob: 01d628435a086f580af979bd4fc3dd7578d04d30 [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 Pitrouc83ea132010-05-09 14:46:46 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk 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
Guilherme Polo5d64c332009-04-05 02:11:19 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +0000207 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000208
209#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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 Pitrouc83ea132010-05-09 14:46:46 +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
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000283#ifdef TKINTER_PROTECT_LOADTK
284static int tk_load_failed;
285#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000286
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000287
Guido van Rossum18468821994-06-20 07:49:28 +0000288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000289Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000290{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000293}
294
Barry Warsawfa701a81997-01-16 00:15:11 +0000295
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000296
Guido van Rossum18468821994-06-20 07:49:28 +0000297/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000298
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000299static int Tkinter_busywaitinterval = 20;
300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000303
Guido van Rossum00d93061998-05-28 23:06:38 +0000304/* Millisecond sleep() for Unix platforms. */
305
306static void
Fred Drake509d79a2000-07-08 04:04:38 +0000307Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000308{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
311 t.tv_sec = milli/1000;
312 t.tv_usec = (milli%1000) * 1000;
313 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000314}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000315#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000316
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000317/* Wait up to 1s for the mainloop to come up. */
318
319static int
320WaitForMainloop(TkappObject* self)
321{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
329 }
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000334}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000335#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000336
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000337
Guido van Rossum18468821994-06-20 07:49:28 +0000338static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000339AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000340{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341 if (PyString_Check(value))
342 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000343#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000344 else if (PyUnicode_Check(value)) {
345 PyObject *v = PyUnicode_AsUTF8String(value);
346 if (v == NULL)
347 return NULL;
348 if (PyList_Append(tmp, v) != 0) {
349 Py_DECREF(v);
350 return NULL;
351 }
352 Py_DECREF(v);
353 return PyString_AsString(v);
354 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000355#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 else {
357 PyObject *v = PyObject_Str(value);
358 if (v == NULL)
359 return NULL;
360 if (PyList_Append(tmp, v) != 0) {
361 Py_DECREF(v);
362 return NULL;
363 }
364 Py_DECREF(v);
365 return PyString_AsString(v);
366 }
Guido van Rossum18468821994-06-20 07:49:28 +0000367}
368
Barry Warsawfa701a81997-01-16 00:15:11 +0000369
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000370
Guido van Rossum18468821994-06-20 07:49:28 +0000371#define ARGSZ 64
372
373static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000374Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000375{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000376 PyObject *tmp = NULL;
377 char *argvStore[ARGSZ];
378 char **argv = NULL;
379 int fvStore[ARGSZ];
380 int *fv = NULL;
381 int argc = 0, fvc = 0, i;
382 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000384 if (!(tmp = PyList_New(0)))
385 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000387 argv = argvStore;
388 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000389
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000390 if (args == NULL)
391 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000392
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000393 else if (!PyTuple_Check(args)) {
394 argc = 1;
395 fv[0] = 0;
396 if (!(argv[0] = AsString(args, tmp)))
397 goto finally;
398 }
399 else {
400 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000401
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000402 if (argc > ARGSZ) {
403 argv = (char **)ckalloc(argc * sizeof(char *));
404 fv = (int *)ckalloc(argc * sizeof(int));
405 if (argv == NULL || fv == NULL) {
406 PyErr_NoMemory();
407 goto finally;
408 }
409 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000410
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000411 for (i = 0; i < argc; i++) {
412 PyObject *v = PyTuple_GetItem(args, i);
413 if (PyTuple_Check(v)) {
414 fv[i] = 1;
415 if (!(argv[i] = Merge(v)))
416 goto finally;
417 fvc++;
418 }
419 else if (v == Py_None) {
420 argc = i;
421 break;
422 }
423 else {
424 fv[i] = 0;
425 if (!(argv[i] = AsString(v, tmp)))
426 goto finally;
427 fvc++;
428 }
429 }
430 }
431 res = Tcl_Merge(argc, argv);
432 if (res == NULL)
433 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000436 for (i = 0; i < fvc; i++)
437 if (fv[i]) {
438 ckfree(argv[i]);
439 }
440 if (argv != argvStore)
441 ckfree(FREECAST argv);
442 if (fv != fvStore)
443 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000445 Py_DECREF(tmp);
446 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000447}
448
Barry Warsawfa701a81997-01-16 00:15:11 +0000449
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000450
Guido van Rossum18468821994-06-20 07:49:28 +0000451static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000452Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 int argc;
455 char **argv;
456 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458 if (list == NULL) {
459 Py_INCREF(Py_None);
460 return Py_None;
461 }
Guido van Rossum18468821994-06-20 07:49:28 +0000462
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000463 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
464 /* Not a list.
465 * Could be a quoted string containing funnies, e.g. {"}.
466 * Return the string itself.
467 */
468 return PyString_FromString(list);
469 }
Guido van Rossum18468821994-06-20 07:49:28 +0000470
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 if (argc == 0)
472 v = PyString_FromString("");
473 else if (argc == 1)
474 v = PyString_FromString(argv[0]);
475 else if ((v = PyTuple_New(argc)) != NULL) {
476 int i;
477 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 for (i = 0; i < argc; i++) {
480 if ((w = Split(argv[i])) == NULL) {
481 Py_DECREF(v);
482 v = NULL;
483 break;
484 }
485 PyTuple_SetItem(v, i, w);
486 }
487 }
488 Tcl_Free(FREECAST argv);
489 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000490}
491
Martin v. Löwisffad6332002-11-26 09:28:05 +0000492/* In some cases, Tcl will still return strings that are supposed to be
493 lists. SplitObj walks through a nested tuple, finding string objects that
494 need to be split. */
495
Martin v. Löwis111c1802008-06-13 07:47:47 +0000496static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000497SplitObj(PyObject *arg)
498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000499 if (PyTuple_Check(arg)) {
500 int i, size;
501 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000502
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000503 size = PyTuple_Size(arg);
504 result = NULL;
505 /* Recursively invoke SplitObj for all tuple items.
506 If this does not return a new object, no action is
507 needed. */
508 for(i = 0; i < size; i++) {
509 elem = PyTuple_GetItem(arg, i);
510 newelem = SplitObj(elem);
511 if (!newelem) {
512 Py_XDECREF(result);
513 return NULL;
514 }
515 if (!result) {
516 int k;
517 if (newelem == elem) {
518 Py_DECREF(newelem);
519 continue;
520 }
521 result = PyTuple_New(size);
522 if (!result)
523 return NULL;
524 for(k = 0; k < i; k++) {
525 elem = PyTuple_GetItem(arg, k);
526 Py_INCREF(elem);
527 PyTuple_SetItem(result, k, elem);
528 }
529 }
530 PyTuple_SetItem(result, i, newelem);
531 }
532 if (result)
533 return result;
534 /* Fall through, returning arg. */
535 }
536 else if (PyString_Check(arg)) {
537 int argc;
538 char **argv;
539 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000540
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000541 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
542 Py_INCREF(arg);
543 return arg;
544 }
545 Tcl_Free(FREECAST argv);
546 if (argc > 1)
547 return Split(PyString_AsString(arg));
548 /* Fall through, returning arg. */
549 }
550 Py_INCREF(arg);
551 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000552}
Barry Warsawfa701a81997-01-16 00:15:11 +0000553
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000554
Guido van Rossum18468821994-06-20 07:49:28 +0000555/**** Tkapp Object ****/
556
557#ifndef WITH_APPINIT
558int
Fred Drake509d79a2000-07-08 04:04:38 +0000559Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000560{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000561 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000562
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000563 if (Tcl_Init(interp) == TCL_ERROR) {
564 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
565 return TCL_ERROR;
566 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000567
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000568 _tkinter_skip_tk_init = Tcl_GetVar(interp,
569 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
570 if (_tkinter_skip_tk_init != NULL &&
571 strcmp(_tkinter_skip_tk_init, "1") == 0) {
572 return TCL_OK;
573 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000574
575#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000576 if (tk_load_failed) {
577 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
578 return TCL_ERROR;
579 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000580#endif
581
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000582 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000583#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000584 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000585#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000586 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
587 return TCL_ERROR;
588 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000589
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000590 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000591}
592#endif /* !WITH_APPINIT */
593
Guido van Rossum18468821994-06-20 07:49:28 +0000594
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000595
Barry Warsawfa701a81997-01-16 00:15:11 +0000596
597/* Initialize the Tk application; see the `main' function in
598 * `tkMain.c'.
599 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000600
Thomas Wouters58d05102000-07-24 14:43:35 +0000601static void EnableEventHook(void); /* Forward */
602static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000603
Barry Warsawfa701a81997-01-16 00:15:11 +0000604static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000605Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000606 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000607{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000608 TkappObject *v;
609 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000610
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 v = PyObject_New(TkappObject, &Tkapp_Type);
612 if (v == NULL)
613 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000614
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000615 v->interp = Tcl_CreateInterp();
616 v->wantobjects = wantobjects;
617 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
618 TCL_GLOBAL_ONLY) != NULL;
619 v->thread_id = Tcl_GetCurrentThread();
620 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000621
622#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000623 if (v->threaded) {
624 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
625 Py_DECREF(v);
626 return 0;
627 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000628#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000629#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000630 if (v->threaded && tcl_lock) {
631 /* If Tcl is threaded, we don't need the lock. */
632 PyThread_free_lock(tcl_lock);
633 tcl_lock = NULL;
634 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000635#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000636
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000637 v->BooleanType = Tcl_GetObjType("boolean");
638 v->ByteArrayType = Tcl_GetObjType("bytearray");
639 v->DoubleType = Tcl_GetObjType("double");
640 v->IntType = Tcl_GetObjType("int");
641 v->ListType = Tcl_GetObjType("list");
642 v->ProcBodyType = Tcl_GetObjType("procbody");
643 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000644
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000645 /* Delete the 'exit' command, which can screw things up */
646 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000647
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000648 if (screenName != NULL)
649 Tcl_SetVar2(v->interp, "env", "DISPLAY",
650 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000651
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000652 if (interactive)
653 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
654 else
655 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000656
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000657 /* This is used to get the application class for Tk 4.1 and up */
658 argv0 = (char*)ckalloc(strlen(className) + 1);
659 if (!argv0) {
660 PyErr_NoMemory();
661 Py_DECREF(v);
662 return NULL;
663 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000664
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000665 strcpy(argv0, className);
666 if (isupper(Py_CHARMASK(argv0[0])))
667 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
668 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
669 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000670
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000671 if (! wantTk) {
672 Tcl_SetVar(v->interp,
673 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
674 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000675#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000676 else if (tk_load_failed) {
677 Tcl_SetVar(v->interp,
678 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
679 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000680#endif
David Aschere2b4b322004-02-18 05:59:53 +0000681
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000682 /* some initial arguments need to be in argv */
683 if (sync || use) {
684 char *args;
685 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 if (sync)
688 len += sizeof "-sync";
689 if (use)
690 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 args = (char*)ckalloc(len);
693 if (!args) {
694 PyErr_NoMemory();
695 Py_DECREF(v);
696 return NULL;
697 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000698
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000699 args[0] = '\0';
700 if (sync)
701 strcat(args, "-sync");
702 if (use) {
703 if (sync)
704 strcat(args, " ");
705 strcat(args, "-use ");
706 strcat(args, use);
707 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000708
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000709 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
710 ckfree(args);
711 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000712
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000713 if (Tcl_AppInit(v->interp) != TCL_OK) {
714 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000715#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000716 if (wantTk) {
717 const char *_tkinter_tk_failed;
718 _tkinter_tk_failed = Tcl_GetVar(v->interp,
719 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000720
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000721 if ( _tkinter_tk_failed != NULL &&
722 strcmp(_tkinter_tk_failed, "1") == 0) {
723 tk_load_failed = 1;
724 }
725 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000726#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000727 Py_DECREF((PyObject *)v);
728 return (TkappObject *)result;
729 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000730
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000731 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000732
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000733 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000734}
735
Barry Warsawfa701a81997-01-16 00:15:11 +0000736
Guilherme Polo1972d162009-03-27 21:43:08 +0000737#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000738static void
739Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000740 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000741{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000742 Py_BEGIN_ALLOW_THREADS;
743 Tcl_MutexLock(mutex);
744 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
745 Tcl_ThreadAlert(self->thread_id);
746 Tcl_ConditionWait(cond, mutex, NULL);
747 Tcl_MutexUnlock(mutex);
748 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000749}
Guilherme Polo1972d162009-03-27 21:43:08 +0000750#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000751
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000752
Guido van Rossum18468821994-06-20 07:49:28 +0000753/** Tcl Eval **/
754
Martin v. Löwisffad6332002-11-26 09:28:05 +0000755typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 PyObject_HEAD
757 Tcl_Obj *value;
758 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000759} PyTclObject;
760
761staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000763
764static PyObject *
765newPyTclObject(Tcl_Obj *arg)
766{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 PyTclObject *self;
768 self = PyObject_New(PyTclObject, &PyTclObject_Type);
769 if (self == NULL)
770 return NULL;
771 Tcl_IncrRefCount(arg);
772 self->value = arg;
773 self->string = NULL;
774 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000775}
776
777static void
778PyTclObject_dealloc(PyTclObject *self)
779{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000780 Tcl_DecrRefCount(self->value);
781 Py_XDECREF(self->string);
782 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000783}
784
785static PyObject *
786PyTclObject_str(PyTclObject *self)
787{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000788 if (self->string && PyString_Check(self->string)) {
789 Py_INCREF(self->string);
790 return self->string;
791 }
792 /* XXX Could cache value if it is an ASCII string. */
793 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794}
795
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000796static char*
797PyTclObject_TclString(PyObject *self)
798{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000799 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000800}
801
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000802/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000803PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000804"the string representation of this object, either as string or Unicode");
805
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000806static PyObject *
807PyTclObject_string(PyTclObject *self, void *ignored)
808{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000809 char *s;
810 int i, len;
811 if (!self->string) {
812 s = Tcl_GetStringFromObj(self->value, &len);
813 for (i = 0; i < len; i++)
814 if (s[i] & 0x80)
815 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000816#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000817 if (i == len)
818 /* It is an ASCII string. */
819 self->string = PyString_FromStringAndSize(s, len);
820 else {
821 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
822 if (!self->string) {
823 PyErr_Clear();
824 self->string = PyString_FromStringAndSize(s, len);
825 }
826 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000827#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000828 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000829#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830 if (!self->string)
831 return NULL;
832 }
833 Py_INCREF(self->string);
834 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000835}
836
837#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000838PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
839
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000840static PyObject *
841PyTclObject_unicode(PyTclObject *self, void *ignored)
842{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000843 char *s;
844 int len;
845 if (self->string && PyUnicode_Check(self->string)) {
846 Py_INCREF(self->string);
847 return self->string;
848 }
849 /* XXX Could chache result if it is non-ASCII. */
850 s = Tcl_GetStringFromObj(self->value, &len);
851 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000852}
853#endif
854
Martin v. Löwisffad6332002-11-26 09:28:05 +0000855static PyObject *
856PyTclObject_repr(PyTclObject *self)
857{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000858 char buf[50];
859 PyOS_snprintf(buf, 50, "<%s object at %p>",
860 self->value->typePtr->name, self->value);
861 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862}
863
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000864static int
865PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
866{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000867 int res;
868 res = strcmp(Tcl_GetString(self->value),
869 Tcl_GetString(other->value));
870 if (res < 0) return -1;
871 if (res > 0) return 1;
872 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000873}
874
Martin v. Löwis39195712003-01-04 00:33:13 +0000875PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
876
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877static PyObject*
878get_typename(PyTclObject* obj, void* ignored)
879{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000880 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000881}
882
Martin v. Löwis39195712003-01-04 00:33:13 +0000883
Martin v. Löwisffad6332002-11-26 09:28:05 +0000884static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000885 {"typename", (getter)get_typename, NULL, get_typename__doc__},
886 {"string", (getter)PyTclObject_string, NULL,
887 PyTclObject_string__doc__},
888 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889};
890
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000891static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000892#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000893 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
894 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000895#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000896 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000897};
898
Martin v. Löwisffad6332002-11-26 09:28:05 +0000899statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000900 PyObject_HEAD_INIT(NULL)
901 0, /*ob_size*/
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject), /*tp_basicsize*/
904 0, /*tp_itemsize*/
905 /* methods */
906 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
907 0, /*tp_print*/
908 0, /*tp_getattr*/
909 0, /*tp_setattr*/
910 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
911 (reprfunc)PyTclObject_repr, /*tp_repr*/
912 0, /*tp_as_number*/
913 0, /*tp_as_sequence*/
914 0, /*tp_as_mapping*/
915 0, /*tp_hash*/
916 0, /*tp_call*/
917 (reprfunc)PyTclObject_str, /*tp_str*/
918 PyObject_GenericGetAttr,/*tp_getattro*/
919 0, /*tp_setattro*/
920 0, /*tp_as_buffer*/
921 Py_TPFLAGS_DEFAULT, /*tp_flags*/
922 0, /*tp_doc*/
923 0, /*tp_traverse*/
924 0, /*tp_clear*/
925 0, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
927 0, /*tp_iter*/
928 0, /*tp_iternext*/
929 PyTclObject_methods, /*tp_methods*/
930 0, /*tp_members*/
931 PyTclObject_getsetlist, /*tp_getset*/
932 0, /*tp_base*/
933 0, /*tp_dict*/
934 0, /*tp_descr_get*/
935 0, /*tp_descr_set*/
936 0, /*tp_dictoffset*/
937 0, /*tp_init*/
938 0, /*tp_alloc*/
939 0, /*tp_new*/
940 0, /*tp_free*/
941 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942};
943
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000944static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000945AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000946{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000947 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000948
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000949 if (PyString_Check(value))
950 return Tcl_NewStringObj(PyString_AS_STRING(value),
951 PyString_GET_SIZE(value));
952 else if (PyBool_Check(value))
953 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
954 else if (PyInt_Check(value))
955 return Tcl_NewLongObj(PyInt_AS_LONG(value));
956 else if (PyFloat_Check(value))
957 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
958 else if (PyTuple_Check(value)) {
959 Tcl_Obj **argv = (Tcl_Obj**)
960 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
961 int i;
962 if(!argv)
963 return 0;
964 for(i=0;i<PyTuple_Size(value);i++)
965 argv[i] = AsObj(PyTuple_GetItem(value,i));
966 result = Tcl_NewListObj(PyTuple_Size(value), argv);
967 ckfree(FREECAST argv);
968 return result;
969 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000970#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000971 else if (PyUnicode_Check(value)) {
972 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
973 Py_ssize_t size = PyUnicode_GET_SIZE(value);
974 /* This #ifdef assumes that Tcl uses UCS-2.
975 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +0000976#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000977 Tcl_UniChar *outbuf = NULL;
978 Py_ssize_t i;
979 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
980 if (allocsize >= size)
981 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
982 /* Else overflow occurred, and we take the next exit */
983 if (!outbuf) {
984 PyErr_NoMemory();
985 return NULL;
986 }
987 for (i = 0; i < size; i++) {
988 if (inbuf[i] >= 0x10000) {
989 /* Tcl doesn't do UTF-16, yet. */
990 PyErr_SetString(PyExc_ValueError,
991 "unsupported character");
992 ckfree(FREECAST outbuf);
993 return NULL;
994 }
995 outbuf[i] = inbuf[i];
996 }
997 result = Tcl_NewUnicodeObj(outbuf, size);
998 ckfree(FREECAST outbuf);
999 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001000#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001001 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001002#endif
1003
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001004 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001005#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001006 else if(PyTclObject_Check(value)) {
1007 Tcl_Obj *v = ((PyTclObject*)value)->value;
1008 Tcl_IncrRefCount(v);
1009 return v;
1010 }
1011 else {
1012 PyObject *v = PyObject_Str(value);
1013 if (!v)
1014 return 0;
1015 result = AsObj(v);
1016 Py_DECREF(v);
1017 return result;
1018 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001019}
1020
Martin v. Löwisffad6332002-11-26 09:28:05 +00001021static PyObject*
1022FromObj(PyObject* tkapp, Tcl_Obj *value)
1023{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001024 PyObject *result = NULL;
1025 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001027 if (value->typePtr == NULL) {
1028 /* If the result contains any bytes with the top bit set,
1029 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001030#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001031 int i;
1032 char *s = value->bytes;
1033 int len = value->length;
1034 for (i = 0; i < len; i++) {
1035 if (value->bytes[i] & 0x80)
1036 break;
1037 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001038
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001039 if (i == value->length)
1040 result = PyString_FromStringAndSize(s, len);
1041 else {
1042 /* Convert UTF-8 to Unicode string */
1043 result = PyUnicode_DecodeUTF8(s, len, "strict");
1044 if (result == NULL) {
1045 PyErr_Clear();
1046 result = PyString_FromStringAndSize(s, len);
1047 }
1048 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001049#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001050 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001051#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001052 return result;
1053 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001054
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001055 if (value->typePtr == app->BooleanType) {
1056 result = value->internalRep.longValue ? Py_True : Py_False;
1057 Py_INCREF(result);
1058 return result;
1059 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001060
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001061 if (value->typePtr == app->ByteArrayType) {
1062 int size;
1063 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1064 return PyString_FromStringAndSize(data, size);
1065 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001066
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001067 if (value->typePtr == app->DoubleType) {
1068 return PyFloat_FromDouble(value->internalRep.doubleValue);
1069 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001070
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001071 if (value->typePtr == app->IntType) {
1072 return PyInt_FromLong(value->internalRep.longValue);
1073 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 if (value->typePtr == app->ListType) {
1076 int size;
1077 int i, status;
1078 PyObject *elem;
1079 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001080
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001081 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1082 if (status == TCL_ERROR)
1083 return Tkinter_Error(tkapp);
1084 result = PyTuple_New(size);
1085 if (!result)
1086 return NULL;
1087 for (i = 0; i < size; i++) {
1088 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1089 value, i, &tcl_elem);
1090 if (status == TCL_ERROR) {
1091 Py_DECREF(result);
1092 return Tkinter_Error(tkapp);
1093 }
1094 elem = FromObj(tkapp, tcl_elem);
1095 if (!elem) {
1096 Py_DECREF(result);
1097 return NULL;
1098 }
1099 PyTuple_SetItem(result, i, elem);
1100 }
1101 return result;
1102 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001103
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001104 if (value->typePtr == app->ProcBodyType) {
1105 /* fall through: return tcl object. */
1106 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001107
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001108 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001109#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001110#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001111 PyObject *result;
1112 int size;
1113 Tcl_UniChar *input;
1114 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001115
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001116 size = Tcl_GetCharLength(value);
1117 result = PyUnicode_FromUnicode(NULL, size);
1118 if (!result)
1119 return NULL;
1120 input = Tcl_GetUnicode(value);
1121 output = PyUnicode_AS_UNICODE(result);
1122 while (size--)
1123 *output++ = *input++;
1124 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001125#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001126 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1127 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128#endif
1129#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001130 int size;
1131 char *c;
1132 c = Tcl_GetStringFromObj(value, &size);
1133 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001134#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001135 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001136
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001137 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138}
1139
Guilherme Polo1972d162009-03-27 21:43:08 +00001140#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001141/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001142TCL_DECLARE_MUTEX(call_mutex)
1143
1144typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001145 Tcl_Event ev; /* Must be first */
1146 TkappObject *self;
1147 PyObject *args;
1148 int flags;
1149 PyObject **res;
1150 PyObject **exc_type, **exc_value, **exc_tb;
1151 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001152} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001153#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001154
1155void
1156Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001157{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001158 int i;
1159 for (i = 0; i < objc; i++)
1160 Tcl_DecrRefCount(objv[i]);
1161 if (objv != objStore)
1162 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001163}
Guido van Rossum18468821994-06-20 07:49:28 +00001164
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001165/* Convert Python objects to Tcl objects. This must happen in the
1166 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001167
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001168static Tcl_Obj**
1169Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1170{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001171 Tcl_Obj **objv = objStore;
1172 int objc = 0, i;
1173 if (args == NULL)
1174 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001175
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001176 else if (!PyTuple_Check(args)) {
1177 objv[0] = AsObj(args);
1178 if (objv[0] == 0)
1179 goto finally;
1180 objc = 1;
1181 Tcl_IncrRefCount(objv[0]);
1182 }
1183 else {
1184 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001185
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001186 if (objc > ARGSZ) {
1187 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1188 if (objv == NULL) {
1189 PyErr_NoMemory();
1190 objc = 0;
1191 goto finally;
1192 }
1193 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001194
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001195 for (i = 0; i < objc; i++) {
1196 PyObject *v = PyTuple_GetItem(args, i);
1197 if (v == Py_None) {
1198 objc = i;
1199 break;
1200 }
1201 objv[i] = AsObj(v);
1202 if (!objv[i]) {
1203 /* Reset objc, so it attempts to clear
1204 objects only up to i. */
1205 objc = i;
1206 goto finally;
1207 }
1208 Tcl_IncrRefCount(objv[i]);
1209 }
1210 }
1211 *pobjc = objc;
1212 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 Tkapp_CallDeallocArgs(objv, objStore, objc);
1215 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216}
Guido van Rossum212643f1998-04-29 16:22:14 +00001217
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001219
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001220static PyObject*
1221Tkapp_CallResult(TkappObject *self)
1222{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001223 PyObject *res = NULL;
1224 if(self->wantobjects) {
1225 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1226 /* Not sure whether the IncrRef is necessary, but something
1227 may overwrite the interpreter result while we are
1228 converting it. */
1229 Tcl_IncrRefCount(value);
1230 res = FromObj((PyObject*)self, value);
1231 Tcl_DecrRefCount(value);
1232 } else {
1233 const char *s = Tcl_GetStringResult(self->interp);
1234 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001235
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001236 /* If the result contains any bytes with the top bit set,
1237 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001238#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001239 while (*p != '\0') {
1240 if (*p & 0x80)
1241 break;
1242 p++;
1243 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001244
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001245 if (*p == '\0')
1246 res = PyString_FromStringAndSize(s, (int)(p-s));
1247 else {
1248 /* Convert UTF-8 to Unicode string */
1249 p = strchr(p, '\0');
1250 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1251 if (res == NULL) {
1252 PyErr_Clear();
1253 res = PyString_FromStringAndSize(s, (int)(p-s));
1254 }
1255 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001256#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001257 p = strchr(p, '\0');
1258 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001259#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001260 }
1261 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262}
Guido van Rossum632de272000-03-29 00:19:50 +00001263
Guilherme Polo1972d162009-03-27 21:43:08 +00001264#ifdef WITH_THREAD
1265
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266/* Tkapp_CallProc is the event procedure that is executed in the context of
1267 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1268 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001269
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270static int
1271Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1272{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001273 Tcl_Obj *objStore[ARGSZ];
1274 Tcl_Obj **objv;
1275 int objc;
1276 int i;
1277 ENTER_PYTHON
1278 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1279 if (!objv) {
1280 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1281 *(e->res) = NULL;
1282 }
1283 LEAVE_PYTHON
1284 if (!objv)
1285 goto done;
1286 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1287 ENTER_PYTHON
1288 if (i == TCL_ERROR) {
1289 *(e->res) = NULL;
1290 *(e->exc_type) = NULL;
1291 *(e->exc_tb) = NULL;
1292 *(e->exc_value) = PyObject_CallFunction(
1293 Tkinter_TclError, "s",
1294 Tcl_GetStringResult(e->self->interp));
1295 }
1296 else {
1297 *(e->res) = Tkapp_CallResult(e->self);
1298 }
1299 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001300
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001301 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001302done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001303 /* Wake up calling thread. */
1304 Tcl_MutexLock(&call_mutex);
1305 Tcl_ConditionNotify(e->done);
1306 Tcl_MutexUnlock(&call_mutex);
1307 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308}
1309
Guilherme Polo1972d162009-03-27 21:43:08 +00001310#endif
1311
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312/* This is the main entry point for calling a Tcl command.
1313 It supports three cases, with regard to threading:
1314 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1315 the context of the calling thread.
1316 2. Tcl is threaded, caller of the command is in the interpreter thread:
1317 Execute the command in the calling thread. Since the Tcl lock will
1318 not be used, we can merge that with case 1.
1319 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1320 the interpreter thread. Allocation of Tcl objects needs to occur in the
1321 interpreter thread, so we ship the PyObject* args to the target thread,
1322 and perform processing there. */
1323
1324static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001325Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001327 Tcl_Obj *objStore[ARGSZ];
1328 Tcl_Obj **objv = NULL;
1329 int objc, i;
1330 PyObject *res = NULL;
1331 TkappObject *self = (TkappObject*)selfptr;
1332 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001333
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001334 /* If args is a single tuple, replace with contents of tuple */
1335 if (1 == PyTuple_Size(args)){
1336 PyObject* item = PyTuple_GetItem(args, 0);
1337 if (PyTuple_Check(item))
1338 args = item;
1339 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001340#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001341 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1342 /* We cannot call the command directly. Instead, we must
1343 marshal the parameters to the interpreter thread. */
1344 Tkapp_CallEvent *ev;
1345 Tcl_Condition cond = NULL;
1346 PyObject *exc_type, *exc_value, *exc_tb;
1347 if (!WaitForMainloop(self))
1348 return NULL;
1349 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1350 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1351 ev->self = self;
1352 ev->args = args;
1353 ev->res = &res;
1354 ev->exc_type = &exc_type;
1355 ev->exc_value = &exc_value;
1356 ev->exc_tb = &exc_tb;
1357 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001358
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001359 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001361 if (res == NULL) {
1362 if (exc_type)
1363 PyErr_Restore(exc_type, exc_value, exc_tb);
1364 else
1365 PyErr_SetObject(Tkinter_TclError, exc_value);
1366 }
1367 Tcl_ConditionFinalize(&cond);
1368 }
1369 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001370#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001371 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001373 objv = Tkapp_CallArgs(args, objStore, &objc);
1374 if (!objv)
1375 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001377 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001379 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001381 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001383 if (i == TCL_ERROR)
1384 Tkinter_Error(selfptr);
1385 else
1386 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001388 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001390 Tkapp_CallDeallocArgs(objv, objStore, objc);
1391 }
1392 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001393}
1394
1395
1396static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001397Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001398{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001399 /* Could do the same here as for Tkapp_Call(), but this is not used
1400 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1401 way for the user to do what all its Global* variants do (save and
1402 reset the scope pointer, call the local version, restore the saved
1403 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001404
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001405 char *cmd;
1406 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001407
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001408 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001410 cmd = Merge(args);
1411 if (cmd) {
1412 int err;
1413 ENTER_TCL
1414 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1415 ENTER_OVERLAP
1416 if (err == TCL_ERROR)
1417 res = Tkinter_Error(self);
1418 else
1419 res = PyString_FromString(Tkapp_Result(self));
1420 LEAVE_OVERLAP_TCL
1421 ckfree(cmd);
1422 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001423
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001424 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001425}
1426
1427static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001428Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001429{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001430 char *script;
1431 PyObject *res = NULL;
1432 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001433
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001434 if (!PyArg_ParseTuple(args, "s:eval", &script))
1435 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001436
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001437 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001439 ENTER_TCL
1440 err = Tcl_Eval(Tkapp_Interp(self), script);
1441 ENTER_OVERLAP
1442 if (err == TCL_ERROR)
1443 res = Tkinter_Error(self);
1444 else
1445 res = PyString_FromString(Tkapp_Result(self));
1446 LEAVE_OVERLAP_TCL
1447 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001448}
1449
1450static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001451Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001452{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001453 char *script;
1454 PyObject *res = NULL;
1455 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001456
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001457 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1458 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001459
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001460 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 ENTER_TCL
1463 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1464 ENTER_OVERLAP
1465 if (err == TCL_ERROR)
1466 res = Tkinter_Error(self);
1467 else
1468 res = PyString_FromString(Tkapp_Result(self));
1469 LEAVE_OVERLAP_TCL
1470 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001471}
1472
1473static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001474Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001475{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 char *fileName;
1477 PyObject *res = NULL;
1478 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001479
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001480 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1481 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001482
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001483 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001484
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001485 ENTER_TCL
1486 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1487 ENTER_OVERLAP
1488 if (err == TCL_ERROR)
1489 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001491 else
1492 res = PyString_FromString(Tkapp_Result(self));
1493 LEAVE_OVERLAP_TCL
1494 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001495}
1496
1497static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001498Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001499{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001500 char *script;
1501 PyObject *res = NULL;
1502 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001503
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001504 if (!PyArg_ParseTuple(args, "s", &script))
1505 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001506
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001507 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001509 ENTER_TCL
1510 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1511 ENTER_OVERLAP
1512 if (err == TCL_ERROR)
1513 res = Tkinter_Error(self);
1514 else
1515 res = PyString_FromString(Tkapp_Result(self));
1516 LEAVE_OVERLAP_TCL
1517 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001518}
1519
1520static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001521Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001522{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001523 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001524
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001525 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1526 return NULL;
1527 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001528
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001529 ENTER_TCL
1530 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1531 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001533 Py_INCREF(Py_None);
1534 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001535}
1536
Barry Warsawfa701a81997-01-16 00:15:11 +00001537
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001538
Guido van Rossum18468821994-06-20 07:49:28 +00001539/** Tcl Variable **/
1540
Guilherme Polo1972d162009-03-27 21:43:08 +00001541typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1542
1543#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001544TCL_DECLARE_MUTEX(var_mutex)
1545
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001546typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001547 Tcl_Event ev; /* must be first */
1548 PyObject *self;
1549 PyObject *args;
1550 int flags;
1551 EventFunc func;
1552 PyObject **res;
1553 PyObject **exc_type;
1554 PyObject **exc_val;
1555 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001556} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001557#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001559static int
1560varname_converter(PyObject *in, void *_out)
1561{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001562 char **out = (char**)_out;
1563 if (PyString_Check(in)) {
1564 *out = PyString_AsString(in);
1565 return 1;
1566 }
1567 if (PyTclObject_Check(in)) {
1568 *out = PyTclObject_TclString(in);
1569 return 1;
1570 }
1571 /* XXX: Should give diagnostics. */
1572 return 0;
1573}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001574
Guilherme Polo1972d162009-03-27 21:43:08 +00001575#ifdef WITH_THREAD
1576
Martin v. Löwis111c1802008-06-13 07:47:47 +00001577static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578var_perform(VarEvent *ev)
1579{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001580 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1581 if (!*(ev->res)) {
1582 PyObject *exc, *val, *tb;
1583 PyErr_Fetch(&exc, &val, &tb);
1584 PyErr_NormalizeException(&exc, &val, &tb);
1585 *(ev->exc_type) = exc;
1586 *(ev->exc_val) = val;
1587 Py_DECREF(tb);
1588 }
1589
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001590}
1591
1592static int
1593var_proc(VarEvent* ev, int flags)
1594{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001595 ENTER_PYTHON
1596 var_perform(ev);
1597 Tcl_MutexLock(&var_mutex);
1598 Tcl_ConditionNotify(ev->cond);
1599 Tcl_MutexUnlock(&var_mutex);
1600 LEAVE_PYTHON
1601 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602}
1603
Guilherme Polo1972d162009-03-27 21:43:08 +00001604#endif
1605
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001606static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001607var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001608{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001609#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001610 TkappObject *self = (TkappObject*)selfptr;
1611 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1612 TkappObject *self = (TkappObject*)selfptr;
1613 VarEvent *ev;
1614 PyObject *res, *exc_type, *exc_val;
1615 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001616
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001617 /* The current thread is not the interpreter thread. Marshal
1618 the call to the interpreter thread, then wait for
1619 completion. */
1620 if (!WaitForMainloop(self))
1621 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001622
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001623 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1624
1625 ev->self = selfptr;
1626 ev->args = args;
1627 ev->flags = flags;
1628 ev->func = func;
1629 ev->res = &res;
1630 ev->exc_type = &exc_type;
1631 ev->exc_val = &exc_val;
1632 ev->cond = &cond;
1633 ev->ev.proc = (Tcl_EventProc*)var_proc;
1634 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1635 Tcl_ConditionFinalize(&cond);
1636 if (!res) {
1637 PyErr_SetObject(exc_type, exc_val);
1638 Py_DECREF(exc_type);
1639 Py_DECREF(exc_val);
1640 return NULL;
1641 }
1642 return res;
1643 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001644#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001645 /* Tcl is not threaded, or this is the interpreter thread. */
1646 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001647}
1648
Guido van Rossum18468821994-06-20 07:49:28 +00001649static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001650SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001651{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001652 char *name1, *name2;
1653 PyObject *newValue;
1654 PyObject *res = NULL;
1655 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001656
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001657 if (PyArg_ParseTuple(args, "O&O:setvar",
1658 varname_converter, &name1, &newValue)) {
1659 /* XXX Acquire tcl lock??? */
1660 newval = AsObj(newValue);
1661 if (newval == NULL)
1662 return NULL;
1663 ENTER_TCL
1664 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1665 newval, flags);
1666 ENTER_OVERLAP
1667 if (!ok)
1668 Tkinter_Error(self);
1669 else {
1670 res = Py_None;
1671 Py_INCREF(res);
1672 }
1673 LEAVE_OVERLAP_TCL
1674 }
1675 else {
1676 PyErr_Clear();
1677 if (PyArg_ParseTuple(args, "ssO:setvar",
1678 &name1, &name2, &newValue)) {
1679 /* XXX must hold tcl lock already??? */
1680 newval = AsObj(newValue);
1681 ENTER_TCL
1682 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1683 ENTER_OVERLAP
1684 if (!ok)
1685 Tkinter_Error(self);
1686 else {
1687 res = Py_None;
1688 Py_INCREF(res);
1689 }
1690 LEAVE_OVERLAP_TCL
1691 }
1692 else {
1693 return NULL;
1694 }
1695 }
1696 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001697}
1698
1699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001700Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001701{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001702 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001703}
1704
1705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001706Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001707{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001708 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001709}
1710
Barry Warsawfa701a81997-01-16 00:15:11 +00001711
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001712
Guido van Rossum18468821994-06-20 07:49:28 +00001713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001716 char *name1, *name2=NULL;
1717 PyObject *res = NULL;
1718 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001719
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001720 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1721 varname_converter, &name1, &name2))
1722 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001723
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001724 ENTER_TCL
1725 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1726 ENTER_OVERLAP
1727 if (tres == NULL) {
1728 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1729 } else {
1730 if (((TkappObject*)self)->wantobjects) {
1731 res = FromObj(self, tres);
1732 }
1733 else {
1734 res = PyString_FromString(Tcl_GetString(tres));
1735 }
1736 }
1737 LEAVE_OVERLAP_TCL
1738 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001739}
1740
1741static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001742Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001743{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001744 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001745}
1746
1747static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001748Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001749{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001750 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001751}
1752
Barry Warsawfa701a81997-01-16 00:15:11 +00001753
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001754
Guido van Rossum18468821994-06-20 07:49:28 +00001755static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001756UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001757{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001758 char *name1, *name2=NULL;
1759 int code;
1760 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001762 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1763 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001764
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001765 ENTER_TCL
1766 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1767 ENTER_OVERLAP
1768 if (code == TCL_ERROR)
1769 res = Tkinter_Error(self);
1770 else {
1771 Py_INCREF(Py_None);
1772 res = Py_None;
1773 }
1774 LEAVE_OVERLAP_TCL
1775 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
1778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001781 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001782}
1783
1784static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001785Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001786{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001787 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
Barry Warsawfa701a81997-01-16 00:15:11 +00001790
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791
Guido van Rossum18468821994-06-20 07:49:28 +00001792/** Tcl to Python **/
1793
1794static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001795Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001796{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001797 char *s;
1798 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001799
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001800 if (PyTuple_Size(args) == 1) {
1801 PyObject* o = PyTuple_GetItem(args, 0);
1802 if (PyInt_Check(o)) {
1803 Py_INCREF(o);
1804 return o;
1805 }
1806 }
1807 if (!PyArg_ParseTuple(args, "s:getint", &s))
1808 return NULL;
1809 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1810 return Tkinter_Error(self);
1811 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001817 char *s;
1818 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001819
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001820 if (PyTuple_Size(args) == 1) {
1821 PyObject *o = PyTuple_GetItem(args, 0);
1822 if (PyFloat_Check(o)) {
1823 Py_INCREF(o);
1824 return o;
1825 }
1826 }
1827 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1828 return NULL;
1829 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1830 return Tkinter_Error(self);
1831 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001832}
1833
1834static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001835Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001836{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001837 char *s;
1838 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001839
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001840 if (PyTuple_Size(args) == 1) {
1841 PyObject *o = PyTuple_GetItem(args, 0);
1842 if (PyInt_Check(o)) {
1843 Py_INCREF(o);
1844 return o;
1845 }
1846 }
1847 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1848 return NULL;
1849 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1850 return Tkinter_Error(self);
1851 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001852}
1853
1854static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001855Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001856{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001857 char *s;
1858 PyObject *res = NULL;
1859 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001861 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1862 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001863
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001864 CHECK_TCL_APPARTMENT;
1865
1866 ENTER_TCL
1867 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1868 ENTER_OVERLAP
1869 if (retval == TCL_ERROR)
1870 res = Tkinter_Error(self);
1871 else
1872 res = Py_BuildValue("s", Tkapp_Result(self));
1873 LEAVE_OVERLAP_TCL
1874 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
1877static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001878Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001879{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001880 char *s;
1881 PyObject *res = NULL;
1882 int retval;
1883 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001884
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001885 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1886 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001887
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001888 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001889
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001890 ENTER_TCL
1891 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1892 ENTER_OVERLAP
1893 if (retval == TCL_ERROR)
1894 res = Tkinter_Error(self);
1895 else
1896 res = Py_BuildValue("l", v);
1897 LEAVE_OVERLAP_TCL
1898 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001899}
1900
1901static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001902Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001903{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001904 char *s;
1905 PyObject *res = NULL;
1906 double v;
1907 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1910 return NULL;
1911 CHECK_TCL_APPARTMENT;
1912 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1913 ENTER_TCL
1914 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1915 ENTER_OVERLAP
1916 PyFPE_END_PROTECT(retval)
1917 if (retval == TCL_ERROR)
1918 res = Tkinter_Error(self);
1919 else
1920 res = Py_BuildValue("d", v);
1921 LEAVE_OVERLAP_TCL
1922 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001923}
1924
1925static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001926Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001927{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001928 char *s;
1929 PyObject *res = NULL;
1930 int retval;
1931 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001932
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001933 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1934 return NULL;
1935 CHECK_TCL_APPARTMENT;
1936 ENTER_TCL
1937 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1938 ENTER_OVERLAP
1939 if (retval == TCL_ERROR)
1940 res = Tkinter_Error(self);
1941 else
1942 res = Py_BuildValue("i", v);
1943 LEAVE_OVERLAP_TCL
1944 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001945}
1946
Barry Warsawfa701a81997-01-16 00:15:11 +00001947
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001948
Guido van Rossum18468821994-06-20 07:49:28 +00001949static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001950Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001951{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001952 char *list;
1953 int argc;
1954 char **argv;
1955 PyObject *v;
1956 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001957
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001958 if (PyTuple_Size(args) == 1) {
1959 v = PyTuple_GetItem(args, 0);
1960 if (PyTuple_Check(v)) {
1961 Py_INCREF(v);
1962 return v;
1963 }
1964 }
1965 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1966 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001967
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001968 if (Tcl_SplitList(Tkapp_Interp(self), list,
1969 &argc, &argv) == TCL_ERROR) {
1970 PyMem_Free(list);
1971 return Tkinter_Error(self);
1972 }
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001974 if (!(v = PyTuple_New(argc)))
1975 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001976
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001977 for (i = 0; i < argc; i++) {
1978 PyObject *s = PyString_FromString(argv[i]);
1979 if (!s || PyTuple_SetItem(v, i, s)) {
1980 Py_DECREF(v);
1981 v = NULL;
1982 goto finally;
1983 }
1984 }
Guido van Rossum18468821994-06-20 07:49:28 +00001985
Barry Warsawfa701a81997-01-16 00:15:11 +00001986 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001987 ckfree(FREECAST argv);
1988 PyMem_Free(list);
1989 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001990}
1991
1992static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001993Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001994{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001995 PyObject *v;
1996 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001997
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001998 if (PyTuple_Size(args) == 1) {
1999 PyObject* o = PyTuple_GetItem(args, 0);
2000 if (PyTuple_Check(o)) {
2001 o = SplitObj(o);
2002 return o;
2003 }
2004 }
2005 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2006 return NULL;
2007 v = Split(list);
2008 PyMem_Free(list);
2009 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002010}
2011
2012static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002013Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002014{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002015 char *s = Merge(args);
2016 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002017
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002018 if (s) {
2019 res = PyString_FromString(s);
2020 ckfree(s);
2021 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002022
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002023 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002024}
2025
Barry Warsawfa701a81997-01-16 00:15:11 +00002026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002027
Guido van Rossum18468821994-06-20 07:49:28 +00002028/** Tcl Command **/
2029
Guido van Rossum00d93061998-05-28 23:06:38 +00002030/* Client data struct */
2031typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002032 PyObject *self;
2033 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002034} PythonCmd_ClientData;
2035
2036static int
Fred Drake509d79a2000-07-08 04:04:38 +00002037PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002038{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002039 errorInCmd = 1;
2040 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2041 LEAVE_PYTHON
2042 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002043}
2044
Guido van Rossum18468821994-06-20 07:49:28 +00002045/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002046 * function or method.
2047 */
Guido van Rossum18468821994-06-20 07:49:28 +00002048static int
Fred Drake509d79a2000-07-08 04:04:38 +00002049PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002050{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002051 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2052 PyObject *func, *arg, *res;
2053 int i, rv;
2054 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002055
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002056 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002057
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002058 /* TBD: no error checking here since we know, via the
2059 * Tkapp_CreateCommand() that the client data is a two-tuple
2060 */
2061 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002062
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002063 /* Create argument list (argv1, ..., argvN) */
2064 if (!(arg = PyTuple_New(argc - 1)))
2065 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002066
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002067 for (i = 0; i < (argc - 1); i++) {
2068 PyObject *s = PyString_FromString(argv[i + 1]);
2069 if (!s || PyTuple_SetItem(arg, i, s)) {
2070 Py_DECREF(arg);
2071 return PythonCmd_Error(interp);
2072 }
2073 }
2074 res = PyEval_CallObject(func, arg);
2075 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002076
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002077 if (res == NULL)
2078 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002079
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002080 obj_res = AsObj(res);
2081 if (obj_res == NULL) {
2082 Py_DECREF(res);
2083 return PythonCmd_Error(interp);
2084 }
2085 else {
2086 Tcl_SetObjResult(interp, obj_res);
2087 rv = TCL_OK;
2088 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002089
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002090 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002095}
2096
2097static void
Fred Drake509d79a2000-07-08 04:04:38 +00002098PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002099{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002100 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002101
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002102 ENTER_PYTHON
2103 Py_XDECREF(data->self);
2104 Py_XDECREF(data->func);
2105 PyMem_DEL(data);
2106 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002107}
2108
Barry Warsawfa701a81997-01-16 00:15:11 +00002109
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002110
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002111
Guilherme Polo1972d162009-03-27 21:43:08 +00002112#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002113TCL_DECLARE_MUTEX(command_mutex)
2114
2115typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002116 Tcl_Event ev;
2117 Tcl_Interp* interp;
2118 char *name;
2119 int create;
2120 int *status;
2121 ClientData *data;
2122 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002123} CommandEvent;
2124
2125static int
2126Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002127{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002128 if (ev->create)
2129 *ev->status = Tcl_CreateCommand(
2130 ev->interp, ev->name, PythonCmd,
2131 ev->data, PythonCmdDelete) == NULL;
2132 else
2133 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2134 Tcl_MutexLock(&command_mutex);
2135 Tcl_ConditionNotify(ev->done);
2136 Tcl_MutexUnlock(&command_mutex);
2137 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002138}
Guilherme Polo1972d162009-03-27 21:43:08 +00002139#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002140
2141static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002142Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002143{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002144 TkappObject *self = (TkappObject*)selfptr;
2145 PythonCmd_ClientData *data;
2146 char *cmdName;
2147 PyObject *func;
2148 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002149
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002150 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2151 return NULL;
2152 if (!PyCallable_Check(func)) {
2153 PyErr_SetString(PyExc_TypeError, "command not callable");
2154 return NULL;
2155 }
Guido van Rossum18468821994-06-20 07:49:28 +00002156
Martin v. Löwisa9656492003-03-30 08:44:58 +00002157#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002158 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2159 !WaitForMainloop(self))
2160 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002161#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002162
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002163 data = PyMem_NEW(PythonCmd_ClientData, 1);
2164 if (!data)
2165 return PyErr_NoMemory();
2166 Py_INCREF(self);
2167 Py_INCREF(func);
2168 data->self = selfptr;
2169 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002170
2171#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002172 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2173 Tcl_Condition cond = NULL;
2174 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2175 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2176 ev->interp = self->interp;
2177 ev->create = 1;
2178 ev->name = cmdName;
2179 ev->data = (ClientData)data;
2180 ev->status = &err;
2181 ev->done = &cond;
2182 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2183 Tcl_ConditionFinalize(&cond);
2184 }
2185 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002186#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002187 {
2188 ENTER_TCL
2189 err = Tcl_CreateCommand(
2190 Tkapp_Interp(self), cmdName, PythonCmd,
2191 (ClientData)data, PythonCmdDelete) == NULL;
2192 LEAVE_TCL
2193 }
2194 if (err) {
2195 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2196 PyMem_DEL(data);
2197 return NULL;
2198 }
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002200 Py_INCREF(Py_None);
2201 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002202}
2203
Barry Warsawfa701a81997-01-16 00:15:11 +00002204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002205
Guido van Rossum18468821994-06-20 07:49:28 +00002206static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002207Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002208{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 TkappObject *self = (TkappObject*)selfptr;
2210 char *cmdName;
2211 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002212
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002213 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2214 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002215
2216#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002217 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2218 Tcl_Condition cond = NULL;
2219 CommandEvent *ev;
2220 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2221 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2222 ev->interp = self->interp;
2223 ev->create = 0;
2224 ev->name = cmdName;
2225 ev->status = &err;
2226 ev->done = &cond;
2227 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2228 &command_mutex);
2229 Tcl_ConditionFinalize(&cond);
2230 }
2231 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002232#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002233 {
2234 ENTER_TCL
2235 err = Tcl_DeleteCommand(self->interp, cmdName);
2236 LEAVE_TCL
2237 }
2238 if (err == -1) {
2239 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2240 return NULL;
2241 }
2242 Py_INCREF(Py_None);
2243 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002244}
2245
Barry Warsawfa701a81997-01-16 00:15:11 +00002246
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002247
Guido van Rossum00d93061998-05-28 23:06:38 +00002248#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002249/** File Handler **/
2250
Guido van Rossum00d93061998-05-28 23:06:38 +00002251typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002252 PyObject *func;
2253 PyObject *file;
2254 int id;
2255 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002256} FileHandler_ClientData;
2257
2258static FileHandler_ClientData *HeadFHCD;
2259
2260static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002261NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002262{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002263 FileHandler_ClientData *p;
2264 p = PyMem_NEW(FileHandler_ClientData, 1);
2265 if (p != NULL) {
2266 Py_XINCREF(func);
2267 Py_XINCREF(file);
2268 p->func = func;
2269 p->file = file;
2270 p->id = id;
2271 p->next = HeadFHCD;
2272 HeadFHCD = p;
2273 }
2274 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002275}
2276
2277static void
Fred Drake509d79a2000-07-08 04:04:38 +00002278DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002279{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002280 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002281
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002282 pp = &HeadFHCD;
2283 while ((p = *pp) != NULL) {
2284 if (p->id == id) {
2285 *pp = p->next;
2286 Py_XDECREF(p->func);
2287 Py_XDECREF(p->file);
2288 PyMem_DEL(p);
2289 }
2290 else
2291 pp = &p->next;
2292 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002293}
2294
Guido van Rossuma597dde1995-01-10 20:56:29 +00002295static void
Fred Drake509d79a2000-07-08 04:04:38 +00002296FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002297{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002298 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2299 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002301 ENTER_PYTHON
2302 func = data->func;
2303 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002304
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002305 arg = Py_BuildValue("(Oi)", file, (long) mask);
2306 res = PyEval_CallObject(func, arg);
2307 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002308
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002309 if (res == NULL) {
2310 errorInCmd = 1;
2311 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2312 }
2313 Py_XDECREF(res);
2314 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002315}
2316
Guido van Rossum18468821994-06-20 07:49:28 +00002317static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002318Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2319 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002320{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002321 FileHandler_ClientData *data;
2322 PyObject *file, *func;
2323 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002324
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002325 if (!self && Py_Py3kWarningFlag) {
2326 if (PyErr_Warn(PyExc_DeprecationWarning,
2327 "_tkinter.createfilehandler is gone in 3.x") < 0)
2328 return NULL;
2329 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002330
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002331 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2332 &file, &mask, &func))
2333 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002334
Martin v. Löwisa9656492003-03-30 08:44:58 +00002335#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002336 if (!self && !tcl_lock) {
2337 /* We don't have the Tcl lock since Tcl is threaded. */
2338 PyErr_SetString(PyExc_RuntimeError,
2339 "_tkinter.createfilehandler not supported "
2340 "for threaded Tcl");
2341 return NULL;
2342 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002343#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002344
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002345 if (self) {
2346 CHECK_TCL_APPARTMENT;
2347 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002348
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002349 tfile = PyObject_AsFileDescriptor(file);
2350 if (tfile < 0)
2351 return NULL;
2352 if (!PyCallable_Check(func)) {
2353 PyErr_SetString(PyExc_TypeError, "bad argument list");
2354 return NULL;
2355 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002356
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002357 data = NewFHCD(func, file, tfile);
2358 if (data == NULL)
2359 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002360
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002361 /* Ought to check for null Tcl_File object... */
2362 ENTER_TCL
2363 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2364 LEAVE_TCL
2365 Py_INCREF(Py_None);
2366 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002367}
2368
2369static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002370Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002371{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002372 PyObject *file;
2373 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002375 if (!self && Py_Py3kWarningFlag) {
2376 if (PyErr_Warn(PyExc_DeprecationWarning,
2377 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2378 return NULL;
2379 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002381 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2382 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002383
Martin v. Löwisa9656492003-03-30 08:44:58 +00002384#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002385 if (!self && !tcl_lock) {
2386 /* We don't have the Tcl lock since Tcl is threaded. */
2387 PyErr_SetString(PyExc_RuntimeError,
2388 "_tkinter.deletefilehandler not supported "
2389 "for threaded Tcl");
2390 return NULL;
2391 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002392#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002393
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002394 if (self) {
2395 CHECK_TCL_APPARTMENT;
2396 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002397
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002398 tfile = PyObject_AsFileDescriptor(file);
2399 if (tfile < 0)
2400 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002402 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002403
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002404 /* Ought to check for null Tcl_File object... */
2405 ENTER_TCL
2406 Tcl_DeleteFileHandler(tfile);
2407 LEAVE_TCL
2408 Py_INCREF(Py_None);
2409 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002410}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002411#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002413
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414/**** Tktt Object (timer token) ****/
2415
Jeremy Hylton938ace62002-07-17 16:30:39 +00002416static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002417
Guido van Rossum00d93061998-05-28 23:06:38 +00002418typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002419 PyObject_HEAD
2420 Tcl_TimerToken token;
2421 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002422} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002423
2424static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002425Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002426{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002427 TkttObject *v = (TkttObject *)self;
2428 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002429
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002430 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2431 return NULL;
2432 if (v->token != NULL) {
2433 Tcl_DeleteTimerHandler(v->token);
2434 v->token = NULL;
2435 }
2436 if (func != NULL) {
2437 v->func = NULL;
2438 Py_DECREF(func);
2439 Py_DECREF(v); /* See Tktt_New() */
2440 }
2441 Py_INCREF(Py_None);
2442 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443}
2444
2445static PyMethodDef Tktt_methods[] =
2446{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002447 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2448 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002449};
2450
2451static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002452Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002454 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 v = PyObject_New(TkttObject, &Tktt_Type);
2457 if (v == NULL)
2458 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002459
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002460 Py_INCREF(func);
2461 v->token = NULL;
2462 v->func = func;
2463
2464 /* Extra reference, deleted when called or when handler is deleted */
2465 Py_INCREF(v);
2466 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002467}
2468
2469static void
Fred Drake509d79a2000-07-08 04:04:38 +00002470Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002471{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002472 TkttObject *v = (TkttObject *)self;
2473 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002474
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002475 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002476
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002477 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478}
2479
Guido van Rossum597ac201998-05-12 14:36:19 +00002480static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002481Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002482{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002483 TkttObject *v = (TkttObject *)self;
2484 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002486 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2487 v->func == NULL ? ", handler deleted" : "");
2488 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002489}
2490
2491static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002492Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002493{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002494 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002495}
2496
2497static PyTypeObject Tktt_Type =
2498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002499 PyVarObject_HEAD_INIT(NULL, 0)
2500 "tktimertoken", /*tp_name */
2501 sizeof(TkttObject), /*tp_basicsize */
2502 0, /*tp_itemsize */
2503 Tktt_Dealloc, /*tp_dealloc */
2504 0, /*tp_print */
2505 Tktt_GetAttr, /*tp_getattr */
2506 0, /*tp_setattr */
2507 0, /*tp_compare */
2508 Tktt_Repr, /*tp_repr */
2509 0, /*tp_as_number */
2510 0, /*tp_as_sequence */
2511 0, /*tp_as_mapping */
2512 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002513};
2514
Barry Warsawfa701a81997-01-16 00:15:11 +00002515
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002516
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002517/** Timer Handler **/
2518
2519static void
Fred Drake509d79a2000-07-08 04:04:38 +00002520TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002521{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002522 TkttObject *v = (TkttObject *)clientData;
2523 PyObject *func = v->func;
2524 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002525
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002526 if (func == NULL)
2527 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002528
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002529 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002531 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002533 res = PyEval_CallObject(func, NULL);
2534 Py_DECREF(func);
2535 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002536
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002537 if (res == NULL) {
2538 errorInCmd = 1;
2539 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2540 }
2541 else
2542 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002543
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002544 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002545}
2546
2547static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002548Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002549{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002550 int milliseconds;
2551 PyObject *func;
2552 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002553
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002554 if (!self && Py_Py3kWarningFlag) {
2555 if (PyErr_Warn(PyExc_DeprecationWarning,
2556 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2557 return NULL;
2558 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002559
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002560 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2561 &milliseconds, &func))
2562 return NULL;
2563 if (!PyCallable_Check(func)) {
2564 PyErr_SetString(PyExc_TypeError, "bad argument list");
2565 return NULL;
2566 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002567
Martin v. Löwisa9656492003-03-30 08:44:58 +00002568#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002569 if (!self && !tcl_lock) {
2570 /* We don't have the Tcl lock since Tcl is threaded. */
2571 PyErr_SetString(PyExc_RuntimeError,
2572 "_tkinter.createtimerhandler not supported "
2573 "for threaded Tcl");
2574 return NULL;
2575 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002576#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002577
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002578 if (self) {
2579 CHECK_TCL_APPARTMENT;
2580 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002581
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002582 v = Tktt_New(func);
2583 if (v) {
2584 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2585 (ClientData)v);
2586 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002587
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002588 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002589}
2590
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002591
Guido van Rossum18468821994-06-20 07:49:28 +00002592/** Event Loop **/
2593
Guido van Rossum18468821994-06-20 07:49:28 +00002594static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002595Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002596{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002597 int threshold = 0;
2598 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002599#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002600 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002601#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002602
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002603 if (!self && Py_Py3kWarningFlag) {
2604 if (PyErr_Warn(PyExc_DeprecationWarning,
2605 "_tkinter.mainloop is gone in 3.x") < 0)
2606 return NULL;
2607 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002608
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002609 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2610 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002611
Martin v. Löwisa9656492003-03-30 08:44:58 +00002612#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002613 if (!self && !tcl_lock) {
2614 /* We don't have the Tcl lock since Tcl is threaded. */
2615 PyErr_SetString(PyExc_RuntimeError,
2616 "_tkinter.mainloop not supported "
2617 "for threaded Tcl");
2618 return NULL;
2619 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002620#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002621
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002622 if (self) {
2623 CHECK_TCL_APPARTMENT;
2624 self->dispatching = 1;
2625 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002626
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002627 quitMainLoop = 0;
2628 while (Tk_GetNumMainWindows() > threshold &&
2629 !quitMainLoop &&
2630 !errorInCmd)
2631 {
2632 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002633
2634#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002635 if (self && self->threaded) {
2636 /* Allow other Python threads to run. */
2637 ENTER_TCL
2638 result = Tcl_DoOneEvent(0);
2639 LEAVE_TCL
2640 }
2641 else {
2642 Py_BEGIN_ALLOW_THREADS
2643 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2644 tcl_tstate = tstate;
2645 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2646 tcl_tstate = NULL;
2647 if(tcl_lock)PyThread_release_lock(tcl_lock);
2648 if (result == 0)
2649 Sleep(Tkinter_busywaitinterval);
2650 Py_END_ALLOW_THREADS
2651 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002652#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002653 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002654#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002655
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002656 if (PyErr_CheckSignals() != 0) {
2657 if (self)
2658 self->dispatching = 0;
2659 return NULL;
2660 }
2661 if (result < 0)
2662 break;
2663 }
2664 if (self)
2665 self->dispatching = 0;
2666 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002667
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002668 if (errorInCmd) {
2669 errorInCmd = 0;
2670 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2671 excInCmd = valInCmd = trbInCmd = NULL;
2672 return NULL;
2673 }
2674 Py_INCREF(Py_None);
2675 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002676}
2677
2678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002679Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002680{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002681 int flags = 0;
2682 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002684 if (!self && Py_Py3kWarningFlag) {
2685 if (PyErr_Warn(PyExc_DeprecationWarning,
2686 "_tkinter.dooneevent is gone in 3.x") < 0)
2687 return NULL;
2688 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002689
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002690 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2691 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002692
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002693 ENTER_TCL
2694 rv = Tcl_DoOneEvent(flags);
2695 LEAVE_TCL
2696 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002697}
2698
2699static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002700Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002701{
2702
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002703 if (!self && Py_Py3kWarningFlag) {
2704 if (PyErr_Warn(PyExc_DeprecationWarning,
2705 "_tkinter.quit is gone in 3.x") < 0)
2706 return NULL;
2707 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002708
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002709 if (!PyArg_ParseTuple(args, ":quit"))
2710 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002711
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002712 quitMainLoop = 1;
2713 Py_INCREF(Py_None);
2714 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002715}
2716
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002718Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002719{
2720
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002721 if (!PyArg_ParseTuple(args, ":interpaddr"))
2722 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002723
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002724 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002725}
2726
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002727static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002728Tkapp_TkInit(PyObject *self, PyObject *args)
2729{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002730 Tcl_Interp *interp = Tkapp_Interp(self);
2731 const char * _tk_exists = NULL;
2732 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002733
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002734#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002735 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2736 * first call failed.
2737 * To avoid the deadlock, we just refuse the second call through
2738 * a static variable.
2739 */
2740 if (tk_load_failed) {
2741 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2742 return NULL;
2743 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002744#endif
2745
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 /* We want to guard against calling Tk_Init() multiple times */
2747 CHECK_TCL_APPARTMENT;
2748 ENTER_TCL
2749 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2750 ENTER_OVERLAP
2751 if (err == TCL_ERROR) {
2752 /* This sets an exception, but we cannot return right
2753 away because we need to exit the overlap first. */
2754 Tkinter_Error(self);
2755 } else {
2756 _tk_exists = Tkapp_Result(self);
2757 }
2758 LEAVE_OVERLAP_TCL
2759 if (err == TCL_ERROR) {
2760 return NULL;
2761 }
2762 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2763 if (Tk_Init(interp) == TCL_ERROR) {
2764 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002765#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002766 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002767#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002768 return NULL;
2769 }
2770 }
2771 Py_INCREF(Py_None);
2772 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002773}
Barry Warsawfa701a81997-01-16 00:15:11 +00002774
Martin v. Löwisffad6332002-11-26 09:28:05 +00002775static PyObject *
2776Tkapp_WantObjects(PyObject *self, PyObject *args)
2777{
2778
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002779 int wantobjects = -1;
2780 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2781 return NULL;
2782 if (wantobjects == -1)
2783 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2784 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002785
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002786 Py_INCREF(Py_None);
2787 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002788}
2789
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002790static PyObject *
2791Tkapp_WillDispatch(PyObject *self, PyObject *args)
2792{
2793
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002794 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002795
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002796 Py_INCREF(Py_None);
2797 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002798}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002799
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002800
Guido van Rossum18468821994-06-20 07:49:28 +00002801/**** Tkapp Method List ****/
2802
2803static PyMethodDef Tkapp_methods[] =
2804{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002805 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2806 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2807 {"call", Tkapp_Call, METH_VARARGS},
2808 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2809 {"eval", Tkapp_Eval, METH_VARARGS},
2810 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2811 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2812 {"record", Tkapp_Record, METH_VARARGS},
2813 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2814 {"setvar", Tkapp_SetVar, METH_VARARGS},
2815 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2816 {"getvar", Tkapp_GetVar, METH_VARARGS},
2817 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2818 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2819 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2820 {"getint", Tkapp_GetInt, METH_VARARGS},
2821 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2822 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2823 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2824 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2825 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2826 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2827 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2828 {"split", Tkapp_Split, METH_VARARGS},
2829 {"merge", Tkapp_Merge, METH_VARARGS},
2830 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2831 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002832#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002833 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2834 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002835#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002836 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2837 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2838 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2839 {"quit", Tkapp_Quit, METH_VARARGS},
2840 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2841 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2842 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002843};
2844
Barry Warsawfa701a81997-01-16 00:15:11 +00002845
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002846
Guido van Rossum18468821994-06-20 07:49:28 +00002847/**** Tkapp Type Methods ****/
2848
2849static void
Fred Drake509d79a2000-07-08 04:04:38 +00002850Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002851{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002852 /*CHECK_TCL_APPARTMENT;*/
2853 ENTER_TCL
2854 Tcl_DeleteInterp(Tkapp_Interp(self));
2855 LEAVE_TCL
2856 PyObject_Del(self);
2857 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002858}
2859
2860static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002861Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002862{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002863 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002864}
2865
2866static PyTypeObject Tkapp_Type =
2867{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002868 PyVarObject_HEAD_INIT(NULL, 0)
2869 "tkapp", /*tp_name */
2870 sizeof(TkappObject), /*tp_basicsize */
2871 0, /*tp_itemsize */
2872 Tkapp_Dealloc, /*tp_dealloc */
2873 0, /*tp_print */
2874 Tkapp_GetAttr, /*tp_getattr */
2875 0, /*tp_setattr */
2876 0, /*tp_compare */
2877 0, /*tp_repr */
2878 0, /*tp_as_number */
2879 0, /*tp_as_sequence */
2880 0, /*tp_as_mapping */
2881 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002882};
2883
Barry Warsawfa701a81997-01-16 00:15:11 +00002884
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002885
Guido van Rossum18468821994-06-20 07:49:28 +00002886/**** Tkinter Module ****/
2887
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002888typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002889 PyObject* tuple;
2890 int size; /* current size */
2891 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002892} FlattenContext;
2893
2894static int
2895_bump(FlattenContext* context, int size)
2896{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002897 /* expand tuple to hold (at least) size new items.
2898 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002899
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002900 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002901
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002902 if (maxsize < context->size + size)
2903 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002904
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002905 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002906
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002907 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002908}
2909
2910static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002911_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002912{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002913 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002914
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002915 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002916
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002917 if (depth > 1000) {
2918 PyErr_SetString(PyExc_ValueError,
2919 "nesting too deep in _flatten");
2920 return 0;
2921 } else if (PyList_Check(item)) {
2922 size = PyList_GET_SIZE(item);
2923 /* preallocate (assume no nesting) */
2924 if (context->size + size > context->maxsize &&
2925 !_bump(context, size))
2926 return 0;
2927 /* copy items to output tuple */
2928 for (i = 0; i < size; i++) {
2929 PyObject *o = PyList_GET_ITEM(item, i);
2930 if (PyList_Check(o) || PyTuple_Check(o)) {
2931 if (!_flatten1(context, o, depth + 1))
2932 return 0;
2933 } else if (o != Py_None) {
2934 if (context->size + 1 > context->maxsize &&
2935 !_bump(context, 1))
2936 return 0;
2937 Py_INCREF(o);
2938 PyTuple_SET_ITEM(context->tuple,
2939 context->size++, o);
2940 }
2941 }
2942 } else if (PyTuple_Check(item)) {
2943 /* same, for tuples */
2944 size = PyTuple_GET_SIZE(item);
2945 if (context->size + size > context->maxsize &&
2946 !_bump(context, size))
2947 return 0;
2948 for (i = 0; i < size; i++) {
2949 PyObject *o = PyTuple_GET_ITEM(item, i);
2950 if (PyList_Check(o) || PyTuple_Check(o)) {
2951 if (!_flatten1(context, o, depth + 1))
2952 return 0;
2953 } else if (o != Py_None) {
2954 if (context->size + 1 > context->maxsize &&
2955 !_bump(context, 1))
2956 return 0;
2957 Py_INCREF(o);
2958 PyTuple_SET_ITEM(context->tuple,
2959 context->size++, o);
2960 }
2961 }
2962 } else {
2963 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2964 return 0;
2965 }
2966 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002967}
2968
2969static PyObject *
2970Tkinter_Flatten(PyObject* self, PyObject* args)
2971{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002972 FlattenContext context;
2973 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002974
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002975 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2976 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002977
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002978 context.maxsize = PySequence_Size(item);
2979 if (context.maxsize < 0)
2980 return NULL;
2981 if (context.maxsize == 0)
2982 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002983
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002984 context.tuple = PyTuple_New(context.maxsize);
2985 if (!context.tuple)
2986 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002987
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002988 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002989
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002990 if (!_flatten1(&context, item,0))
2991 return NULL;
2992
2993 if (_PyTuple_Resize(&context.tuple, context.size))
2994 return NULL;
2995
2996 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002997}
2998
Guido van Rossum18468821994-06-20 07:49:28 +00002999static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003000Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003001{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003002 char *screenName = NULL;
3003 char *baseName = NULL;
3004 char *className = NULL;
3005 int interactive = 0;
3006 int wantobjects = 0;
3007 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3008 int sync = 0; /* pass -sync to wish */
3009 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003010
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003011 baseName = strrchr(Py_GetProgramName(), '/');
3012 if (baseName != NULL)
3013 baseName++;
3014 else
3015 baseName = Py_GetProgramName();
3016 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003017
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003018 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3019 &screenName, &baseName, &className,
3020 &interactive, &wantobjects, &wantTk,
3021 &sync, &use))
3022 return NULL;
3023
3024 return (PyObject *) Tkapp_New(screenName, baseName, className,
3025 interactive, wantobjects, wantTk,
3026 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003027}
3028
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003029static PyObject *
3030Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3031{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003032 int new_val;
3033 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3034 return NULL;
3035 if (new_val < 0) {
3036 PyErr_SetString(PyExc_ValueError,
3037 "busywaitinterval must be >= 0");
3038 return NULL;
3039 }
3040 Tkinter_busywaitinterval = new_val;
3041 Py_INCREF(Py_None);
3042 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003043}
3044
3045static char setbusywaitinterval_doc[] =
3046"setbusywaitinterval(n) -> None\n\
3047\n\
3048Set the busy-wait interval in milliseconds between successive\n\
3049calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3050It should be set to a divisor of the maximum time between\n\
3051frames in an animation.";
3052
3053static PyObject *
3054Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3055{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003056 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003057}
3058
3059static char getbusywaitinterval_doc[] =
3060"getbusywaitinterval() -> int\n\
3061\n\
3062Return the current busy-wait interval between successive\n\
3063calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3064
Guido van Rossum18468821994-06-20 07:49:28 +00003065static PyMethodDef moduleMethods[] =
3066{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003067 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3068 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003069#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003070 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3071 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003072#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003073 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3074 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3075 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3076 {"quit", Tkapp_Quit, METH_VARARGS},
3077 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3078 setbusywaitinterval_doc},
3079 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3080 METH_NOARGS, getbusywaitinterval_doc},
3081 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003082};
3083
Guido van Rossum7bf15641998-05-22 18:28:17 +00003084#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003085
3086static int stdin_ready = 0;
3087
Guido van Rossumad4db171998-06-13 13:56:28 +00003088#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003089static void
Fred Drake509d79a2000-07-08 04:04:38 +00003090MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003091{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003092 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003093}
Guido van Rossumad4db171998-06-13 13:56:28 +00003094#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003095
Martin v. Löwisa9656492003-03-30 08:44:58 +00003096#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003097static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003098#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003099
Guido van Rossum18468821994-06-20 07:49:28 +00003100static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003101EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003102{
Guido van Rossumad4db171998-06-13 13:56:28 +00003103#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003104 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003105#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003106#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003107 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003108#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003109 stdin_ready = 0;
3110 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003111#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003112 tfile = fileno(stdin);
3113 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003114#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003115 while (!errorInCmd && !stdin_ready) {
3116 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003117#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003118 if (_kbhit()) {
3119 stdin_ready = 1;
3120 break;
3121 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003122#endif
3123#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003124 Py_BEGIN_ALLOW_THREADS
3125 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3126 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003127
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003128 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003129
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003130 tcl_tstate = NULL;
3131 if(tcl_lock)PyThread_release_lock(tcl_lock);
3132 if (result == 0)
3133 Sleep(Tkinter_busywaitinterval);
3134 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003135#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003136 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003137#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003139 if (result < 0)
3140 break;
3141 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003142#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003143 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003144#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003145 if (errorInCmd) {
3146 errorInCmd = 0;
3147 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3148 excInCmd = valInCmd = trbInCmd = NULL;
3149 PyErr_Print();
3150 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003151#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003152 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003153#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003154 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003155}
Guido van Rossum18468821994-06-20 07:49:28 +00003156
Guido van Rossum00d93061998-05-28 23:06:38 +00003157#endif
3158
Guido van Rossum7bf15641998-05-22 18:28:17 +00003159static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003160EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003161{
Guido van Rossum00d93061998-05-28 23:06:38 +00003162#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003163 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003164#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003165 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003166#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003167 PyOS_InputHook = EventHook;
3168 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003169#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003170}
3171
3172static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003173DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003174{
Guido van Rossum00d93061998-05-28 23:06:38 +00003175#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3177 PyOS_InputHook = NULL;
3178 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003179#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003180}
3181
Barry Warsawfa701a81997-01-16 00:15:11 +00003182
3183/* all errors will be checked in one fell swoop in init_tkinter() */
3184static void
Fred Drake509d79a2000-07-08 04:04:38 +00003185ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003186{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003187 PyObject *v = PyInt_FromLong(val);
3188 if (v) {
3189 PyDict_SetItemString(d, name, v);
3190 Py_DECREF(v);
3191 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003192}
3193static void
Fred Drake509d79a2000-07-08 04:04:38 +00003194ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003195{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003196 PyObject *v = PyString_FromString(val);
3197 if (v) {
3198 PyDict_SetItemString(d, name, v);
3199 Py_DECREF(v);
3200 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003201}
3202
3203
Mark Hammond62b1ab12002-07-23 06:31:15 +00003204PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003205init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003206{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003207 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003208
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003209 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003210
3211#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003212 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003213#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003215 m = Py_InitModule("_tkinter", moduleMethods);
3216 if (m == NULL)
3217 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003218
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003219 d = PyModule_GetDict(m);
3220 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3221 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003222
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003223 ins_long(d, "READABLE", TCL_READABLE);
3224 ins_long(d, "WRITABLE", TCL_WRITABLE);
3225 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3226 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3227 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3228 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3229 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3230 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3231 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3232 ins_string(d, "TK_VERSION", TK_VERSION);
3233 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003234
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003235 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003237 Py_TYPE(&Tktt_Type) = &PyType_Type;
3238 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003239
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003240 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3241 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003242
3243#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003244 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3245 * start waking up. Note that Tcl_FindExecutable will do this, this
3246 * code must be above it! The original warning from
3247 * tkMacOSXAppInit.c is copied below.
3248 *
3249 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3250 * Tcl interpreter for now. It probably should work to do this
3251 * in the other order, but for now it doesn't seem to.
3252 *
3253 */
3254 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003255#endif
3256
3257
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003258 /* This helps the dynamic loader; in Unicode aware Tcl versions
3259 it also helps Tcl find its encodings. */
3260 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003261
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003262 if (PyErr_Occurred())
3263 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003264
Guido van Rossum43ff8681998-07-14 18:02:13 +00003265#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003266 /* This was not a good idea; through <Destroy> bindings,
3267 Tcl_Finalize() may invoke Python code but at that point the
3268 interpreter and thread state have already been destroyed! */
3269 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003270#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003271
Guido van Rossum18468821994-06-20 07:49:28 +00003272}