blob: a04d580b02e404dc139411ec8345d1868e84bb72 [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
Serhiy Storchaka42035702013-08-21 21:46:12 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= (size_t)INT_MAX && \
52 (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Guilherme Polo5d64c332009-04-05 02:11:19 +000074#include "tkinter.h"
75
Jason Tishlerbbe89612002-12-31 20:30:46 +000076/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000077#ifndef CONST84_RETURN
78#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000079#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000080#define CONST
81#endif
82
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000083#if TK_VERSION_HEX < 0x08030102
84#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000092 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Jack Janseneddc1442003-11-20 01:44:59 +000099#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100#define HAVE_CREATEFILEHANDLER
101#endif
102
Guido van Rossum00d93061998-05-28 23:06:38 +0000103#ifdef HAVE_CREATEFILEHANDLER
104
Neal Norwitzd948a432006-01-08 01:08:55 +0000105/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
106 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
107#ifndef TCL_UNIX_FD
108# ifdef TCL_WIN_SOCKET
109# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
110# else
111# define TCL_UNIX_FD 1
112# endif
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* Tcl_CreateFileHandler() changed several times; these macros deal with the
116 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
117 Unix, only because Jack added it back); when available on Windows, it only
118 applies to sockets. */
119
Guido van Rossum7bf15641998-05-22 18:28:17 +0000120#ifdef MS_WINDOWS
121#define FHANDLETYPE TCL_WIN_SOCKET
122#else
123#define FHANDLETYPE TCL_UNIX_FD
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
127 which uses this to handle Tcl events while the user is typing commands. */
128
129#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000130#define WAIT_FOR_STDIN
131#endif
132
Guido van Rossum00d93061998-05-28 23:06:38 +0000133#endif /* HAVE_CREATEFILEHANDLER */
134
Guido van Rossumad4db171998-06-13 13:56:28 +0000135#ifdef MS_WINDOWS
136#include <conio.h>
137#define WAIT_FOR_STDIN
138#endif
139
Guido van Rossum00d93061998-05-28 23:06:38 +0000140#ifdef WITH_THREAD
141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142/* The threading situation is complicated. Tcl is not thread-safe, except
143 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000144 So we need to use a lock around all uses of Tcl. Previously, the Python
145 interpreter lock was used for this. However, this causes problems when
146 other Python threads need to run while Tcl is blocked waiting for events.
147
148 To solve this problem, a separate lock for Tcl is introduced. Holding it
149 is incompatible with holding Python's interpreter lock. The following four
150 macros manipulate both locks together.
151
152 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
153 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
154 that could call an event handler, or otherwise affect the state of a Tcl
155 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000156 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000157 released and the lock for Tcl has been acquired.
158
Guido van Rossum5e977831998-06-15 14:03:52 +0000159 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
160 (For example, when transferring data from the Tcl interpreter result to a
161 Python string object.) This can be done by using different macros to close
162 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
163 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
164 releases the Tcl lock.
165
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000166 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000167 handlers when the handler needs to use Python. Such event handlers are
168 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000170 the Python interpreter lock, restoring the appropriate thread state, and
171 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
172 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175 These locks expand to several statements and brackets; they should not be
176 used in branches of if statements and the like.
177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
179 only valid in the thread that created it, and all Tk activity must happen in this
180 thread, also. That means that the mainloop must be invoked in the thread that
181 created the interpreter. Invoking commands from other threads is possible;
182 _tkinter will queue an event for the interpreter thread, which will then
183 execute the command and pass back the result. If the main thread is not in the
184 mainloop, and invoking commands causes an exception; if the main loop is running
185 but not processing events, the command invocation will block.
186
187 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
188 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
189 threads. So we use the Tcl TLS API.
190
Guido van Rossum00d93061998-05-28 23:06:38 +0000191*/
192
Guido van Rossum65d5b571998-12-21 19:32:43 +0000193static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194
195#ifdef TCL_THREADS
196static Tcl_ThreadDataKey state_key;
197typedef PyThreadState *ThreadSpecificData;
198#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
199#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
205 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
207#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
Guido van Rossum62320c91998-06-15 04:36:09 +0000210#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000211 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000212
213#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000214 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000215
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000216#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
218 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 { PyThreadState *tstate = PyEval_SaveThread(); \
222 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223
224#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000225 if (((TkappObject *)self)->threaded && \
226 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
227 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
228 return 0; \
229 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000230
231#else
232
233#define ENTER_TCL
234#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000235#define ENTER_OVERLAP
236#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000237#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000238#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000239#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000240
241#endif
242
Guido van Rossum97867b21996-08-08 19:09:53 +0000243#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000244#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#endif
246
Guido van Rossum18468821994-06-20 07:49:28 +0000247/**** Tkapp Object Declaration ****/
248
Jeremy Hylton938ace62002-07-17 16:30:39 +0000249static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000250
Guido van Rossum00d93061998-05-28 23:06:38 +0000251typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000252 PyObject_HEAD
253 Tcl_Interp *interp;
254 int wantobjects;
255 int threaded; /* True if tcl_platform[threaded] */
256 Tcl_ThreadId thread_id;
257 int dispatching;
258 /* We cannot include tclInt.h, as this is internal.
259 So we cache interesting types here. */
260 Tcl_ObjType *BooleanType;
261 Tcl_ObjType *ByteArrayType;
262 Tcl_ObjType *DoubleType;
263 Tcl_ObjType *IntType;
264 Tcl_ObjType *ListType;
265 Tcl_ObjType *ProcBodyType;
266 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000267} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Christian Heimese93237d2007-12-19 02:37:44 +0000269#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000270#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000271#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Guido van Rossum35d43371997-08-02 00:09:09 +0000273#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000274(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000275
Barry Warsawfa701a81997-01-16 00:15:11 +0000276
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000277
Guido van Rossum18468821994-06-20 07:49:28 +0000278/**** Error Handling ****/
279
280static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000281static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000282static int errorInCmd = 0;
283static PyObject *excInCmd;
284static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000285static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000287#ifdef TKINTER_PROTECT_LOADTK
288static int tk_load_failed;
289#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000293Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000295 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000297}
298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000302
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000303static int Tkinter_busywaitinterval = 20;
304
Guido van Rossum00d93061998-05-28 23:06:38 +0000305#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000306#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000307
Guido van Rossum00d93061998-05-28 23:06:38 +0000308/* Millisecond sleep() for Unix platforms. */
309
310static void
Fred Drake509d79a2000-07-08 04:04:38 +0000311Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000312{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000313 /* XXX Too bad if you don't have select(). */
314 struct timeval t;
315 t.tv_sec = milli/1000;
316 t.tv_usec = (milli%1000) * 1000;
317 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000318}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000319#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000320
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000321/* Wait up to 1s for the mainloop to come up. */
322
323static int
324WaitForMainloop(TkappObject* self)
325{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000326 int i;
327 for (i = 0; i < 10; i++) {
328 if (self->dispatching)
329 return 1;
330 Py_BEGIN_ALLOW_THREADS
331 Sleep(100);
332 Py_END_ALLOW_THREADS
333 }
334 if (self->dispatching)
335 return 1;
336 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
337 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000338}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000339#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000340
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341
Guido van Rossum18468821994-06-20 07:49:28 +0000342static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000343AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000344{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000345 if (PyString_Check(value))
346 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000347#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000348 else if (PyUnicode_Check(value)) {
349 PyObject *v = PyUnicode_AsUTF8String(value);
350 if (v == NULL)
351 return NULL;
352 if (PyList_Append(tmp, v) != 0) {
353 Py_DECREF(v);
354 return NULL;
355 }
356 Py_DECREF(v);
357 return PyString_AsString(v);
358 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000359#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000360 else {
361 PyObject *v = PyObject_Str(value);
362 if (v == NULL)
363 return NULL;
364 if (PyList_Append(tmp, v) != 0) {
365 Py_DECREF(v);
366 return NULL;
367 }
368 Py_DECREF(v);
369 return PyString_AsString(v);
370 }
Guido van Rossum18468821994-06-20 07:49:28 +0000371}
372
Barry Warsawfa701a81997-01-16 00:15:11 +0000373
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000374
Guido van Rossum18468821994-06-20 07:49:28 +0000375#define ARGSZ 64
376
377static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000378Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000379{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000380 PyObject *tmp = NULL;
381 char *argvStore[ARGSZ];
382 char **argv = NULL;
383 int fvStore[ARGSZ];
384 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300385 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000386 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000388 if (!(tmp = PyList_New(0)))
389 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000391 argv = argvStore;
392 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000394 if (args == NULL)
395 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000396
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000397 else if (!PyTuple_Check(args)) {
398 argc = 1;
399 fv[0] = 0;
400 if (!(argv[0] = AsString(args, tmp)))
401 goto finally;
402 }
403 else {
404 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000406 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300407 if (!CHECK_SIZE(argc, sizeof(char *))) {
408 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
409 goto finally;
410 }
411 argv = (char **)ckalloc((size_t)argc * sizeof(char *));
412 fv = (int *)ckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000413 if (argv == NULL || fv == NULL) {
414 PyErr_NoMemory();
415 goto finally;
416 }
417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000419 for (i = 0; i < argc; i++) {
420 PyObject *v = PyTuple_GetItem(args, i);
421 if (PyTuple_Check(v)) {
422 fv[i] = 1;
423 if (!(argv[i] = Merge(v)))
424 goto finally;
425 fvc++;
426 }
427 else if (v == Py_None) {
428 argc = i;
429 break;
430 }
431 else {
432 fv[i] = 0;
433 if (!(argv[i] = AsString(v, tmp)))
434 goto finally;
435 fvc++;
436 }
437 }
438 }
439 res = Tcl_Merge(argc, argv);
440 if (res == NULL)
441 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000442
Barry Warsawfa701a81997-01-16 00:15:11 +0000443 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000444 for (i = 0; i < fvc; i++)
445 if (fv[i]) {
446 ckfree(argv[i]);
447 }
448 if (argv != argvStore)
449 ckfree(FREECAST argv);
450 if (fv != fvStore)
451 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000453 Py_DECREF(tmp);
454 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000455}
456
Barry Warsawfa701a81997-01-16 00:15:11 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458
Guido van Rossum18468821994-06-20 07:49:28 +0000459static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000460Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000461{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000462 int argc;
463 char **argv;
464 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000465
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000466 if (list == NULL) {
467 Py_INCREF(Py_None);
468 return Py_None;
469 }
Guido van Rossum18468821994-06-20 07:49:28 +0000470
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
472 /* Not a list.
473 * Could be a quoted string containing funnies, e.g. {"}.
474 * Return the string itself.
475 */
476 return PyString_FromString(list);
477 }
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 if (argc == 0)
480 v = PyString_FromString("");
481 else if (argc == 1)
482 v = PyString_FromString(argv[0]);
483 else if ((v = PyTuple_New(argc)) != NULL) {
484 int i;
485 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000486
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000487 for (i = 0; i < argc; i++) {
488 if ((w = Split(argv[i])) == NULL) {
489 Py_DECREF(v);
490 v = NULL;
491 break;
492 }
493 PyTuple_SetItem(v, i, w);
494 }
495 }
496 Tcl_Free(FREECAST argv);
497 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000498}
499
Martin v. Löwisffad6332002-11-26 09:28:05 +0000500/* In some cases, Tcl will still return strings that are supposed to be
501 lists. SplitObj walks through a nested tuple, finding string objects that
502 need to be split. */
503
Martin v. Löwis111c1802008-06-13 07:47:47 +0000504static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000505SplitObj(PyObject *arg)
506{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000507 if (PyTuple_Check(arg)) {
508 int i, size;
509 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000510
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000511 size = PyTuple_Size(arg);
512 result = NULL;
513 /* Recursively invoke SplitObj for all tuple items.
514 If this does not return a new object, no action is
515 needed. */
516 for(i = 0; i < size; i++) {
517 elem = PyTuple_GetItem(arg, i);
518 newelem = SplitObj(elem);
519 if (!newelem) {
520 Py_XDECREF(result);
521 return NULL;
522 }
523 if (!result) {
524 int k;
525 if (newelem == elem) {
526 Py_DECREF(newelem);
527 continue;
528 }
529 result = PyTuple_New(size);
530 if (!result)
531 return NULL;
532 for(k = 0; k < i; k++) {
533 elem = PyTuple_GetItem(arg, k);
534 Py_INCREF(elem);
535 PyTuple_SetItem(result, k, elem);
536 }
537 }
538 PyTuple_SetItem(result, i, newelem);
539 }
540 if (result)
541 return result;
542 /* Fall through, returning arg. */
543 }
544 else if (PyString_Check(arg)) {
545 int argc;
546 char **argv;
547 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000548
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000549 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
550 Py_INCREF(arg);
551 return arg;
552 }
553 Tcl_Free(FREECAST argv);
554 if (argc > 1)
555 return Split(PyString_AsString(arg));
556 /* Fall through, returning arg. */
557 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300558 else if (PyUnicode_Check(arg)) {
559 int argc;
560 char **argv;
561 char *list;
562 PyObject *s = PyUnicode_AsUTF8String(arg);
563
564 if (s == NULL) {
565 Py_INCREF(arg);
566 return arg;
567 }
568 list = PyString_AsString(s);
569
570 if (list == NULL ||
571 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
572 Py_DECREF(s);
573 Py_INCREF(arg);
574 return arg;
575 }
576 Tcl_Free(FREECAST argv);
577 if (argc > 1) {
578 PyObject *v = Split(list);
579 Py_DECREF(s);
580 return v;
581 }
582 Py_DECREF(s);
583 /* Fall through, returning arg. */
584 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000585 Py_INCREF(arg);
586 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000587}
Barry Warsawfa701a81997-01-16 00:15:11 +0000588
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000589
Guido van Rossum18468821994-06-20 07:49:28 +0000590/**** Tkapp Object ****/
591
592#ifndef WITH_APPINIT
593int
Fred Drake509d79a2000-07-08 04:04:38 +0000594Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000595{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000596 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000597
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000598 if (Tcl_Init(interp) == TCL_ERROR) {
599 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
600 return TCL_ERROR;
601 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000602
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000603 _tkinter_skip_tk_init = Tcl_GetVar(interp,
604 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
605 if (_tkinter_skip_tk_init != NULL &&
606 strcmp(_tkinter_skip_tk_init, "1") == 0) {
607 return TCL_OK;
608 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000609
610#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 if (tk_load_failed) {
612 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
613 return TCL_ERROR;
614 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000615#endif
616
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000617 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000618#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000619 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000620#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000621 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
622 return TCL_ERROR;
623 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000624
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000625 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000626}
627#endif /* !WITH_APPINIT */
628
Guido van Rossum18468821994-06-20 07:49:28 +0000629
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000630
Barry Warsawfa701a81997-01-16 00:15:11 +0000631
632/* Initialize the Tk application; see the `main' function in
633 * `tkMain.c'.
634 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000635
Thomas Wouters58d05102000-07-24 14:43:35 +0000636static void EnableEventHook(void); /* Forward */
637static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000638
Barry Warsawfa701a81997-01-16 00:15:11 +0000639static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000640Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000641 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000642{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000643 TkappObject *v;
644 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000645
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000646 v = PyObject_New(TkappObject, &Tkapp_Type);
647 if (v == NULL)
648 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000649
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000650 v->interp = Tcl_CreateInterp();
651 v->wantobjects = wantobjects;
652 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
653 TCL_GLOBAL_ONLY) != NULL;
654 v->thread_id = Tcl_GetCurrentThread();
655 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000656
657#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000658 if (v->threaded) {
659 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
660 Py_DECREF(v);
661 return 0;
662 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000663#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000664#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000665 if (v->threaded && tcl_lock) {
666 /* If Tcl is threaded, we don't need the lock. */
667 PyThread_free_lock(tcl_lock);
668 tcl_lock = NULL;
669 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000670#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000671
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000672 v->BooleanType = Tcl_GetObjType("boolean");
673 v->ByteArrayType = Tcl_GetObjType("bytearray");
674 v->DoubleType = Tcl_GetObjType("double");
675 v->IntType = Tcl_GetObjType("int");
676 v->ListType = Tcl_GetObjType("list");
677 v->ProcBodyType = Tcl_GetObjType("procbody");
678 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000679
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000680 /* Delete the 'exit' command, which can screw things up */
681 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000682
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 if (screenName != NULL)
684 Tcl_SetVar2(v->interp, "env", "DISPLAY",
685 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 if (interactive)
688 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
689 else
690 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 /* This is used to get the application class for Tk 4.1 and up */
693 argv0 = (char*)ckalloc(strlen(className) + 1);
694 if (!argv0) {
695 PyErr_NoMemory();
696 Py_DECREF(v);
697 return NULL;
698 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000699
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000700 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200701 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
702 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000703 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
704 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000705
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 if (! wantTk) {
707 Tcl_SetVar(v->interp,
708 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
709 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000710#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000711 else if (tk_load_failed) {
712 Tcl_SetVar(v->interp,
713 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
714 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000715#endif
David Aschere2b4b322004-02-18 05:59:53 +0000716
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000717 /* some initial arguments need to be in argv */
718 if (sync || use) {
719 char *args;
720 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000721
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000722 if (sync)
723 len += sizeof "-sync";
724 if (use)
725 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000726
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000727 args = (char*)ckalloc(len);
728 if (!args) {
729 PyErr_NoMemory();
730 Py_DECREF(v);
731 return NULL;
732 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000733
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000734 args[0] = '\0';
735 if (sync)
736 strcat(args, "-sync");
737 if (use) {
738 if (sync)
739 strcat(args, " ");
740 strcat(args, "-use ");
741 strcat(args, use);
742 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000743
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000744 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
745 ckfree(args);
746 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000747
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000748 if (Tcl_AppInit(v->interp) != TCL_OK) {
749 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000750#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000751 if (wantTk) {
752 const char *_tkinter_tk_failed;
753 _tkinter_tk_failed = Tcl_GetVar(v->interp,
754 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000755
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 if ( _tkinter_tk_failed != NULL &&
757 strcmp(_tkinter_tk_failed, "1") == 0) {
758 tk_load_failed = 1;
759 }
760 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000761#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 Py_DECREF((PyObject *)v);
763 return (TkappObject *)result;
764 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000765
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000766 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000767
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000768 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000769}
770
Barry Warsawfa701a81997-01-16 00:15:11 +0000771
Guilherme Polo1972d162009-03-27 21:43:08 +0000772#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000773static void
774Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000775 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000777 Py_BEGIN_ALLOW_THREADS;
778 Tcl_MutexLock(mutex);
779 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
780 Tcl_ThreadAlert(self->thread_id);
781 Tcl_ConditionWait(cond, mutex, NULL);
782 Tcl_MutexUnlock(mutex);
783 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000784}
Guilherme Polo1972d162009-03-27 21:43:08 +0000785#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000786
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000787
Guido van Rossum18468821994-06-20 07:49:28 +0000788/** Tcl Eval **/
789
Martin v. Löwisffad6332002-11-26 09:28:05 +0000790typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000791 PyObject_HEAD
792 Tcl_Obj *value;
793 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000794} PyTclObject;
795
796staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000797#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000798
799static PyObject *
800newPyTclObject(Tcl_Obj *arg)
801{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000802 PyTclObject *self;
803 self = PyObject_New(PyTclObject, &PyTclObject_Type);
804 if (self == NULL)
805 return NULL;
806 Tcl_IncrRefCount(arg);
807 self->value = arg;
808 self->string = NULL;
809 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static void
813PyTclObject_dealloc(PyTclObject *self)
814{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 Tcl_DecrRefCount(self->value);
816 Py_XDECREF(self->string);
817 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000818}
819
820static PyObject *
821PyTclObject_str(PyTclObject *self)
822{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000823 if (self->string && PyString_Check(self->string)) {
824 Py_INCREF(self->string);
825 return self->string;
826 }
827 /* XXX Could cache value if it is an ASCII string. */
828 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000829}
830
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000831static char*
832PyTclObject_TclString(PyObject *self)
833{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000834 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000835}
836
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000837/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000838PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000839"the string representation of this object, either as string or Unicode");
840
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000841static PyObject *
842PyTclObject_string(PyTclObject *self, void *ignored)
843{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000844 char *s;
845 int i, len;
846 if (!self->string) {
847 s = Tcl_GetStringFromObj(self->value, &len);
848 for (i = 0; i < len; i++)
849 if (s[i] & 0x80)
850 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000851#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000852 if (i == len)
853 /* It is an ASCII string. */
854 self->string = PyString_FromStringAndSize(s, len);
855 else {
856 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
857 if (!self->string) {
858 PyErr_Clear();
859 self->string = PyString_FromStringAndSize(s, len);
860 }
861 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000862#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000863 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000864#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000865 if (!self->string)
866 return NULL;
867 }
868 Py_INCREF(self->string);
869 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000870}
871
872#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000873PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
874
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000875static PyObject *
876PyTclObject_unicode(PyTclObject *self, void *ignored)
877{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000878 char *s;
879 int len;
880 if (self->string && PyUnicode_Check(self->string)) {
881 Py_INCREF(self->string);
882 return self->string;
883 }
884 /* XXX Could chache result if it is non-ASCII. */
885 s = Tcl_GetStringFromObj(self->value, &len);
886 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000887}
888#endif
889
Martin v. Löwisffad6332002-11-26 09:28:05 +0000890static PyObject *
891PyTclObject_repr(PyTclObject *self)
892{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000893 char buf[50];
894 PyOS_snprintf(buf, 50, "<%s object at %p>",
895 self->value->typePtr->name, self->value);
896 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000897}
898
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000899static int
900PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
901{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000902 int res;
903 res = strcmp(Tcl_GetString(self->value),
904 Tcl_GetString(other->value));
905 if (res < 0) return -1;
906 if (res > 0) return 1;
907 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000908}
909
Martin v. Löwis39195712003-01-04 00:33:13 +0000910PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
911
Martin v. Löwisffad6332002-11-26 09:28:05 +0000912static PyObject*
913get_typename(PyTclObject* obj, void* ignored)
914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000915 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916}
917
Martin v. Löwis39195712003-01-04 00:33:13 +0000918
Martin v. Löwisffad6332002-11-26 09:28:05 +0000919static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000920 {"typename", (getter)get_typename, NULL, get_typename__doc__},
921 {"string", (getter)PyTclObject_string, NULL,
922 PyTclObject_string__doc__},
923 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924};
925
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000926static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000927#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000928 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
929 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000930#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000931 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000932};
933
Martin v. Löwisffad6332002-11-26 09:28:05 +0000934statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000935 PyObject_HEAD_INIT(NULL)
936 0, /*ob_size*/
937 "_tkinter.Tcl_Obj", /*tp_name*/
938 sizeof(PyTclObject), /*tp_basicsize*/
939 0, /*tp_itemsize*/
940 /* methods */
941 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
942 0, /*tp_print*/
943 0, /*tp_getattr*/
944 0, /*tp_setattr*/
945 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
946 (reprfunc)PyTclObject_repr, /*tp_repr*/
947 0, /*tp_as_number*/
948 0, /*tp_as_sequence*/
949 0, /*tp_as_mapping*/
950 0, /*tp_hash*/
951 0, /*tp_call*/
952 (reprfunc)PyTclObject_str, /*tp_str*/
953 PyObject_GenericGetAttr,/*tp_getattro*/
954 0, /*tp_setattro*/
955 0, /*tp_as_buffer*/
956 Py_TPFLAGS_DEFAULT, /*tp_flags*/
957 0, /*tp_doc*/
958 0, /*tp_traverse*/
959 0, /*tp_clear*/
960 0, /*tp_richcompare*/
961 0, /*tp_weaklistoffset*/
962 0, /*tp_iter*/
963 0, /*tp_iternext*/
964 PyTclObject_methods, /*tp_methods*/
965 0, /*tp_members*/
966 PyTclObject_getsetlist, /*tp_getset*/
967 0, /*tp_base*/
968 0, /*tp_dict*/
969 0, /*tp_descr_get*/
970 0, /*tp_descr_set*/
971 0, /*tp_dictoffset*/
972 0, /*tp_init*/
973 0, /*tp_alloc*/
974 0, /*tp_new*/
975 0, /*tp_free*/
976 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977};
978
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000979static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000980AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000981{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000982 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000983
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000984 if (PyString_Check(value))
985 return Tcl_NewStringObj(PyString_AS_STRING(value),
986 PyString_GET_SIZE(value));
987 else if (PyBool_Check(value))
988 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
989 else if (PyInt_Check(value))
990 return Tcl_NewLongObj(PyInt_AS_LONG(value));
991 else if (PyFloat_Check(value))
992 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
993 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300994 Tcl_Obj **argv;
995 Py_ssize_t size, i;
996
997 size = PyTuple_Size(value);
998 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
999 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1000 return NULL;
1001 }
1002 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001003 if(!argv)
1004 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001005 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001006 argv[i] = AsObj(PyTuple_GetItem(value,i));
1007 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1008 ckfree(FREECAST argv);
1009 return result;
1010 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001011#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001012 else if (PyUnicode_Check(value)) {
1013 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1014 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1015 /* This #ifdef assumes that Tcl uses UCS-2.
1016 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001017#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001018 Tcl_UniChar *outbuf = NULL;
1019 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001020 size_t allocsize;
1021 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1022 PyErr_SetString(PyExc_OverflowError, "string is too long");
1023 return NULL;
1024 }
1025 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001026 if (allocsize >= size)
1027 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1028 /* Else overflow occurred, and we take the next exit */
1029 if (!outbuf) {
1030 PyErr_NoMemory();
1031 return NULL;
1032 }
1033 for (i = 0; i < size; i++) {
1034 if (inbuf[i] >= 0x10000) {
1035 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001036 PyErr_Format(Tkinter_TclError,
1037 "character U+%x is above the range "
1038 "(U+0000-U+FFFF) allowed by Tcl",
1039 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001040 ckfree(FREECAST outbuf);
1041 return NULL;
1042 }
1043 outbuf[i] = inbuf[i];
1044 }
1045 result = Tcl_NewUnicodeObj(outbuf, size);
1046 ckfree(FREECAST outbuf);
1047 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001048#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001049 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001050#endif
1051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001052 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001053#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001054 else if(PyTclObject_Check(value)) {
1055 Tcl_Obj *v = ((PyTclObject*)value)->value;
1056 Tcl_IncrRefCount(v);
1057 return v;
1058 }
1059 else {
1060 PyObject *v = PyObject_Str(value);
1061 if (!v)
1062 return 0;
1063 result = AsObj(v);
1064 Py_DECREF(v);
1065 return result;
1066 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001067}
1068
Martin v. Löwisffad6332002-11-26 09:28:05 +00001069static PyObject*
1070FromObj(PyObject* tkapp, Tcl_Obj *value)
1071{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001072 PyObject *result = NULL;
1073 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 if (value->typePtr == NULL) {
1076 /* If the result contains any bytes with the top bit set,
1077 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001078#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001079 int i;
1080 char *s = value->bytes;
1081 int len = value->length;
1082 for (i = 0; i < len; i++) {
1083 if (value->bytes[i] & 0x80)
1084 break;
1085 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001086
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001087 if (i == value->length)
1088 result = PyString_FromStringAndSize(s, len);
1089 else {
1090 /* Convert UTF-8 to Unicode string */
1091 result = PyUnicode_DecodeUTF8(s, len, "strict");
1092 if (result == NULL) {
1093 PyErr_Clear();
1094 result = PyString_FromStringAndSize(s, len);
1095 }
1096 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001097#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001098 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001099#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001100 return result;
1101 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001102
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001103 if (value->typePtr == app->BooleanType) {
1104 result = value->internalRep.longValue ? Py_True : Py_False;
1105 Py_INCREF(result);
1106 return result;
1107 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001109 if (value->typePtr == app->ByteArrayType) {
1110 int size;
1111 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1112 return PyString_FromStringAndSize(data, size);
1113 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001115 if (value->typePtr == app->DoubleType) {
1116 return PyFloat_FromDouble(value->internalRep.doubleValue);
1117 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001118
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001119 if (value->typePtr == app->IntType) {
1120 return PyInt_FromLong(value->internalRep.longValue);
1121 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001122
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001123 if (value->typePtr == app->ListType) {
1124 int size;
1125 int i, status;
1126 PyObject *elem;
1127 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001129 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1130 if (status == TCL_ERROR)
1131 return Tkinter_Error(tkapp);
1132 result = PyTuple_New(size);
1133 if (!result)
1134 return NULL;
1135 for (i = 0; i < size; i++) {
1136 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1137 value, i, &tcl_elem);
1138 if (status == TCL_ERROR) {
1139 Py_DECREF(result);
1140 return Tkinter_Error(tkapp);
1141 }
1142 elem = FromObj(tkapp, tcl_elem);
1143 if (!elem) {
1144 Py_DECREF(result);
1145 return NULL;
1146 }
1147 PyTuple_SetItem(result, i, elem);
1148 }
1149 return result;
1150 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001151
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001152 if (value->typePtr == app->ProcBodyType) {
1153 /* fall through: return tcl object. */
1154 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001155
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001156 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001158#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 PyObject *result;
1160 int size;
1161 Tcl_UniChar *input;
1162 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001163
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001164 size = Tcl_GetCharLength(value);
1165 result = PyUnicode_FromUnicode(NULL, size);
1166 if (!result)
1167 return NULL;
1168 input = Tcl_GetUnicode(value);
1169 output = PyUnicode_AS_UNICODE(result);
1170 while (size--)
1171 *output++ = *input++;
1172 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001173#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001174 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1175 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001176#endif
1177#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001178 int size;
1179 char *c;
1180 c = Tcl_GetStringFromObj(value, &size);
1181 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001182#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001183 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001184
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001185 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001186}
1187
Guilherme Polo1972d162009-03-27 21:43:08 +00001188#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001189/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190TCL_DECLARE_MUTEX(call_mutex)
1191
1192typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001193 Tcl_Event ev; /* Must be first */
1194 TkappObject *self;
1195 PyObject *args;
1196 int flags;
1197 PyObject **res;
1198 PyObject **exc_type, **exc_value, **exc_tb;
1199 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001200} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001201#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001202
1203void
1204Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001205{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001206 int i;
1207 for (i = 0; i < objc; i++)
1208 Tcl_DecrRefCount(objv[i]);
1209 if (objv != objStore)
1210 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001211}
Guido van Rossum18468821994-06-20 07:49:28 +00001212
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213/* Convert Python objects to Tcl objects. This must happen in the
1214 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001215
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001216static Tcl_Obj**
1217Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1218{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001220 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001221 if (args == NULL)
1222 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001224 else if (!PyTuple_Check(args)) {
1225 objv[0] = AsObj(args);
1226 if (objv[0] == 0)
1227 goto finally;
1228 objc = 1;
1229 Tcl_IncrRefCount(objv[0]);
1230 }
1231 else {
1232 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001233
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001234 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001235 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1236 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1237 return NULL;
1238 }
1239 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001240 if (objv == NULL) {
1241 PyErr_NoMemory();
1242 objc = 0;
1243 goto finally;
1244 }
1245 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001246
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001247 for (i = 0; i < objc; i++) {
1248 PyObject *v = PyTuple_GetItem(args, i);
1249 if (v == Py_None) {
1250 objc = i;
1251 break;
1252 }
1253 objv[i] = AsObj(v);
1254 if (!objv[i]) {
1255 /* Reset objc, so it attempts to clear
1256 objects only up to i. */
1257 objc = i;
1258 goto finally;
1259 }
1260 Tcl_IncrRefCount(objv[i]);
1261 }
1262 }
1263 *pobjc = objc;
1264 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001265finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001266 Tkapp_CallDeallocArgs(objv, objStore, objc);
1267 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001268}
Guido van Rossum212643f1998-04-29 16:22:14 +00001269
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001271
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272static PyObject*
1273Tkapp_CallResult(TkappObject *self)
1274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001275 PyObject *res = NULL;
1276 if(self->wantobjects) {
1277 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1278 /* Not sure whether the IncrRef is necessary, but something
1279 may overwrite the interpreter result while we are
1280 converting it. */
1281 Tcl_IncrRefCount(value);
1282 res = FromObj((PyObject*)self, value);
1283 Tcl_DecrRefCount(value);
1284 } else {
1285 const char *s = Tcl_GetStringResult(self->interp);
1286 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001287
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001288 /* If the result contains any bytes with the top bit set,
1289 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001290#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001291 while (*p != '\0') {
1292 if (*p & 0x80)
1293 break;
1294 p++;
1295 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001296
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001297 if (*p == '\0')
1298 res = PyString_FromStringAndSize(s, (int)(p-s));
1299 else {
1300 /* Convert UTF-8 to Unicode string */
1301 p = strchr(p, '\0');
1302 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1303 if (res == NULL) {
1304 PyErr_Clear();
1305 res = PyString_FromStringAndSize(s, (int)(p-s));
1306 }
1307 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001308#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001309 p = strchr(p, '\0');
1310 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001311#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001312 }
1313 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001314}
Guido van Rossum632de272000-03-29 00:19:50 +00001315
Guilherme Polo1972d162009-03-27 21:43:08 +00001316#ifdef WITH_THREAD
1317
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318/* Tkapp_CallProc is the event procedure that is executed in the context of
1319 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1320 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322static int
1323Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1324{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001325 Tcl_Obj *objStore[ARGSZ];
1326 Tcl_Obj **objv;
1327 int objc;
1328 int i;
1329 ENTER_PYTHON
1330 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1331 if (!objv) {
1332 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1333 *(e->res) = NULL;
1334 }
1335 LEAVE_PYTHON
1336 if (!objv)
1337 goto done;
1338 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1339 ENTER_PYTHON
1340 if (i == TCL_ERROR) {
1341 *(e->res) = NULL;
1342 *(e->exc_type) = NULL;
1343 *(e->exc_tb) = NULL;
1344 *(e->exc_value) = PyObject_CallFunction(
1345 Tkinter_TclError, "s",
1346 Tcl_GetStringResult(e->self->interp));
1347 }
1348 else {
1349 *(e->res) = Tkapp_CallResult(e->self);
1350 }
1351 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001353 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001354done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001355 /* Wake up calling thread. */
1356 Tcl_MutexLock(&call_mutex);
1357 Tcl_ConditionNotify(e->done);
1358 Tcl_MutexUnlock(&call_mutex);
1359 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360}
1361
Guilherme Polo1972d162009-03-27 21:43:08 +00001362#endif
1363
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364/* This is the main entry point for calling a Tcl command.
1365 It supports three cases, with regard to threading:
1366 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1367 the context of the calling thread.
1368 2. Tcl is threaded, caller of the command is in the interpreter thread:
1369 Execute the command in the calling thread. Since the Tcl lock will
1370 not be used, we can merge that with case 1.
1371 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1372 the interpreter thread. Allocation of Tcl objects needs to occur in the
1373 interpreter thread, so we ship the PyObject* args to the target thread,
1374 and perform processing there. */
1375
1376static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001377Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001378{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001379 Tcl_Obj *objStore[ARGSZ];
1380 Tcl_Obj **objv = NULL;
1381 int objc, i;
1382 PyObject *res = NULL;
1383 TkappObject *self = (TkappObject*)selfptr;
1384 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001386 /* If args is a single tuple, replace with contents of tuple */
1387 if (1 == PyTuple_Size(args)){
1388 PyObject* item = PyTuple_GetItem(args, 0);
1389 if (PyTuple_Check(item))
1390 args = item;
1391 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001392#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001393 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1394 /* We cannot call the command directly. Instead, we must
1395 marshal the parameters to the interpreter thread. */
1396 Tkapp_CallEvent *ev;
1397 Tcl_Condition cond = NULL;
1398 PyObject *exc_type, *exc_value, *exc_tb;
1399 if (!WaitForMainloop(self))
1400 return NULL;
1401 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1402 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1403 ev->self = self;
1404 ev->args = args;
1405 ev->res = &res;
1406 ev->exc_type = &exc_type;
1407 ev->exc_value = &exc_value;
1408 ev->exc_tb = &exc_tb;
1409 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001411 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001413 if (res == NULL) {
1414 if (exc_type)
1415 PyErr_Restore(exc_type, exc_value, exc_tb);
1416 else
1417 PyErr_SetObject(Tkinter_TclError, exc_value);
1418 }
1419 Tcl_ConditionFinalize(&cond);
1420 }
1421 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001422#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001423 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001425 objv = Tkapp_CallArgs(args, objStore, &objc);
1426 if (!objv)
1427 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001429 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001430
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001431 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001433 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001434
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001435 if (i == TCL_ERROR)
1436 Tkinter_Error(selfptr);
1437 else
1438 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001440 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001442 Tkapp_CallDeallocArgs(objv, objStore, objc);
1443 }
1444 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001445}
1446
1447
1448static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001449Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001450{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001451 /* Could do the same here as for Tkapp_Call(), but this is not used
1452 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1453 way for the user to do what all its Global* variants do (save and
1454 reset the scope pointer, call the local version, restore the saved
1455 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001456
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001457 char *cmd;
1458 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +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 cmd = Merge(args);
1463 if (cmd) {
1464 int err;
1465 ENTER_TCL
1466 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1467 ENTER_OVERLAP
1468 if (err == TCL_ERROR)
1469 res = Tkinter_Error(self);
1470 else
1471 res = PyString_FromString(Tkapp_Result(self));
1472 LEAVE_OVERLAP_TCL
1473 ckfree(cmd);
1474 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001477}
1478
1479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001480Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001481{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 char *script;
1483 PyObject *res = NULL;
1484 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001486 if (!PyArg_ParseTuple(args, "s:eval", &script))
1487 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001489 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001491 ENTER_TCL
1492 err = Tcl_Eval(Tkapp_Interp(self), script);
1493 ENTER_OVERLAP
1494 if (err == TCL_ERROR)
1495 res = Tkinter_Error(self);
1496 else
1497 res = PyString_FromString(Tkapp_Result(self));
1498 LEAVE_OVERLAP_TCL
1499 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
1502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001503Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001504{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001505 char *script;
1506 PyObject *res = NULL;
1507 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001509 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1510 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001512 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001514 ENTER_TCL
1515 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1516 ENTER_OVERLAP
1517 if (err == TCL_ERROR)
1518 res = Tkinter_Error(self);
1519 else
1520 res = PyString_FromString(Tkapp_Result(self));
1521 LEAVE_OVERLAP_TCL
1522 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
1524
1525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001526Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001527{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001528 char *fileName;
1529 PyObject *res = NULL;
1530 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001531
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001532 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1533 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001535 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001537 ENTER_TCL
1538 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1539 ENTER_OVERLAP
1540 if (err == TCL_ERROR)
1541 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001542
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001543 else
1544 res = PyString_FromString(Tkapp_Result(self));
1545 LEAVE_OVERLAP_TCL
1546 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001547}
1548
1549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001550Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001551{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001552 char *script;
1553 PyObject *res = NULL;
1554 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001556 if (!PyArg_ParseTuple(args, "s", &script))
1557 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001558
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001559 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001560
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001561 ENTER_TCL
1562 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1563 ENTER_OVERLAP
1564 if (err == TCL_ERROR)
1565 res = Tkinter_Error(self);
1566 else
1567 res = PyString_FromString(Tkapp_Result(self));
1568 LEAVE_OVERLAP_TCL
1569 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001570}
1571
1572static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001573Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001574{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001575 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001576
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001577 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1578 return NULL;
1579 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001580
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001581 ENTER_TCL
1582 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1583 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001585 Py_INCREF(Py_None);
1586 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001587}
1588
Barry Warsawfa701a81997-01-16 00:15:11 +00001589
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001590
Guido van Rossum18468821994-06-20 07:49:28 +00001591/** Tcl Variable **/
1592
Guilherme Polo1972d162009-03-27 21:43:08 +00001593typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1594
1595#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596TCL_DECLARE_MUTEX(var_mutex)
1597
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001598typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001599 Tcl_Event ev; /* must be first */
1600 PyObject *self;
1601 PyObject *args;
1602 int flags;
1603 EventFunc func;
1604 PyObject **res;
1605 PyObject **exc_type;
1606 PyObject **exc_val;
1607 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001608} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001609#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001611static int
1612varname_converter(PyObject *in, void *_out)
1613{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001614 char **out = (char**)_out;
1615 if (PyString_Check(in)) {
1616 *out = PyString_AsString(in);
1617 return 1;
1618 }
1619 if (PyTclObject_Check(in)) {
1620 *out = PyTclObject_TclString(in);
1621 return 1;
1622 }
1623 /* XXX: Should give diagnostics. */
1624 return 0;
1625}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001626
Guilherme Polo1972d162009-03-27 21:43:08 +00001627#ifdef WITH_THREAD
1628
Martin v. Löwis111c1802008-06-13 07:47:47 +00001629static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630var_perform(VarEvent *ev)
1631{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001632 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1633 if (!*(ev->res)) {
1634 PyObject *exc, *val, *tb;
1635 PyErr_Fetch(&exc, &val, &tb);
1636 PyErr_NormalizeException(&exc, &val, &tb);
1637 *(ev->exc_type) = exc;
1638 *(ev->exc_val) = val;
1639 Py_DECREF(tb);
1640 }
1641
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001642}
1643
1644static int
1645var_proc(VarEvent* ev, int flags)
1646{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001647 ENTER_PYTHON
1648 var_perform(ev);
1649 Tcl_MutexLock(&var_mutex);
1650 Tcl_ConditionNotify(ev->cond);
1651 Tcl_MutexUnlock(&var_mutex);
1652 LEAVE_PYTHON
1653 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654}
1655
Guilherme Polo1972d162009-03-27 21:43:08 +00001656#endif
1657
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001659var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001660{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001661#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001662 TkappObject *self = (TkappObject*)selfptr;
1663 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1664 TkappObject *self = (TkappObject*)selfptr;
1665 VarEvent *ev;
1666 PyObject *res, *exc_type, *exc_val;
1667 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001668
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001669 /* The current thread is not the interpreter thread. Marshal
1670 the call to the interpreter thread, then wait for
1671 completion. */
1672 if (!WaitForMainloop(self))
1673 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001674
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001675 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1676
1677 ev->self = selfptr;
1678 ev->args = args;
1679 ev->flags = flags;
1680 ev->func = func;
1681 ev->res = &res;
1682 ev->exc_type = &exc_type;
1683 ev->exc_val = &exc_val;
1684 ev->cond = &cond;
1685 ev->ev.proc = (Tcl_EventProc*)var_proc;
1686 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1687 Tcl_ConditionFinalize(&cond);
1688 if (!res) {
1689 PyErr_SetObject(exc_type, exc_val);
1690 Py_DECREF(exc_type);
1691 Py_DECREF(exc_val);
1692 return NULL;
1693 }
1694 return res;
1695 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001696#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001697 /* Tcl is not threaded, or this is the interpreter thread. */
1698 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001699}
1700
Guido van Rossum18468821994-06-20 07:49:28 +00001701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001704 char *name1, *name2;
1705 PyObject *newValue;
1706 PyObject *res = NULL;
1707 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001708
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001709 if (PyArg_ParseTuple(args, "O&O:setvar",
1710 varname_converter, &name1, &newValue)) {
1711 /* XXX Acquire tcl lock??? */
1712 newval = AsObj(newValue);
1713 if (newval == NULL)
1714 return NULL;
1715 ENTER_TCL
1716 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1717 newval, flags);
1718 ENTER_OVERLAP
1719 if (!ok)
1720 Tkinter_Error(self);
1721 else {
1722 res = Py_None;
1723 Py_INCREF(res);
1724 }
1725 LEAVE_OVERLAP_TCL
1726 }
1727 else {
1728 PyErr_Clear();
1729 if (PyArg_ParseTuple(args, "ssO:setvar",
1730 &name1, &name2, &newValue)) {
1731 /* XXX must hold tcl lock already??? */
1732 newval = AsObj(newValue);
1733 ENTER_TCL
1734 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1735 ENTER_OVERLAP
1736 if (!ok)
1737 Tkinter_Error(self);
1738 else {
1739 res = Py_None;
1740 Py_INCREF(res);
1741 }
1742 LEAVE_OVERLAP_TCL
1743 }
1744 else {
1745 return NULL;
1746 }
1747 }
1748 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001749}
1750
1751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001752Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001753{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001754 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001755}
1756
1757static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001758Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001759{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001760 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001761}
1762
Barry Warsawfa701a81997-01-16 00:15:11 +00001763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001764
Guido van Rossum18468821994-06-20 07:49:28 +00001765static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001766GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001767{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001768 char *name1, *name2=NULL;
1769 PyObject *res = NULL;
1770 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001771
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001772 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1773 varname_converter, &name1, &name2))
1774 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001775
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001776 ENTER_TCL
1777 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1778 ENTER_OVERLAP
1779 if (tres == NULL) {
1780 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1781 } else {
1782 if (((TkappObject*)self)->wantobjects) {
1783 res = FromObj(self, tres);
1784 }
1785 else {
1786 res = PyString_FromString(Tcl_GetString(tres));
1787 }
1788 }
1789 LEAVE_OVERLAP_TCL
1790 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001791}
1792
1793static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001794Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001795{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001796 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001797}
1798
1799static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001800Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001801{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001802 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001803}
1804
Barry Warsawfa701a81997-01-16 00:15:11 +00001805
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001806
Guido van Rossum18468821994-06-20 07:49:28 +00001807static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001808UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001809{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 char *name1, *name2=NULL;
1811 int code;
1812 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001813
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001814 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1815 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001816
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001817 ENTER_TCL
1818 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1819 ENTER_OVERLAP
1820 if (code == TCL_ERROR)
1821 res = Tkinter_Error(self);
1822 else {
1823 Py_INCREF(Py_None);
1824 res = Py_None;
1825 }
1826 LEAVE_OVERLAP_TCL
1827 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001828}
1829
1830static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001831Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001832{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001833 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001839 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001840}
1841
Barry Warsawfa701a81997-01-16 00:15:11 +00001842
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001843
Guido van Rossum18468821994-06-20 07:49:28 +00001844/** Tcl to Python **/
1845
1846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001849 char *s;
1850 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001851
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001852 if (PyTuple_Size(args) == 1) {
1853 PyObject* o = PyTuple_GetItem(args, 0);
1854 if (PyInt_Check(o)) {
1855 Py_INCREF(o);
1856 return o;
1857 }
1858 }
1859 if (!PyArg_ParseTuple(args, "s:getint", &s))
1860 return NULL;
1861 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1862 return Tkinter_Error(self);
1863 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001867Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001868{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 char *s;
1870 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001871
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001872 if (PyTuple_Size(args) == 1) {
1873 PyObject *o = PyTuple_GetItem(args, 0);
1874 if (PyFloat_Check(o)) {
1875 Py_INCREF(o);
1876 return o;
1877 }
1878 }
1879 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1880 return NULL;
1881 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1882 return Tkinter_Error(self);
1883 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001884}
1885
1886static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001887Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001888{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001889 char *s;
1890 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001891
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001892 if (PyTuple_Size(args) == 1) {
1893 PyObject *o = PyTuple_GetItem(args, 0);
1894 if (PyInt_Check(o)) {
1895 Py_INCREF(o);
1896 return o;
1897 }
1898 }
1899 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1900 return NULL;
1901 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1902 return Tkinter_Error(self);
1903 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001907Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 char *s;
1910 PyObject *res = NULL;
1911 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001912
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001913 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1914 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001915
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001916 CHECK_TCL_APPARTMENT;
1917
1918 ENTER_TCL
1919 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1920 ENTER_OVERLAP
1921 if (retval == TCL_ERROR)
1922 res = Tkinter_Error(self);
1923 else
1924 res = Py_BuildValue("s", Tkapp_Result(self));
1925 LEAVE_OVERLAP_TCL
1926 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001927}
1928
1929static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001930Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001931{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001932 char *s;
1933 PyObject *res = NULL;
1934 int retval;
1935 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001937 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1938 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001939
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001940 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001941
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001942 ENTER_TCL
1943 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1944 ENTER_OVERLAP
1945 if (retval == TCL_ERROR)
1946 res = Tkinter_Error(self);
1947 else
1948 res = Py_BuildValue("l", v);
1949 LEAVE_OVERLAP_TCL
1950 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001951}
1952
1953static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001954Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001955{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001956 char *s;
1957 PyObject *res = NULL;
1958 double v;
1959 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001961 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1962 return NULL;
1963 CHECK_TCL_APPARTMENT;
1964 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1965 ENTER_TCL
1966 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1967 ENTER_OVERLAP
1968 PyFPE_END_PROTECT(retval)
1969 if (retval == TCL_ERROR)
1970 res = Tkinter_Error(self);
1971 else
1972 res = Py_BuildValue("d", v);
1973 LEAVE_OVERLAP_TCL
1974 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001975}
1976
1977static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001978Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001979{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001980 char *s;
1981 PyObject *res = NULL;
1982 int retval;
1983 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001984
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001985 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1986 return NULL;
1987 CHECK_TCL_APPARTMENT;
1988 ENTER_TCL
1989 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1990 ENTER_OVERLAP
1991 if (retval == TCL_ERROR)
1992 res = Tkinter_Error(self);
1993 else
1994 res = Py_BuildValue("i", v);
1995 LEAVE_OVERLAP_TCL
1996 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001997}
1998
Barry Warsawfa701a81997-01-16 00:15:11 +00001999
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002000
Guido van Rossum18468821994-06-20 07:49:28 +00002001static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002002Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002003{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002004 char *list;
2005 int argc;
2006 char **argv;
2007 PyObject *v;
2008 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002009
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002010 if (PyTuple_Size(args) == 1) {
2011 v = PyTuple_GetItem(args, 0);
2012 if (PyTuple_Check(v)) {
2013 Py_INCREF(v);
2014 return v;
2015 }
2016 }
2017 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2018 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002019
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002020 if (Tcl_SplitList(Tkapp_Interp(self), list,
2021 &argc, &argv) == TCL_ERROR) {
2022 PyMem_Free(list);
2023 return Tkinter_Error(self);
2024 }
Guido van Rossum18468821994-06-20 07:49:28 +00002025
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002026 if (!(v = PyTuple_New(argc)))
2027 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002029 for (i = 0; i < argc; i++) {
2030 PyObject *s = PyString_FromString(argv[i]);
2031 if (!s || PyTuple_SetItem(v, i, s)) {
2032 Py_DECREF(v);
2033 v = NULL;
2034 goto finally;
2035 }
2036 }
Guido van Rossum18468821994-06-20 07:49:28 +00002037
Barry Warsawfa701a81997-01-16 00:15:11 +00002038 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002039 ckfree(FREECAST argv);
2040 PyMem_Free(list);
2041 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002042}
2043
2044static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002045Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002046{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002047 PyObject *v;
2048 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002049
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002050 if (PyTuple_Size(args) == 1) {
2051 PyObject* o = PyTuple_GetItem(args, 0);
2052 if (PyTuple_Check(o)) {
2053 o = SplitObj(o);
2054 return o;
2055 }
2056 }
2057 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2058 return NULL;
2059 v = Split(list);
2060 PyMem_Free(list);
2061 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002062}
2063
2064static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002065Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002066{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002067 char *s = Merge(args);
2068 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002069
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002070 if (s) {
2071 res = PyString_FromString(s);
2072 ckfree(s);
2073 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002075 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002076}
2077
Barry Warsawfa701a81997-01-16 00:15:11 +00002078
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002079
Guido van Rossum18468821994-06-20 07:49:28 +00002080/** Tcl Command **/
2081
Guido van Rossum00d93061998-05-28 23:06:38 +00002082/* Client data struct */
2083typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002084 PyObject *self;
2085 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002086} PythonCmd_ClientData;
2087
2088static int
Fred Drake509d79a2000-07-08 04:04:38 +00002089PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002090{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002091 errorInCmd = 1;
2092 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2093 LEAVE_PYTHON
2094 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002095}
2096
Guido van Rossum18468821994-06-20 07:49:28 +00002097/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002098 * function or method.
2099 */
Guido van Rossum18468821994-06-20 07:49:28 +00002100static int
Fred Drake509d79a2000-07-08 04:04:38 +00002101PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002102{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002103 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2104 PyObject *func, *arg, *res;
2105 int i, rv;
2106 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002107
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002108 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002109
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002110 /* TBD: no error checking here since we know, via the
2111 * Tkapp_CreateCommand() that the client data is a two-tuple
2112 */
2113 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002115 /* Create argument list (argv1, ..., argvN) */
2116 if (!(arg = PyTuple_New(argc - 1)))
2117 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002118
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002119 for (i = 0; i < (argc - 1); i++) {
2120 PyObject *s = PyString_FromString(argv[i + 1]);
2121 if (!s || PyTuple_SetItem(arg, i, s)) {
2122 Py_DECREF(arg);
2123 return PythonCmd_Error(interp);
2124 }
2125 }
2126 res = PyEval_CallObject(func, arg);
2127 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002128
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002129 if (res == NULL)
2130 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002131
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002132 obj_res = AsObj(res);
2133 if (obj_res == NULL) {
2134 Py_DECREF(res);
2135 return PythonCmd_Error(interp);
2136 }
2137 else {
2138 Tcl_SetObjResult(interp, obj_res);
2139 rv = TCL_OK;
2140 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002141
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002142 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002143
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002144 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002145
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002146 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
2149static void
Fred Drake509d79a2000-07-08 04:04:38 +00002150PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002151{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002152 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002153
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002154 ENTER_PYTHON
2155 Py_XDECREF(data->self);
2156 Py_XDECREF(data->func);
2157 PyMem_DEL(data);
2158 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002159}
2160
Barry Warsawfa701a81997-01-16 00:15:11 +00002161
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002162
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002163
Guilherme Polo1972d162009-03-27 21:43:08 +00002164#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002165TCL_DECLARE_MUTEX(command_mutex)
2166
2167typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002168 Tcl_Event ev;
2169 Tcl_Interp* interp;
2170 char *name;
2171 int create;
2172 int *status;
2173 ClientData *data;
2174 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002175} CommandEvent;
2176
2177static int
2178Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002179{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002180 if (ev->create)
2181 *ev->status = Tcl_CreateCommand(
2182 ev->interp, ev->name, PythonCmd,
2183 ev->data, PythonCmdDelete) == NULL;
2184 else
2185 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2186 Tcl_MutexLock(&command_mutex);
2187 Tcl_ConditionNotify(ev->done);
2188 Tcl_MutexUnlock(&command_mutex);
2189 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002190}
Guilherme Polo1972d162009-03-27 21:43:08 +00002191#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002192
2193static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002194Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002195{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002196 TkappObject *self = (TkappObject*)selfptr;
2197 PythonCmd_ClientData *data;
2198 char *cmdName;
2199 PyObject *func;
2200 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002201
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2203 return NULL;
2204 if (!PyCallable_Check(func)) {
2205 PyErr_SetString(PyExc_TypeError, "command not callable");
2206 return NULL;
2207 }
Guido van Rossum18468821994-06-20 07:49:28 +00002208
Martin v. Löwisa9656492003-03-30 08:44:58 +00002209#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002210 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2211 !WaitForMainloop(self))
2212 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002213#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002215 data = PyMem_NEW(PythonCmd_ClientData, 1);
2216 if (!data)
2217 return PyErr_NoMemory();
2218 Py_INCREF(self);
2219 Py_INCREF(func);
2220 data->self = selfptr;
2221 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002222
2223#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002224 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2225 Tcl_Condition cond = NULL;
2226 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2227 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2228 ev->interp = self->interp;
2229 ev->create = 1;
2230 ev->name = cmdName;
2231 ev->data = (ClientData)data;
2232 ev->status = &err;
2233 ev->done = &cond;
2234 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2235 Tcl_ConditionFinalize(&cond);
2236 }
2237 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002238#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002239 {
2240 ENTER_TCL
2241 err = Tcl_CreateCommand(
2242 Tkapp_Interp(self), cmdName, PythonCmd,
2243 (ClientData)data, PythonCmdDelete) == NULL;
2244 LEAVE_TCL
2245 }
2246 if (err) {
2247 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2248 PyMem_DEL(data);
2249 return NULL;
2250 }
Guido van Rossum18468821994-06-20 07:49:28 +00002251
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002252 Py_INCREF(Py_None);
2253 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002254}
2255
Barry Warsawfa701a81997-01-16 00:15:11 +00002256
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002257
Guido van Rossum18468821994-06-20 07:49:28 +00002258static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002259Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002260{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002261 TkappObject *self = (TkappObject*)selfptr;
2262 char *cmdName;
2263 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002264
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002265 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2266 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002267
2268#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002269 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2270 Tcl_Condition cond = NULL;
2271 CommandEvent *ev;
2272 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2273 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2274 ev->interp = self->interp;
2275 ev->create = 0;
2276 ev->name = cmdName;
2277 ev->status = &err;
2278 ev->done = &cond;
2279 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2280 &command_mutex);
2281 Tcl_ConditionFinalize(&cond);
2282 }
2283 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002284#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002285 {
2286 ENTER_TCL
2287 err = Tcl_DeleteCommand(self->interp, cmdName);
2288 LEAVE_TCL
2289 }
2290 if (err == -1) {
2291 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2292 return NULL;
2293 }
2294 Py_INCREF(Py_None);
2295 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002296}
2297
Barry Warsawfa701a81997-01-16 00:15:11 +00002298
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002299
Guido van Rossum00d93061998-05-28 23:06:38 +00002300#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002301/** File Handler **/
2302
Guido van Rossum00d93061998-05-28 23:06:38 +00002303typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002304 PyObject *func;
2305 PyObject *file;
2306 int id;
2307 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002308} FileHandler_ClientData;
2309
2310static FileHandler_ClientData *HeadFHCD;
2311
2312static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002313NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002314{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002315 FileHandler_ClientData *p;
2316 p = PyMem_NEW(FileHandler_ClientData, 1);
2317 if (p != NULL) {
2318 Py_XINCREF(func);
2319 Py_XINCREF(file);
2320 p->func = func;
2321 p->file = file;
2322 p->id = id;
2323 p->next = HeadFHCD;
2324 HeadFHCD = p;
2325 }
2326 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002327}
2328
2329static void
Fred Drake509d79a2000-07-08 04:04:38 +00002330DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002331{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002332 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002333
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002334 pp = &HeadFHCD;
2335 while ((p = *pp) != NULL) {
2336 if (p->id == id) {
2337 *pp = p->next;
2338 Py_XDECREF(p->func);
2339 Py_XDECREF(p->file);
2340 PyMem_DEL(p);
2341 }
2342 else
2343 pp = &p->next;
2344 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002345}
2346
Guido van Rossuma597dde1995-01-10 20:56:29 +00002347static void
Fred Drake509d79a2000-07-08 04:04:38 +00002348FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002349{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002350 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2351 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002353 ENTER_PYTHON
2354 func = data->func;
2355 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002356
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002357 arg = Py_BuildValue("(Oi)", file, (long) mask);
2358 res = PyEval_CallObject(func, arg);
2359 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002360
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002361 if (res == NULL) {
2362 errorInCmd = 1;
2363 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2364 }
2365 Py_XDECREF(res);
2366 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002367}
2368
Guido van Rossum18468821994-06-20 07:49:28 +00002369static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002370Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2371 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002372{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002373 FileHandler_ClientData *data;
2374 PyObject *file, *func;
2375 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002376
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002377 if (!self && Py_Py3kWarningFlag) {
2378 if (PyErr_Warn(PyExc_DeprecationWarning,
2379 "_tkinter.createfilehandler is gone in 3.x") < 0)
2380 return NULL;
2381 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002383 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2384 &file, &mask, &func))
2385 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002386
Martin v. Löwisa9656492003-03-30 08:44:58 +00002387#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002388 if (!self && !tcl_lock) {
2389 /* We don't have the Tcl lock since Tcl is threaded. */
2390 PyErr_SetString(PyExc_RuntimeError,
2391 "_tkinter.createfilehandler not supported "
2392 "for threaded Tcl");
2393 return NULL;
2394 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002395#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002396
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002397 if (self) {
2398 CHECK_TCL_APPARTMENT;
2399 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002400
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002401 tfile = PyObject_AsFileDescriptor(file);
2402 if (tfile < 0)
2403 return NULL;
2404 if (!PyCallable_Check(func)) {
2405 PyErr_SetString(PyExc_TypeError, "bad argument list");
2406 return NULL;
2407 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002409 data = NewFHCD(func, file, tfile);
2410 if (data == NULL)
2411 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002413 /* Ought to check for null Tcl_File object... */
2414 ENTER_TCL
2415 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2416 LEAVE_TCL
2417 Py_INCREF(Py_None);
2418 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002419}
2420
2421static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002422Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002423{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002424 PyObject *file;
2425 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002427 if (!self && Py_Py3kWarningFlag) {
2428 if (PyErr_Warn(PyExc_DeprecationWarning,
2429 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2430 return NULL;
2431 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002432
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002433 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2434 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002435
Martin v. Löwisa9656492003-03-30 08:44:58 +00002436#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002437 if (!self && !tcl_lock) {
2438 /* We don't have the Tcl lock since Tcl is threaded. */
2439 PyErr_SetString(PyExc_RuntimeError,
2440 "_tkinter.deletefilehandler not supported "
2441 "for threaded Tcl");
2442 return NULL;
2443 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002444#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002445
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002446 if (self) {
2447 CHECK_TCL_APPARTMENT;
2448 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002449
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002450 tfile = PyObject_AsFileDescriptor(file);
2451 if (tfile < 0)
2452 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002453
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002454 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 /* Ought to check for null Tcl_File object... */
2457 ENTER_TCL
2458 Tcl_DeleteFileHandler(tfile);
2459 LEAVE_TCL
2460 Py_INCREF(Py_None);
2461 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002462}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002463#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002464
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002465
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002466/**** Tktt Object (timer token) ****/
2467
Jeremy Hylton938ace62002-07-17 16:30:39 +00002468static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002469
Guido van Rossum00d93061998-05-28 23:06:38 +00002470typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002471 PyObject_HEAD
2472 Tcl_TimerToken token;
2473 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002474} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002475
2476static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002477Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 TkttObject *v = (TkttObject *)self;
2480 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002481
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002482 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2483 return NULL;
2484 if (v->token != NULL) {
2485 Tcl_DeleteTimerHandler(v->token);
2486 v->token = NULL;
2487 }
2488 if (func != NULL) {
2489 v->func = NULL;
2490 Py_DECREF(func);
2491 Py_DECREF(v); /* See Tktt_New() */
2492 }
2493 Py_INCREF(Py_None);
2494 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002495}
2496
2497static PyMethodDef Tktt_methods[] =
2498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002499 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2500 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002501};
2502
2503static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002504Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002505{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002506 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002507
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002508 v = PyObject_New(TkttObject, &Tktt_Type);
2509 if (v == NULL)
2510 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 Py_INCREF(func);
2513 v->token = NULL;
2514 v->func = func;
2515
2516 /* Extra reference, deleted when called or when handler is deleted */
2517 Py_INCREF(v);
2518 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002519}
2520
2521static void
Fred Drake509d79a2000-07-08 04:04:38 +00002522Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002523{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002524 TkttObject *v = (TkttObject *)self;
2525 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002526
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002527 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002528
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002529 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002530}
2531
Guido van Rossum597ac201998-05-12 14:36:19 +00002532static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002533Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002534{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002535 TkttObject *v = (TkttObject *)self;
2536 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002537
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002538 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2539 v->func == NULL ? ", handler deleted" : "");
2540 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002541}
2542
2543static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002544Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002545{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002546 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002547}
2548
2549static PyTypeObject Tktt_Type =
2550{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002551 PyVarObject_HEAD_INIT(NULL, 0)
2552 "tktimertoken", /*tp_name */
2553 sizeof(TkttObject), /*tp_basicsize */
2554 0, /*tp_itemsize */
2555 Tktt_Dealloc, /*tp_dealloc */
2556 0, /*tp_print */
2557 Tktt_GetAttr, /*tp_getattr */
2558 0, /*tp_setattr */
2559 0, /*tp_compare */
2560 Tktt_Repr, /*tp_repr */
2561 0, /*tp_as_number */
2562 0, /*tp_as_sequence */
2563 0, /*tp_as_mapping */
2564 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002565};
2566
Barry Warsawfa701a81997-01-16 00:15:11 +00002567
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002568
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002569/** Timer Handler **/
2570
2571static void
Fred Drake509d79a2000-07-08 04:04:38 +00002572TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002573{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002574 TkttObject *v = (TkttObject *)clientData;
2575 PyObject *func = v->func;
2576 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002577
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002578 if (func == NULL)
2579 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002580
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002581 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002582
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002583 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002585 res = PyEval_CallObject(func, NULL);
2586 Py_DECREF(func);
2587 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002588
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002589 if (res == NULL) {
2590 errorInCmd = 1;
2591 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2592 }
2593 else
2594 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002595
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002596 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002597}
2598
2599static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002600Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002601{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002602 int milliseconds;
2603 PyObject *func;
2604 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002605
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002606 if (!self && Py_Py3kWarningFlag) {
2607 if (PyErr_Warn(PyExc_DeprecationWarning,
2608 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2609 return NULL;
2610 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002611
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002612 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2613 &milliseconds, &func))
2614 return NULL;
2615 if (!PyCallable_Check(func)) {
2616 PyErr_SetString(PyExc_TypeError, "bad argument list");
2617 return NULL;
2618 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002619
Martin v. Löwisa9656492003-03-30 08:44:58 +00002620#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002621 if (!self && !tcl_lock) {
2622 /* We don't have the Tcl lock since Tcl is threaded. */
2623 PyErr_SetString(PyExc_RuntimeError,
2624 "_tkinter.createtimerhandler not supported "
2625 "for threaded Tcl");
2626 return NULL;
2627 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002628#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002629
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002630 if (self) {
2631 CHECK_TCL_APPARTMENT;
2632 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002633
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002634 v = Tktt_New(func);
2635 if (v) {
2636 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2637 (ClientData)v);
2638 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002639
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002640 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002641}
2642
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002643
Guido van Rossum18468821994-06-20 07:49:28 +00002644/** Event Loop **/
2645
Guido van Rossum18468821994-06-20 07:49:28 +00002646static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002647Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002648{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002649 int threshold = 0;
2650 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002651#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002652 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002653#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002654
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002655 if (!self && Py_Py3kWarningFlag) {
2656 if (PyErr_Warn(PyExc_DeprecationWarning,
2657 "_tkinter.mainloop is gone in 3.x") < 0)
2658 return NULL;
2659 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002660
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002661 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2662 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002663
Martin v. Löwisa9656492003-03-30 08:44:58 +00002664#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002665 if (!self && !tcl_lock) {
2666 /* We don't have the Tcl lock since Tcl is threaded. */
2667 PyErr_SetString(PyExc_RuntimeError,
2668 "_tkinter.mainloop not supported "
2669 "for threaded Tcl");
2670 return NULL;
2671 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002672#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002673
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002674 if (self) {
2675 CHECK_TCL_APPARTMENT;
2676 self->dispatching = 1;
2677 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002678
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002679 quitMainLoop = 0;
2680 while (Tk_GetNumMainWindows() > threshold &&
2681 !quitMainLoop &&
2682 !errorInCmd)
2683 {
2684 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002685
2686#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002687 if (self && self->threaded) {
2688 /* Allow other Python threads to run. */
2689 ENTER_TCL
2690 result = Tcl_DoOneEvent(0);
2691 LEAVE_TCL
2692 }
2693 else {
2694 Py_BEGIN_ALLOW_THREADS
2695 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2696 tcl_tstate = tstate;
2697 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2698 tcl_tstate = NULL;
2699 if(tcl_lock)PyThread_release_lock(tcl_lock);
2700 if (result == 0)
2701 Sleep(Tkinter_busywaitinterval);
2702 Py_END_ALLOW_THREADS
2703 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002704#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002705 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002706#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002707
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002708 if (PyErr_CheckSignals() != 0) {
2709 if (self)
2710 self->dispatching = 0;
2711 return NULL;
2712 }
2713 if (result < 0)
2714 break;
2715 }
2716 if (self)
2717 self->dispatching = 0;
2718 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002719
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002720 if (errorInCmd) {
2721 errorInCmd = 0;
2722 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2723 excInCmd = valInCmd = trbInCmd = NULL;
2724 return NULL;
2725 }
2726 Py_INCREF(Py_None);
2727 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002728}
2729
2730static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002731Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002732{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002733 int flags = 0;
2734 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002735
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002736 if (!self && Py_Py3kWarningFlag) {
2737 if (PyErr_Warn(PyExc_DeprecationWarning,
2738 "_tkinter.dooneevent is gone in 3.x") < 0)
2739 return NULL;
2740 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002741
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002742 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2743 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002744
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002745 ENTER_TCL
2746 rv = Tcl_DoOneEvent(flags);
2747 LEAVE_TCL
2748 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002749}
2750
2751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002752Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002753{
2754
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002755 if (!self && Py_Py3kWarningFlag) {
2756 if (PyErr_Warn(PyExc_DeprecationWarning,
2757 "_tkinter.quit is gone in 3.x") < 0)
2758 return NULL;
2759 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002760
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002761 if (!PyArg_ParseTuple(args, ":quit"))
2762 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002764 quitMainLoop = 1;
2765 Py_INCREF(Py_None);
2766 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002767}
2768
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002769static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002770Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002771{
2772
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002773 if (!PyArg_ParseTuple(args, ":interpaddr"))
2774 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002775
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002776 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002777}
2778
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002779static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002780Tkapp_TkInit(PyObject *self, PyObject *args)
2781{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002782 Tcl_Interp *interp = Tkapp_Interp(self);
2783 const char * _tk_exists = NULL;
2784 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002785
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002786#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002787 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2788 * first call failed.
2789 * To avoid the deadlock, we just refuse the second call through
2790 * a static variable.
2791 */
2792 if (tk_load_failed) {
2793 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2794 return NULL;
2795 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002796#endif
2797
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002798 /* We want to guard against calling Tk_Init() multiple times */
2799 CHECK_TCL_APPARTMENT;
2800 ENTER_TCL
2801 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2802 ENTER_OVERLAP
2803 if (err == TCL_ERROR) {
2804 /* This sets an exception, but we cannot return right
2805 away because we need to exit the overlap first. */
2806 Tkinter_Error(self);
2807 } else {
2808 _tk_exists = Tkapp_Result(self);
2809 }
2810 LEAVE_OVERLAP_TCL
2811 if (err == TCL_ERROR) {
2812 return NULL;
2813 }
2814 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2815 if (Tk_Init(interp) == TCL_ERROR) {
2816 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002817#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002818 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002819#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002820 return NULL;
2821 }
2822 }
2823 Py_INCREF(Py_None);
2824 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002825}
Barry Warsawfa701a81997-01-16 00:15:11 +00002826
Martin v. Löwisffad6332002-11-26 09:28:05 +00002827static PyObject *
2828Tkapp_WantObjects(PyObject *self, PyObject *args)
2829{
2830
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002831 int wantobjects = -1;
2832 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2833 return NULL;
2834 if (wantobjects == -1)
2835 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2836 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002837
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002838 Py_INCREF(Py_None);
2839 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002840}
2841
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002842static PyObject *
2843Tkapp_WillDispatch(PyObject *self, PyObject *args)
2844{
2845
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002846 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002847
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002848 Py_INCREF(Py_None);
2849 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002850}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002851
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002852
Guido van Rossum18468821994-06-20 07:49:28 +00002853/**** Tkapp Method List ****/
2854
2855static PyMethodDef Tkapp_methods[] =
2856{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002857 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2858 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2859 {"call", Tkapp_Call, METH_VARARGS},
2860 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2861 {"eval", Tkapp_Eval, METH_VARARGS},
2862 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2863 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2864 {"record", Tkapp_Record, METH_VARARGS},
2865 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2866 {"setvar", Tkapp_SetVar, METH_VARARGS},
2867 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2868 {"getvar", Tkapp_GetVar, METH_VARARGS},
2869 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2870 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2871 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2872 {"getint", Tkapp_GetInt, METH_VARARGS},
2873 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2874 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2875 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2876 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2877 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2878 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2879 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2880 {"split", Tkapp_Split, METH_VARARGS},
2881 {"merge", Tkapp_Merge, METH_VARARGS},
2882 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2883 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002884#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002885 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2886 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002887#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002888 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2889 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2890 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2891 {"quit", Tkapp_Quit, METH_VARARGS},
2892 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2893 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2894 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002895};
2896
Barry Warsawfa701a81997-01-16 00:15:11 +00002897
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002898
Guido van Rossum18468821994-06-20 07:49:28 +00002899/**** Tkapp Type Methods ****/
2900
2901static void
Fred Drake509d79a2000-07-08 04:04:38 +00002902Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002903{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002904 /*CHECK_TCL_APPARTMENT;*/
2905 ENTER_TCL
2906 Tcl_DeleteInterp(Tkapp_Interp(self));
2907 LEAVE_TCL
2908 PyObject_Del(self);
2909 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002910}
2911
2912static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002913Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002915 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002916}
2917
2918static PyTypeObject Tkapp_Type =
2919{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002920 PyVarObject_HEAD_INIT(NULL, 0)
2921 "tkapp", /*tp_name */
2922 sizeof(TkappObject), /*tp_basicsize */
2923 0, /*tp_itemsize */
2924 Tkapp_Dealloc, /*tp_dealloc */
2925 0, /*tp_print */
2926 Tkapp_GetAttr, /*tp_getattr */
2927 0, /*tp_setattr */
2928 0, /*tp_compare */
2929 0, /*tp_repr */
2930 0, /*tp_as_number */
2931 0, /*tp_as_sequence */
2932 0, /*tp_as_mapping */
2933 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002934};
2935
Barry Warsawfa701a81997-01-16 00:15:11 +00002936
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002937
Guido van Rossum18468821994-06-20 07:49:28 +00002938/**** Tkinter Module ****/
2939
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002940typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002941 PyObject* tuple;
2942 int size; /* current size */
2943 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002944} FlattenContext;
2945
2946static int
2947_bump(FlattenContext* context, int size)
2948{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002949 /* expand tuple to hold (at least) size new items.
2950 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002951
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002952 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002953
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002954 if (maxsize < context->size + size)
2955 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002956
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002957 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002958
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002959 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002960}
2961
2962static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002963_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002964{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002965 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002966
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002967 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002968
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002969 if (depth > 1000) {
2970 PyErr_SetString(PyExc_ValueError,
2971 "nesting too deep in _flatten");
2972 return 0;
2973 } else if (PyList_Check(item)) {
2974 size = PyList_GET_SIZE(item);
2975 /* preallocate (assume no nesting) */
2976 if (context->size + size > context->maxsize &&
2977 !_bump(context, size))
2978 return 0;
2979 /* copy items to output tuple */
2980 for (i = 0; i < size; i++) {
2981 PyObject *o = PyList_GET_ITEM(item, i);
2982 if (PyList_Check(o) || PyTuple_Check(o)) {
2983 if (!_flatten1(context, o, depth + 1))
2984 return 0;
2985 } else if (o != Py_None) {
2986 if (context->size + 1 > context->maxsize &&
2987 !_bump(context, 1))
2988 return 0;
2989 Py_INCREF(o);
2990 PyTuple_SET_ITEM(context->tuple,
2991 context->size++, o);
2992 }
2993 }
2994 } else if (PyTuple_Check(item)) {
2995 /* same, for tuples */
2996 size = PyTuple_GET_SIZE(item);
2997 if (context->size + size > context->maxsize &&
2998 !_bump(context, size))
2999 return 0;
3000 for (i = 0; i < size; i++) {
3001 PyObject *o = PyTuple_GET_ITEM(item, i);
3002 if (PyList_Check(o) || PyTuple_Check(o)) {
3003 if (!_flatten1(context, o, depth + 1))
3004 return 0;
3005 } else if (o != Py_None) {
3006 if (context->size + 1 > context->maxsize &&
3007 !_bump(context, 1))
3008 return 0;
3009 Py_INCREF(o);
3010 PyTuple_SET_ITEM(context->tuple,
3011 context->size++, o);
3012 }
3013 }
3014 } else {
3015 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3016 return 0;
3017 }
3018 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003019}
3020
3021static PyObject *
3022Tkinter_Flatten(PyObject* self, PyObject* args)
3023{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003024 FlattenContext context;
3025 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003027 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3028 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003029
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003030 context.maxsize = PySequence_Size(item);
3031 if (context.maxsize < 0)
3032 return NULL;
3033 if (context.maxsize == 0)
3034 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003035
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003036 context.tuple = PyTuple_New(context.maxsize);
3037 if (!context.tuple)
3038 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003040 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003042 if (!_flatten1(&context, item,0))
3043 return NULL;
3044
3045 if (_PyTuple_Resize(&context.tuple, context.size))
3046 return NULL;
3047
3048 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003049}
3050
Guido van Rossum18468821994-06-20 07:49:28 +00003051static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003052Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003053{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003054 char *screenName = NULL;
3055 char *baseName = NULL;
3056 char *className = NULL;
3057 int interactive = 0;
3058 int wantobjects = 0;
3059 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3060 int sync = 0; /* pass -sync to wish */
3061 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003062
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003063 baseName = strrchr(Py_GetProgramName(), '/');
3064 if (baseName != NULL)
3065 baseName++;
3066 else
3067 baseName = Py_GetProgramName();
3068 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003069
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003070 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3071 &screenName, &baseName, &className,
3072 &interactive, &wantobjects, &wantTk,
3073 &sync, &use))
3074 return NULL;
3075
3076 return (PyObject *) Tkapp_New(screenName, baseName, className,
3077 interactive, wantobjects, wantTk,
3078 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003079}
3080
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003081static PyObject *
3082Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3083{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003084 int new_val;
3085 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3086 return NULL;
3087 if (new_val < 0) {
3088 PyErr_SetString(PyExc_ValueError,
3089 "busywaitinterval must be >= 0");
3090 return NULL;
3091 }
3092 Tkinter_busywaitinterval = new_val;
3093 Py_INCREF(Py_None);
3094 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003095}
3096
3097static char setbusywaitinterval_doc[] =
3098"setbusywaitinterval(n) -> None\n\
3099\n\
3100Set the busy-wait interval in milliseconds between successive\n\
3101calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3102It should be set to a divisor of the maximum time between\n\
3103frames in an animation.";
3104
3105static PyObject *
3106Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3107{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003108 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003109}
3110
3111static char getbusywaitinterval_doc[] =
3112"getbusywaitinterval() -> int\n\
3113\n\
3114Return the current busy-wait interval between successive\n\
3115calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3116
Guido van Rossum18468821994-06-20 07:49:28 +00003117static PyMethodDef moduleMethods[] =
3118{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003119 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3120 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003121#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003122 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3123 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003124#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003125 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3126 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3127 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3128 {"quit", Tkapp_Quit, METH_VARARGS},
3129 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3130 setbusywaitinterval_doc},
3131 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3132 METH_NOARGS, getbusywaitinterval_doc},
3133 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003134};
3135
Guido van Rossum7bf15641998-05-22 18:28:17 +00003136#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003137
3138static int stdin_ready = 0;
3139
Guido van Rossumad4db171998-06-13 13:56:28 +00003140#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003141static void
Fred Drake509d79a2000-07-08 04:04:38 +00003142MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003143{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003144 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003145}
Guido van Rossumad4db171998-06-13 13:56:28 +00003146#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003147
Martin v. Löwisa9656492003-03-30 08:44:58 +00003148#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003149static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003150#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003151
Guido van Rossum18468821994-06-20 07:49:28 +00003152static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003153EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003154{
Guido van Rossumad4db171998-06-13 13:56:28 +00003155#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003156 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003157#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003158#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003159 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003160#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003161 stdin_ready = 0;
3162 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003163#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003164 tfile = fileno(stdin);
3165 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003166#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003167 while (!errorInCmd && !stdin_ready) {
3168 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003169#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003170 if (_kbhit()) {
3171 stdin_ready = 1;
3172 break;
3173 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003174#endif
3175#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 Py_BEGIN_ALLOW_THREADS
3177 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3178 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003179
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003180 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003181
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003182 tcl_tstate = NULL;
3183 if(tcl_lock)PyThread_release_lock(tcl_lock);
3184 if (result == 0)
3185 Sleep(Tkinter_busywaitinterval);
3186 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003187#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003188 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003189#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003190
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003191 if (result < 0)
3192 break;
3193 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003194#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003195 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003196#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003197 if (errorInCmd) {
3198 errorInCmd = 0;
3199 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3200 excInCmd = valInCmd = trbInCmd = NULL;
3201 PyErr_Print();
3202 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003203#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003204 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003205#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003206 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003207}
Guido van Rossum18468821994-06-20 07:49:28 +00003208
Guido van Rossum00d93061998-05-28 23:06:38 +00003209#endif
3210
Guido van Rossum7bf15641998-05-22 18:28:17 +00003211static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003212EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003213{
Guido van Rossum00d93061998-05-28 23:06:38 +00003214#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003215 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003216#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003218#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003219 PyOS_InputHook = EventHook;
3220 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003221#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003222}
3223
3224static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003225DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003226{
Guido van Rossum00d93061998-05-28 23:06:38 +00003227#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003228 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3229 PyOS_InputHook = NULL;
3230 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003231#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003232}
3233
Barry Warsawfa701a81997-01-16 00:15:11 +00003234
3235/* all errors will be checked in one fell swoop in init_tkinter() */
3236static void
Fred Drake509d79a2000-07-08 04:04:38 +00003237ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003238{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003239 PyObject *v = PyInt_FromLong(val);
3240 if (v) {
3241 PyDict_SetItemString(d, name, v);
3242 Py_DECREF(v);
3243 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003244}
3245static void
Fred Drake509d79a2000-07-08 04:04:38 +00003246ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003247{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003248 PyObject *v = PyString_FromString(val);
3249 if (v) {
3250 PyDict_SetItemString(d, name, v);
3251 Py_DECREF(v);
3252 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003253}
3254
3255
Mark Hammond62b1ab12002-07-23 06:31:15 +00003256PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003257init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003258{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003259 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003260
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003261 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003262
3263#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003265#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003266
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003267 m = Py_InitModule("_tkinter", moduleMethods);
3268 if (m == NULL)
3269 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003270
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003271 d = PyModule_GetDict(m);
3272 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3273 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003274
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003275 ins_long(d, "READABLE", TCL_READABLE);
3276 ins_long(d, "WRITABLE", TCL_WRITABLE);
3277 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3278 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3279 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3280 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3281 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3282 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3283 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3284 ins_string(d, "TK_VERSION", TK_VERSION);
3285 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003286
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003287 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003288
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003289 Py_TYPE(&Tktt_Type) = &PyType_Type;
3290 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003291
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003292 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3293 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003294
3295#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003296 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3297 * start waking up. Note that Tcl_FindExecutable will do this, this
3298 * code must be above it! The original warning from
3299 * tkMacOSXAppInit.c is copied below.
3300 *
3301 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3302 * Tcl interpreter for now. It probably should work to do this
3303 * in the other order, but for now it doesn't seem to.
3304 *
3305 */
3306 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003307#endif
3308
3309
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003310 /* This helps the dynamic loader; in Unicode aware Tcl versions
3311 it also helps Tcl find its encodings. */
3312 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003313
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003314 if (PyErr_Occurred())
3315 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003316
Guido van Rossum43ff8681998-07-14 18:02:13 +00003317#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003318 /* This was not a good idea; through <Destroy> bindings,
3319 Tcl_Finalize() may invoke Python code but at that point the
3320 interpreter and thread state have already been destroyed! */
3321 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003322#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003323
Guido van Rossum18468821994-06-20 07:49:28 +00003324}