blob: 8d52b891d56909ec16c0d1e03441caf080a929a3 [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
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200459#ifdef Py_USING_UNICODE
460static PyObject *
461unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
462{
463 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
464 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
465 /* Tcl encodes null character as \xc0\x80 */
466 if (memchr(s, '\xc0', size)) {
467 char *buf, *q;
468 const char *e = s + size;
469 PyErr_Clear();
470 q = buf = (char *)PyMem_Malloc(size);
471 if (buf == NULL)
472 return NULL;
473 while (s != e) {
474 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
475 *q++ = '\0';
476 s += 2;
477 }
478 else
479 *q++ = *s++;
480 }
481 s = buf;
482 size = q - s;
483 r = PyUnicode_DecodeUTF8(s, size, NULL);
484 PyMem_Free(buf);
485 }
486 }
487 return r;
488}
489#endif
490
491static PyObject *
492fromTclStringAndSize(const char *s, Py_ssize_t size)
493{
494 PyObject *r;
495#ifdef Py_USING_UNICODE
496 Py_ssize_t i;
497 /* If Tcl string contains any bytes with the top bit set,
498 it's UTF-8 and we should decode it to Unicode */
499 for (i = 0; i < size; i++)
500 if (s[i] & 0x80)
501 break;
502 if (i != size) {
503 /* It isn't an ASCII string. */
504 r = unicode_FromTclStringAndSize(s, size);
505 if (r)
506 return r;
507 PyErr_Clear();
508 }
509#endif
510 r = PyString_FromStringAndSize(s, size);
511 return r;
512}
513
514static PyObject *
515fromTclString(const char *s)
516{
517 return fromTclStringAndSize(s, strlen(s));
518}
519
520
Guido van Rossum18468821994-06-20 07:49:28 +0000521static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000522Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000523{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000524 int argc;
525 char **argv;
526 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000527
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000528 if (list == NULL) {
529 Py_INCREF(Py_None);
530 return Py_None;
531 }
Guido van Rossum18468821994-06-20 07:49:28 +0000532
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000533 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
534 /* Not a list.
535 * Could be a quoted string containing funnies, e.g. {"}.
536 * Return the string itself.
537 */
538 return PyString_FromString(list);
539 }
Guido van Rossum18468821994-06-20 07:49:28 +0000540
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000541 if (argc == 0)
542 v = PyString_FromString("");
543 else if (argc == 1)
544 v = PyString_FromString(argv[0]);
545 else if ((v = PyTuple_New(argc)) != NULL) {
546 int i;
547 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000548
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000549 for (i = 0; i < argc; i++) {
550 if ((w = Split(argv[i])) == NULL) {
551 Py_DECREF(v);
552 v = NULL;
553 break;
554 }
555 PyTuple_SetItem(v, i, w);
556 }
557 }
558 Tcl_Free(FREECAST argv);
559 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000560}
561
Martin v. Löwisffad6332002-11-26 09:28:05 +0000562/* In some cases, Tcl will still return strings that are supposed to be
563 lists. SplitObj walks through a nested tuple, finding string objects that
564 need to be split. */
565
Martin v. Löwis111c1802008-06-13 07:47:47 +0000566static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000567SplitObj(PyObject *arg)
568{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000569 if (PyTuple_Check(arg)) {
570 int i, size;
571 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000572
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000573 size = PyTuple_Size(arg);
574 result = NULL;
575 /* Recursively invoke SplitObj for all tuple items.
576 If this does not return a new object, no action is
577 needed. */
578 for(i = 0; i < size; i++) {
579 elem = PyTuple_GetItem(arg, i);
580 newelem = SplitObj(elem);
581 if (!newelem) {
582 Py_XDECREF(result);
583 return NULL;
584 }
585 if (!result) {
586 int k;
587 if (newelem == elem) {
588 Py_DECREF(newelem);
589 continue;
590 }
591 result = PyTuple_New(size);
592 if (!result)
593 return NULL;
594 for(k = 0; k < i; k++) {
595 elem = PyTuple_GetItem(arg, k);
596 Py_INCREF(elem);
597 PyTuple_SetItem(result, k, elem);
598 }
599 }
600 PyTuple_SetItem(result, i, newelem);
601 }
602 if (result)
603 return result;
604 /* Fall through, returning arg. */
605 }
606 else if (PyString_Check(arg)) {
607 int argc;
608 char **argv;
609 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000610
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
612 Py_INCREF(arg);
613 return arg;
614 }
615 Tcl_Free(FREECAST argv);
616 if (argc > 1)
617 return Split(PyString_AsString(arg));
618 /* Fall through, returning arg. */
619 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300620 else if (PyUnicode_Check(arg)) {
621 int argc;
622 char **argv;
623 char *list;
624 PyObject *s = PyUnicode_AsUTF8String(arg);
625
626 if (s == NULL) {
627 Py_INCREF(arg);
628 return arg;
629 }
630 list = PyString_AsString(s);
631
632 if (list == NULL ||
633 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
634 Py_DECREF(s);
635 Py_INCREF(arg);
636 return arg;
637 }
638 Tcl_Free(FREECAST argv);
639 if (argc > 1) {
640 PyObject *v = Split(list);
641 Py_DECREF(s);
642 return v;
643 }
644 Py_DECREF(s);
645 /* Fall through, returning arg. */
646 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000647 Py_INCREF(arg);
648 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000649}
Barry Warsawfa701a81997-01-16 00:15:11 +0000650
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000651
Guido van Rossum18468821994-06-20 07:49:28 +0000652/**** Tkapp Object ****/
653
654#ifndef WITH_APPINIT
655int
Fred Drake509d79a2000-07-08 04:04:38 +0000656Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000657{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000658 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000659
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000660 if (Tcl_Init(interp) == TCL_ERROR) {
661 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
662 return TCL_ERROR;
663 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000664
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000665 _tkinter_skip_tk_init = Tcl_GetVar(interp,
666 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
667 if (_tkinter_skip_tk_init != NULL &&
668 strcmp(_tkinter_skip_tk_init, "1") == 0) {
669 return TCL_OK;
670 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000671
672#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000673 if (tk_load_failed) {
674 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
675 return TCL_ERROR;
676 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000677#endif
678
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000679 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000680#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000681 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000682#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
684 return TCL_ERROR;
685 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000688}
689#endif /* !WITH_APPINIT */
690
Guido van Rossum18468821994-06-20 07:49:28 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692
Barry Warsawfa701a81997-01-16 00:15:11 +0000693
694/* Initialize the Tk application; see the `main' function in
695 * `tkMain.c'.
696 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000697
Thomas Wouters58d05102000-07-24 14:43:35 +0000698static void EnableEventHook(void); /* Forward */
699static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000700
Barry Warsawfa701a81997-01-16 00:15:11 +0000701static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000702Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000703 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000704{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000705 TkappObject *v;
706 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000707
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000708 v = PyObject_New(TkappObject, &Tkapp_Type);
709 if (v == NULL)
710 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000711
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000712 v->interp = Tcl_CreateInterp();
713 v->wantobjects = wantobjects;
714 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
715 TCL_GLOBAL_ONLY) != NULL;
716 v->thread_id = Tcl_GetCurrentThread();
717 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000718
719#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000720 if (v->threaded) {
721 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
722 Py_DECREF(v);
723 return 0;
724 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000725#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000726#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000727 if (v->threaded && tcl_lock) {
728 /* If Tcl is threaded, we don't need the lock. */
729 PyThread_free_lock(tcl_lock);
730 tcl_lock = NULL;
731 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000732#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000733
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000734 v->BooleanType = Tcl_GetObjType("boolean");
735 v->ByteArrayType = Tcl_GetObjType("bytearray");
736 v->DoubleType = Tcl_GetObjType("double");
737 v->IntType = Tcl_GetObjType("int");
738 v->ListType = Tcl_GetObjType("list");
739 v->ProcBodyType = Tcl_GetObjType("procbody");
740 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000741
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000742 /* Delete the 'exit' command, which can screw things up */
743 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000744
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000745 if (screenName != NULL)
746 Tcl_SetVar2(v->interp, "env", "DISPLAY",
747 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000748
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000749 if (interactive)
750 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
751 else
752 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000753
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000754 /* This is used to get the application class for Tk 4.1 and up */
755 argv0 = (char*)ckalloc(strlen(className) + 1);
756 if (!argv0) {
757 PyErr_NoMemory();
758 Py_DECREF(v);
759 return NULL;
760 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000761
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200763 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
764 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000765 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
766 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000767
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000768 if (! wantTk) {
769 Tcl_SetVar(v->interp,
770 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
771 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000772#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000773 else if (tk_load_failed) {
774 Tcl_SetVar(v->interp,
775 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
776 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000777#endif
David Aschere2b4b322004-02-18 05:59:53 +0000778
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000779 /* some initial arguments need to be in argv */
780 if (sync || use) {
781 char *args;
782 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000783
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000784 if (sync)
785 len += sizeof "-sync";
786 if (use)
787 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000788
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000789 args = (char*)ckalloc(len);
790 if (!args) {
791 PyErr_NoMemory();
792 Py_DECREF(v);
793 return NULL;
794 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000795
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000796 args[0] = '\0';
797 if (sync)
798 strcat(args, "-sync");
799 if (use) {
800 if (sync)
801 strcat(args, " ");
802 strcat(args, "-use ");
803 strcat(args, use);
804 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000805
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000806 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
807 ckfree(args);
808 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000809
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000810 if (Tcl_AppInit(v->interp) != TCL_OK) {
811 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000812#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000813 if (wantTk) {
814 const char *_tkinter_tk_failed;
815 _tkinter_tk_failed = Tcl_GetVar(v->interp,
816 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000817
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000818 if ( _tkinter_tk_failed != NULL &&
819 strcmp(_tkinter_tk_failed, "1") == 0) {
820 tk_load_failed = 1;
821 }
822 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000823#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000824 Py_DECREF((PyObject *)v);
825 return (TkappObject *)result;
826 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000827
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000828 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000829
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000831}
832
Barry Warsawfa701a81997-01-16 00:15:11 +0000833
Guilherme Polo1972d162009-03-27 21:43:08 +0000834#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000835static void
836Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000837 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000839 Py_BEGIN_ALLOW_THREADS;
840 Tcl_MutexLock(mutex);
841 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
842 Tcl_ThreadAlert(self->thread_id);
843 Tcl_ConditionWait(cond, mutex, NULL);
844 Tcl_MutexUnlock(mutex);
845 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000846}
Guilherme Polo1972d162009-03-27 21:43:08 +0000847#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000848
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000849
Guido van Rossum18468821994-06-20 07:49:28 +0000850/** Tcl Eval **/
851
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000853 PyObject_HEAD
854 Tcl_Obj *value;
855 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000856} PyTclObject;
857
858staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000859#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860
861static PyObject *
862newPyTclObject(Tcl_Obj *arg)
863{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000864 PyTclObject *self;
865 self = PyObject_New(PyTclObject, &PyTclObject_Type);
866 if (self == NULL)
867 return NULL;
868 Tcl_IncrRefCount(arg);
869 self->value = arg;
870 self->string = NULL;
871 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000872}
873
874static void
875PyTclObject_dealloc(PyTclObject *self)
876{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000877 Tcl_DecrRefCount(self->value);
878 Py_XDECREF(self->string);
879 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000880}
881
882static PyObject *
883PyTclObject_str(PyTclObject *self)
884{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000885 if (self->string && PyString_Check(self->string)) {
886 Py_INCREF(self->string);
887 return self->string;
888 }
889 /* XXX Could cache value if it is an ASCII string. */
890 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000891}
892
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000893static char*
894PyTclObject_TclString(PyObject *self)
895{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000896 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000897}
898
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000899/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000900PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000901"the string representation of this object, either as string or Unicode");
902
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000903static PyObject *
904PyTclObject_string(PyTclObject *self, void *ignored)
905{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000906 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200907 int len;
908 char *s = Tcl_GetStringFromObj(self->value, &len);
909 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000910 if (!self->string)
911 return NULL;
912 }
913 Py_INCREF(self->string);
914 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000915}
916
917#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000918PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
919
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000920static PyObject *
921PyTclObject_unicode(PyTclObject *self, void *ignored)
922{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000923 char *s;
924 int len;
925 if (self->string && PyUnicode_Check(self->string)) {
926 Py_INCREF(self->string);
927 return self->string;
928 }
929 /* XXX Could chache result if it is non-ASCII. */
930 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200931 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000932}
933#endif
934
Martin v. Löwisffad6332002-11-26 09:28:05 +0000935static PyObject *
936PyTclObject_repr(PyTclObject *self)
937{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000938 char buf[50];
939 PyOS_snprintf(buf, 50, "<%s object at %p>",
940 self->value->typePtr->name, self->value);
941 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000942}
943
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000944static int
945PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
946{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000947 int res;
948 res = strcmp(Tcl_GetString(self->value),
949 Tcl_GetString(other->value));
950 if (res < 0) return -1;
951 if (res > 0) return 1;
952 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000953}
954
Martin v. Löwis39195712003-01-04 00:33:13 +0000955PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
956
Martin v. Löwisffad6332002-11-26 09:28:05 +0000957static PyObject*
958get_typename(PyTclObject* obj, void* ignored)
959{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000960 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961}
962
Martin v. Löwis39195712003-01-04 00:33:13 +0000963
Martin v. Löwisffad6332002-11-26 09:28:05 +0000964static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000965 {"typename", (getter)get_typename, NULL, get_typename__doc__},
966 {"string", (getter)PyTclObject_string, NULL,
967 PyTclObject_string__doc__},
968 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000969};
970
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000971static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000972#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000973 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
974 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000975#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000976 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000977};
978
Martin v. Löwisffad6332002-11-26 09:28:05 +0000979statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000980 PyObject_HEAD_INIT(NULL)
981 0, /*ob_size*/
982 "_tkinter.Tcl_Obj", /*tp_name*/
983 sizeof(PyTclObject), /*tp_basicsize*/
984 0, /*tp_itemsize*/
985 /* methods */
986 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
987 0, /*tp_print*/
988 0, /*tp_getattr*/
989 0, /*tp_setattr*/
990 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
991 (reprfunc)PyTclObject_repr, /*tp_repr*/
992 0, /*tp_as_number*/
993 0, /*tp_as_sequence*/
994 0, /*tp_as_mapping*/
995 0, /*tp_hash*/
996 0, /*tp_call*/
997 (reprfunc)PyTclObject_str, /*tp_str*/
998 PyObject_GenericGetAttr,/*tp_getattro*/
999 0, /*tp_setattro*/
1000 0, /*tp_as_buffer*/
1001 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1002 0, /*tp_doc*/
1003 0, /*tp_traverse*/
1004 0, /*tp_clear*/
1005 0, /*tp_richcompare*/
1006 0, /*tp_weaklistoffset*/
1007 0, /*tp_iter*/
1008 0, /*tp_iternext*/
1009 PyTclObject_methods, /*tp_methods*/
1010 0, /*tp_members*/
1011 PyTclObject_getsetlist, /*tp_getset*/
1012 0, /*tp_base*/
1013 0, /*tp_dict*/
1014 0, /*tp_descr_get*/
1015 0, /*tp_descr_set*/
1016 0, /*tp_dictoffset*/
1017 0, /*tp_init*/
1018 0, /*tp_alloc*/
1019 0, /*tp_new*/
1020 0, /*tp_free*/
1021 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001022};
1023
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001024static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001025AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001026{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001027 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001029 if (PyString_Check(value))
1030 return Tcl_NewStringObj(PyString_AS_STRING(value),
1031 PyString_GET_SIZE(value));
1032 else if (PyBool_Check(value))
1033 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1034 else if (PyInt_Check(value))
1035 return Tcl_NewLongObj(PyInt_AS_LONG(value));
1036 else if (PyFloat_Check(value))
1037 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1038 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001039 Tcl_Obj **argv;
1040 Py_ssize_t size, i;
1041
1042 size = PyTuple_Size(value);
1043 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1044 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1045 return NULL;
1046 }
1047 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001048 if(!argv)
1049 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001050 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001051 argv[i] = AsObj(PyTuple_GetItem(value,i));
1052 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1053 ckfree(FREECAST argv);
1054 return result;
1055 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001056#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001057 else if (PyUnicode_Check(value)) {
1058 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1059 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1060 /* This #ifdef assumes that Tcl uses UCS-2.
1061 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001062#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001063 Tcl_UniChar *outbuf = NULL;
1064 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001065 size_t allocsize;
1066 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1067 PyErr_SetString(PyExc_OverflowError, "string is too long");
1068 return NULL;
1069 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001070 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1071 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001072 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001073 if (allocsize >= size)
1074 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1075 /* Else overflow occurred, and we take the next exit */
1076 if (!outbuf) {
1077 PyErr_NoMemory();
1078 return NULL;
1079 }
1080 for (i = 0; i < size; i++) {
1081 if (inbuf[i] >= 0x10000) {
1082 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001083 PyErr_Format(Tkinter_TclError,
1084 "character U+%x is above the range "
1085 "(U+0000-U+FFFF) allowed by Tcl",
1086 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001087 ckfree(FREECAST outbuf);
1088 return NULL;
1089 }
1090 outbuf[i] = inbuf[i];
1091 }
1092 result = Tcl_NewUnicodeObj(outbuf, size);
1093 ckfree(FREECAST outbuf);
1094 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001095#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001096 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001097#endif
1098
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001099 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001100#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001101 else if(PyTclObject_Check(value)) {
1102 Tcl_Obj *v = ((PyTclObject*)value)->value;
1103 Tcl_IncrRefCount(v);
1104 return v;
1105 }
1106 else {
1107 PyObject *v = PyObject_Str(value);
1108 if (!v)
1109 return 0;
1110 result = AsObj(v);
1111 Py_DECREF(v);
1112 return result;
1113 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001114}
1115
Martin v. Löwisffad6332002-11-26 09:28:05 +00001116static PyObject*
1117FromObj(PyObject* tkapp, Tcl_Obj *value)
1118{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001119 PyObject *result = NULL;
1120 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001121
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001122 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001123 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001124 return result;
1125 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001126
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001127 if (value->typePtr == app->BooleanType) {
1128 result = value->internalRep.longValue ? Py_True : Py_False;
1129 Py_INCREF(result);
1130 return result;
1131 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001132
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001133 if (value->typePtr == app->ByteArrayType) {
1134 int size;
1135 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1136 return PyString_FromStringAndSize(data, size);
1137 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001139 if (value->typePtr == app->DoubleType) {
1140 return PyFloat_FromDouble(value->internalRep.doubleValue);
1141 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001142
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001143 if (value->typePtr == app->IntType) {
1144 return PyInt_FromLong(value->internalRep.longValue);
1145 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001146
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001147 if (value->typePtr == app->ListType) {
1148 int size;
1149 int i, status;
1150 PyObject *elem;
1151 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001152
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001153 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1154 if (status == TCL_ERROR)
1155 return Tkinter_Error(tkapp);
1156 result = PyTuple_New(size);
1157 if (!result)
1158 return NULL;
1159 for (i = 0; i < size; i++) {
1160 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1161 value, i, &tcl_elem);
1162 if (status == TCL_ERROR) {
1163 Py_DECREF(result);
1164 return Tkinter_Error(tkapp);
1165 }
1166 elem = FromObj(tkapp, tcl_elem);
1167 if (!elem) {
1168 Py_DECREF(result);
1169 return NULL;
1170 }
1171 PyTuple_SetItem(result, i, elem);
1172 }
1173 return result;
1174 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001175
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001176 if (value->typePtr == app->ProcBodyType) {
1177 /* fall through: return tcl object. */
1178 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001179
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001180 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001181#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001182#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001183 PyObject *result;
1184 int size;
1185 Tcl_UniChar *input;
1186 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001187
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001188 size = Tcl_GetCharLength(value);
1189 result = PyUnicode_FromUnicode(NULL, size);
1190 if (!result)
1191 return NULL;
1192 input = Tcl_GetUnicode(value);
1193 output = PyUnicode_AS_UNICODE(result);
1194 while (size--)
1195 *output++ = *input++;
1196 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001197#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001198 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1199 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001200#endif
1201#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001202 int size;
1203 char *c;
1204 c = Tcl_GetStringFromObj(value, &size);
1205 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001206#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001207 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001208
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001209 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001210}
1211
Guilherme Polo1972d162009-03-27 21:43:08 +00001212#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001213/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214TCL_DECLARE_MUTEX(call_mutex)
1215
1216typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001217 Tcl_Event ev; /* Must be first */
1218 TkappObject *self;
1219 PyObject *args;
1220 int flags;
1221 PyObject **res;
1222 PyObject **exc_type, **exc_value, **exc_tb;
1223 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001225#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226
1227void
1228Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001229{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001230 int i;
1231 for (i = 0; i < objc; i++)
1232 Tcl_DecrRefCount(objv[i]);
1233 if (objv != objStore)
1234 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001235}
Guido van Rossum18468821994-06-20 07:49:28 +00001236
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001237/* Convert Python objects to Tcl objects. This must happen in the
1238 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001239
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240static Tcl_Obj**
1241Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1242{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001243 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001244 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001245 if (args == NULL)
1246 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001247
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001248 else if (!PyTuple_Check(args)) {
1249 objv[0] = AsObj(args);
1250 if (objv[0] == 0)
1251 goto finally;
1252 objc = 1;
1253 Tcl_IncrRefCount(objv[0]);
1254 }
1255 else {
1256 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001257
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001258 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001259 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1260 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1261 return NULL;
1262 }
1263 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001264 if (objv == NULL) {
1265 PyErr_NoMemory();
1266 objc = 0;
1267 goto finally;
1268 }
1269 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001270
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001271 for (i = 0; i < objc; i++) {
1272 PyObject *v = PyTuple_GetItem(args, i);
1273 if (v == Py_None) {
1274 objc = i;
1275 break;
1276 }
1277 objv[i] = AsObj(v);
1278 if (!objv[i]) {
1279 /* Reset objc, so it attempts to clear
1280 objects only up to i. */
1281 objc = i;
1282 goto finally;
1283 }
1284 Tcl_IncrRefCount(objv[i]);
1285 }
1286 }
1287 *pobjc = objc;
1288 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001289finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001290 Tkapp_CallDeallocArgs(objv, objStore, objc);
1291 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001292}
Guido van Rossum212643f1998-04-29 16:22:14 +00001293
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001295
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001296static PyObject*
1297Tkapp_CallResult(TkappObject *self)
1298{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001299 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001300 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001301 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 /* Not sure whether the IncrRef is necessary, but something
1303 may overwrite the interpreter result while we are
1304 converting it. */
1305 Tcl_IncrRefCount(value);
1306 res = FromObj((PyObject*)self, value);
1307 Tcl_DecrRefCount(value);
1308 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001309 int len;
1310 const char *s = Tcl_GetStringFromObj(value, &len);
1311 res = fromTclStringAndSize(s, len);
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{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001614 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001615 char **out = (char**)_out;
1616 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001617 if (PyString_Size(in) > INT_MAX) {
1618 PyErr_SetString(PyExc_OverflowError, "string is too long");
1619 return 0;
1620 }
1621 s = PyString_AsString(in);
1622 if (strlen(s) != PyString_Size(in)) {
1623 PyErr_SetString(PyExc_ValueError, "null character in string");
1624 return 0;
1625 }
1626 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001627 return 1;
1628 }
1629 if (PyTclObject_Check(in)) {
1630 *out = PyTclObject_TclString(in);
1631 return 1;
1632 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001633 PyErr_Format(PyExc_TypeError,
1634 "must be str or Tcl_Obj, not %.50s",
1635 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001636 return 0;
1637}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001638
Guilherme Polo1972d162009-03-27 21:43:08 +00001639#ifdef WITH_THREAD
1640
Martin v. Löwis111c1802008-06-13 07:47:47 +00001641static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001642var_perform(VarEvent *ev)
1643{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001644 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1645 if (!*(ev->res)) {
1646 PyObject *exc, *val, *tb;
1647 PyErr_Fetch(&exc, &val, &tb);
1648 PyErr_NormalizeException(&exc, &val, &tb);
1649 *(ev->exc_type) = exc;
1650 *(ev->exc_val) = val;
1651 Py_DECREF(tb);
1652 }
1653
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654}
1655
1656static int
1657var_proc(VarEvent* ev, int flags)
1658{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001659 ENTER_PYTHON
1660 var_perform(ev);
1661 Tcl_MutexLock(&var_mutex);
1662 Tcl_ConditionNotify(ev->cond);
1663 Tcl_MutexUnlock(&var_mutex);
1664 LEAVE_PYTHON
1665 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001666}
1667
Guilherme Polo1972d162009-03-27 21:43:08 +00001668#endif
1669
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001670static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001671var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001672{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001673#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001674 TkappObject *self = (TkappObject*)selfptr;
1675 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1676 TkappObject *self = (TkappObject*)selfptr;
1677 VarEvent *ev;
1678 PyObject *res, *exc_type, *exc_val;
1679 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001681 /* The current thread is not the interpreter thread. Marshal
1682 the call to the interpreter thread, then wait for
1683 completion. */
1684 if (!WaitForMainloop(self))
1685 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001686
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001687 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1688
1689 ev->self = selfptr;
1690 ev->args = args;
1691 ev->flags = flags;
1692 ev->func = func;
1693 ev->res = &res;
1694 ev->exc_type = &exc_type;
1695 ev->exc_val = &exc_val;
1696 ev->cond = &cond;
1697 ev->ev.proc = (Tcl_EventProc*)var_proc;
1698 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1699 Tcl_ConditionFinalize(&cond);
1700 if (!res) {
1701 PyErr_SetObject(exc_type, exc_val);
1702 Py_DECREF(exc_type);
1703 Py_DECREF(exc_val);
1704 return NULL;
1705 }
1706 return res;
1707 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001708#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001709 /* Tcl is not threaded, or this is the interpreter thread. */
1710 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001711}
1712
Guido van Rossum18468821994-06-20 07:49:28 +00001713static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001714SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001715{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001716 char *name1, *name2;
1717 PyObject *newValue;
1718 PyObject *res = NULL;
1719 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001720
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001721 switch (PyTuple_GET_SIZE(args)) {
1722 case 2:
1723 if (!PyArg_ParseTuple(args, "O&O:setvar",
1724 varname_converter, &name1, &newValue))
1725 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001726 /* XXX Acquire tcl lock??? */
1727 newval = AsObj(newValue);
1728 if (newval == NULL)
1729 return NULL;
1730 ENTER_TCL
1731 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1732 newval, flags);
1733 ENTER_OVERLAP
1734 if (!ok)
1735 Tkinter_Error(self);
1736 else {
1737 res = Py_None;
1738 Py_INCREF(res);
1739 }
1740 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001741 break;
1742 case 3:
1743 if (!PyArg_ParseTuple(args, "ssO:setvar",
1744 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001745 return NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001746 /* XXX must hold tcl lock already??? */
1747 newval = AsObj(newValue);
1748 ENTER_TCL
1749 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1750 ENTER_OVERLAP
1751 if (!ok)
1752 Tkinter_Error(self);
1753 else {
1754 res = Py_None;
1755 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001756 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001757 LEAVE_OVERLAP_TCL
1758 break;
1759 default:
1760 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1761 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001762 }
1763 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001764}
1765
1766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001767Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001768{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001769 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001775 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001776}
1777
Barry Warsawfa701a81997-01-16 00:15:11 +00001778
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001779
Guido van Rossum18468821994-06-20 07:49:28 +00001780static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001781GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001782{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001783 char *name1, *name2=NULL;
1784 PyObject *res = NULL;
1785 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001786
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001787 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1788 varname_converter, &name1, &name2))
1789 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001790
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 ENTER_TCL
1792 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1793 ENTER_OVERLAP
1794 if (tres == NULL) {
1795 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1796 } else {
1797 if (((TkappObject*)self)->wantobjects) {
1798 res = FromObj(self, tres);
1799 }
1800 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001801 int len;
1802 char *s = Tcl_GetStringFromObj(tres, &len);
1803 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001804 }
1805 }
1806 LEAVE_OVERLAP_TCL
1807 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001808}
1809
1810static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001811Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001812{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001813 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001819 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001820}
1821
Barry Warsawfa701a81997-01-16 00:15:11 +00001822
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001823
Guido van Rossum18468821994-06-20 07:49:28 +00001824static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001825UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001826{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001827 char *name1, *name2=NULL;
1828 int code;
1829 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001830
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001831 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1832 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001833
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001834 ENTER_TCL
1835 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1836 ENTER_OVERLAP
1837 if (code == TCL_ERROR)
1838 res = Tkinter_Error(self);
1839 else {
1840 Py_INCREF(Py_None);
1841 res = Py_None;
1842 }
1843 LEAVE_OVERLAP_TCL
1844 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001845}
1846
1847static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001848Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001849{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001850 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
1853static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001854Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001855{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001856 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001857}
1858
Barry Warsawfa701a81997-01-16 00:15:11 +00001859
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001860
Guido van Rossum18468821994-06-20 07:49:28 +00001861/** Tcl to Python **/
1862
1863static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001864Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001865{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001866 char *s;
1867 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 if (PyTuple_Size(args) == 1) {
1870 PyObject* o = PyTuple_GetItem(args, 0);
1871 if (PyInt_Check(o)) {
1872 Py_INCREF(o);
1873 return o;
1874 }
1875 }
1876 if (!PyArg_ParseTuple(args, "s:getint", &s))
1877 return NULL;
1878 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1879 return Tkinter_Error(self);
1880 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
1883static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001884Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001885{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001886 char *s;
1887 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001888
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001889 if (PyTuple_Size(args) == 1) {
1890 PyObject *o = PyTuple_GetItem(args, 0);
1891 if (PyFloat_Check(o)) {
1892 Py_INCREF(o);
1893 return o;
1894 }
1895 }
1896 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1897 return NULL;
1898 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1899 return Tkinter_Error(self);
1900 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001901}
1902
1903static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001904Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001905{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001906 char *s;
1907 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 if (PyTuple_Size(args) == 1) {
1910 PyObject *o = PyTuple_GetItem(args, 0);
1911 if (PyInt_Check(o)) {
1912 Py_INCREF(o);
1913 return o;
1914 }
1915 }
1916 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1917 return NULL;
1918 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1919 return Tkinter_Error(self);
1920 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001921}
1922
1923static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001924Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001925{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001926 char *s;
1927 PyObject *res = NULL;
1928 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001930 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1931 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001932
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001933 CHECK_TCL_APPARTMENT;
1934
1935 ENTER_TCL
1936 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1937 ENTER_OVERLAP
1938 if (retval == TCL_ERROR)
1939 res = Tkinter_Error(self);
1940 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001941 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001942 LEAVE_OVERLAP_TCL
1943 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001944}
1945
1946static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001947Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001948{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001949 char *s;
1950 PyObject *res = NULL;
1951 int retval;
1952 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001953
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001954 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1955 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001956
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001957 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001958
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001959 ENTER_TCL
1960 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1961 ENTER_OVERLAP
1962 if (retval == TCL_ERROR)
1963 res = Tkinter_Error(self);
1964 else
1965 res = Py_BuildValue("l", v);
1966 LEAVE_OVERLAP_TCL
1967 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001968}
1969
1970static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001971Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001972{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001973 char *s;
1974 PyObject *res = NULL;
1975 double v;
1976 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001977
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001978 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1979 return NULL;
1980 CHECK_TCL_APPARTMENT;
1981 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1982 ENTER_TCL
1983 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1984 ENTER_OVERLAP
1985 PyFPE_END_PROTECT(retval)
1986 if (retval == TCL_ERROR)
1987 res = Tkinter_Error(self);
1988 else
1989 res = Py_BuildValue("d", v);
1990 LEAVE_OVERLAP_TCL
1991 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001992}
1993
1994static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001995Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001996{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001997 char *s;
1998 PyObject *res = NULL;
1999 int retval;
2000 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002001
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002002 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2003 return NULL;
2004 CHECK_TCL_APPARTMENT;
2005 ENTER_TCL
2006 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2007 ENTER_OVERLAP
2008 if (retval == TCL_ERROR)
2009 res = Tkinter_Error(self);
2010 else
2011 res = Py_BuildValue("i", v);
2012 LEAVE_OVERLAP_TCL
2013 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002014}
2015
Barry Warsawfa701a81997-01-16 00:15:11 +00002016
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002017
Guido van Rossum18468821994-06-20 07:49:28 +00002018static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002019Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002020{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002021 char *list;
2022 int argc;
2023 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002024 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002025 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002027 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2028 return NULL;
2029 if (PyTclObject_Check(arg)) {
2030 int objc;
2031 Tcl_Obj **objv;
2032 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2033 ((PyTclObject*)arg)->value,
2034 &objc, &objv) == TCL_ERROR) {
2035 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002036 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002037 if (!(v = PyTuple_New(objc)))
2038 return NULL;
2039 for (i = 0; i < objc; i++) {
2040 PyObject *s = FromObj(self, objv[i]);
2041 if (!s || PyTuple_SetItem(v, i, s)) {
2042 Py_DECREF(v);
2043 return NULL;
2044 }
2045 }
2046 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002047 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002048 if (PyTuple_Check(arg)) {
2049 Py_INCREF(arg);
2050 return arg;
2051 }
2052
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002053 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2054 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002055
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002056 if (Tcl_SplitList(Tkapp_Interp(self), list,
2057 &argc, &argv) == TCL_ERROR) {
2058 PyMem_Free(list);
2059 return Tkinter_Error(self);
2060 }
Guido van Rossum18468821994-06-20 07:49:28 +00002061
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002062 if (!(v = PyTuple_New(argc)))
2063 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002064
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002065 for (i = 0; i < argc; i++) {
2066 PyObject *s = PyString_FromString(argv[i]);
2067 if (!s || PyTuple_SetItem(v, i, s)) {
2068 Py_DECREF(v);
2069 v = NULL;
2070 goto finally;
2071 }
2072 }
Guido van Rossum18468821994-06-20 07:49:28 +00002073
Barry Warsawfa701a81997-01-16 00:15:11 +00002074 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002075 ckfree(FREECAST argv);
2076 PyMem_Free(list);
2077 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002078}
2079
2080static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002081Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002082{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002083 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002084 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002085
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002086 if (!PyArg_ParseTuple(args, "O:split", &arg))
2087 return NULL;
2088 if (PyTclObject_Check(arg)) {
2089 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2090 int objc;
2091 Tcl_Obj **objv;
2092 int i;
2093 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2094 &objc, &objv) == TCL_ERROR) {
2095 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002096 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002097 if (objc == 0)
2098 return PyString_FromString("");
2099 if (objc == 1)
2100 return FromObj(self, objv[0]);
2101 if (!(v = PyTuple_New(objc)))
2102 return NULL;
2103 for (i = 0; i < objc; i++) {
2104 PyObject *s = FromObj(self, objv[i]);
2105 if (!s || PyTuple_SetItem(v, i, s)) {
2106 Py_DECREF(v);
2107 return NULL;
2108 }
2109 }
2110 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002112 if (PyTuple_Check(arg))
2113 return SplitObj(arg);
2114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002115 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2116 return NULL;
2117 v = Split(list);
2118 PyMem_Free(list);
2119 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002120}
2121
2122static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002123Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002124{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002125 char *s = Merge(args);
2126 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002127
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002128 if (s) {
2129 res = PyString_FromString(s);
2130 ckfree(s);
2131 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002132
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002133 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002134}
2135
Barry Warsawfa701a81997-01-16 00:15:11 +00002136
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002137
Guido van Rossum18468821994-06-20 07:49:28 +00002138/** Tcl Command **/
2139
Guido van Rossum00d93061998-05-28 23:06:38 +00002140/* Client data struct */
2141typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002142 PyObject *self;
2143 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002144} PythonCmd_ClientData;
2145
2146static int
Fred Drake509d79a2000-07-08 04:04:38 +00002147PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002148{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002149 errorInCmd = 1;
2150 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2151 LEAVE_PYTHON
2152 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002153}
2154
Guido van Rossum18468821994-06-20 07:49:28 +00002155/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002156 * function or method.
2157 */
Guido van Rossum18468821994-06-20 07:49:28 +00002158static int
Fred Drake509d79a2000-07-08 04:04:38 +00002159PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002160{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002161 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2162 PyObject *func, *arg, *res;
2163 int i, rv;
2164 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002165
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002166 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002167
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002168 /* TBD: no error checking here since we know, via the
2169 * Tkapp_CreateCommand() that the client data is a two-tuple
2170 */
2171 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002172
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002173 /* Create argument list (argv1, ..., argvN) */
2174 if (!(arg = PyTuple_New(argc - 1)))
2175 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002176
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002177 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002178 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002179 if (!s || PyTuple_SetItem(arg, i, s)) {
2180 Py_DECREF(arg);
2181 return PythonCmd_Error(interp);
2182 }
2183 }
2184 res = PyEval_CallObject(func, arg);
2185 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002186
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002187 if (res == NULL)
2188 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002189
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002190 obj_res = AsObj(res);
2191 if (obj_res == NULL) {
2192 Py_DECREF(res);
2193 return PythonCmd_Error(interp);
2194 }
2195 else {
2196 Tcl_SetObjResult(interp, obj_res);
2197 rv = TCL_OK;
2198 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002199
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002200 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002201
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002203
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002204 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002205}
2206
2207static void
Fred Drake509d79a2000-07-08 04:04:38 +00002208PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002209{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002210 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002211
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002212 ENTER_PYTHON
2213 Py_XDECREF(data->self);
2214 Py_XDECREF(data->func);
2215 PyMem_DEL(data);
2216 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002217}
2218
Barry Warsawfa701a81997-01-16 00:15:11 +00002219
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002220
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002221
Guilherme Polo1972d162009-03-27 21:43:08 +00002222#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002223TCL_DECLARE_MUTEX(command_mutex)
2224
2225typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002226 Tcl_Event ev;
2227 Tcl_Interp* interp;
2228 char *name;
2229 int create;
2230 int *status;
2231 ClientData *data;
2232 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002233} CommandEvent;
2234
2235static int
2236Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002237{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002238 if (ev->create)
2239 *ev->status = Tcl_CreateCommand(
2240 ev->interp, ev->name, PythonCmd,
2241 ev->data, PythonCmdDelete) == NULL;
2242 else
2243 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2244 Tcl_MutexLock(&command_mutex);
2245 Tcl_ConditionNotify(ev->done);
2246 Tcl_MutexUnlock(&command_mutex);
2247 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002248}
Guilherme Polo1972d162009-03-27 21:43:08 +00002249#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002250
2251static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002252Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002253{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002254 TkappObject *self = (TkappObject*)selfptr;
2255 PythonCmd_ClientData *data;
2256 char *cmdName;
2257 PyObject *func;
2258 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002259
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002260 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2261 return NULL;
2262 if (!PyCallable_Check(func)) {
2263 PyErr_SetString(PyExc_TypeError, "command not callable");
2264 return NULL;
2265 }
Guido van Rossum18468821994-06-20 07:49:28 +00002266
Martin v. Löwisa9656492003-03-30 08:44:58 +00002267#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002268 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2269 !WaitForMainloop(self))
2270 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002271#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002272
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002273 data = PyMem_NEW(PythonCmd_ClientData, 1);
2274 if (!data)
2275 return PyErr_NoMemory();
2276 Py_INCREF(self);
2277 Py_INCREF(func);
2278 data->self = selfptr;
2279 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002280
2281#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002282 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2283 Tcl_Condition cond = NULL;
2284 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2285 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2286 ev->interp = self->interp;
2287 ev->create = 1;
2288 ev->name = cmdName;
2289 ev->data = (ClientData)data;
2290 ev->status = &err;
2291 ev->done = &cond;
2292 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2293 Tcl_ConditionFinalize(&cond);
2294 }
2295 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002296#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002297 {
2298 ENTER_TCL
2299 err = Tcl_CreateCommand(
2300 Tkapp_Interp(self), cmdName, PythonCmd,
2301 (ClientData)data, PythonCmdDelete) == NULL;
2302 LEAVE_TCL
2303 }
2304 if (err) {
2305 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2306 PyMem_DEL(data);
2307 return NULL;
2308 }
Guido van Rossum18468821994-06-20 07:49:28 +00002309
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002310 Py_INCREF(Py_None);
2311 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002312}
2313
Barry Warsawfa701a81997-01-16 00:15:11 +00002314
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002315
Guido van Rossum18468821994-06-20 07:49:28 +00002316static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002317Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002318{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002319 TkappObject *self = (TkappObject*)selfptr;
2320 char *cmdName;
2321 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002322
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002323 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2324 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002325
2326#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002327 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2328 Tcl_Condition cond = NULL;
2329 CommandEvent *ev;
2330 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2331 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2332 ev->interp = self->interp;
2333 ev->create = 0;
2334 ev->name = cmdName;
2335 ev->status = &err;
2336 ev->done = &cond;
2337 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2338 &command_mutex);
2339 Tcl_ConditionFinalize(&cond);
2340 }
2341 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002342#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002343 {
2344 ENTER_TCL
2345 err = Tcl_DeleteCommand(self->interp, cmdName);
2346 LEAVE_TCL
2347 }
2348 if (err == -1) {
2349 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2350 return NULL;
2351 }
2352 Py_INCREF(Py_None);
2353 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002354}
2355
Barry Warsawfa701a81997-01-16 00:15:11 +00002356
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002357
Guido van Rossum00d93061998-05-28 23:06:38 +00002358#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002359/** File Handler **/
2360
Guido van Rossum00d93061998-05-28 23:06:38 +00002361typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002362 PyObject *func;
2363 PyObject *file;
2364 int id;
2365 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002366} FileHandler_ClientData;
2367
2368static FileHandler_ClientData *HeadFHCD;
2369
2370static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002371NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002372{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002373 FileHandler_ClientData *p;
2374 p = PyMem_NEW(FileHandler_ClientData, 1);
2375 if (p != NULL) {
2376 Py_XINCREF(func);
2377 Py_XINCREF(file);
2378 p->func = func;
2379 p->file = file;
2380 p->id = id;
2381 p->next = HeadFHCD;
2382 HeadFHCD = p;
2383 }
2384 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002385}
2386
2387static void
Fred Drake509d79a2000-07-08 04:04:38 +00002388DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002389{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002390 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002391
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002392 pp = &HeadFHCD;
2393 while ((p = *pp) != NULL) {
2394 if (p->id == id) {
2395 *pp = p->next;
2396 Py_XDECREF(p->func);
2397 Py_XDECREF(p->file);
2398 PyMem_DEL(p);
2399 }
2400 else
2401 pp = &p->next;
2402 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002403}
2404
Guido van Rossuma597dde1995-01-10 20:56:29 +00002405static void
Fred Drake509d79a2000-07-08 04:04:38 +00002406FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002407{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002408 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2409 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002410
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002411 ENTER_PYTHON
2412 func = data->func;
2413 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002414
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002415 arg = Py_BuildValue("(Oi)", file, (long) mask);
2416 res = PyEval_CallObject(func, arg);
2417 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002418
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002419 if (res == NULL) {
2420 errorInCmd = 1;
2421 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2422 }
2423 Py_XDECREF(res);
2424 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002425}
2426
Guido van Rossum18468821994-06-20 07:49:28 +00002427static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002428Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2429 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002430{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002431 FileHandler_ClientData *data;
2432 PyObject *file, *func;
2433 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002434
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002435 if (!self && Py_Py3kWarningFlag) {
2436 if (PyErr_Warn(PyExc_DeprecationWarning,
2437 "_tkinter.createfilehandler is gone in 3.x") < 0)
2438 return NULL;
2439 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002441 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2442 &file, &mask, &func))
2443 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002444
Martin v. Löwisa9656492003-03-30 08:44:58 +00002445#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002446 if (!self && !tcl_lock) {
2447 /* We don't have the Tcl lock since Tcl is threaded. */
2448 PyErr_SetString(PyExc_RuntimeError,
2449 "_tkinter.createfilehandler not supported "
2450 "for threaded Tcl");
2451 return NULL;
2452 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002453#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002454
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002455 if (self) {
2456 CHECK_TCL_APPARTMENT;
2457 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002458
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002459 tfile = PyObject_AsFileDescriptor(file);
2460 if (tfile < 0)
2461 return NULL;
2462 if (!PyCallable_Check(func)) {
2463 PyErr_SetString(PyExc_TypeError, "bad argument list");
2464 return NULL;
2465 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002466
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002467 data = NewFHCD(func, file, tfile);
2468 if (data == NULL)
2469 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002471 /* Ought to check for null Tcl_File object... */
2472 ENTER_TCL
2473 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2474 LEAVE_TCL
2475 Py_INCREF(Py_None);
2476 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002477}
2478
2479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002480Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002481{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002482 PyObject *file;
2483 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002484
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002485 if (!self && Py_Py3kWarningFlag) {
2486 if (PyErr_Warn(PyExc_DeprecationWarning,
2487 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2488 return NULL;
2489 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002491 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2492 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002493
Martin v. Löwisa9656492003-03-30 08:44:58 +00002494#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002495 if (!self && !tcl_lock) {
2496 /* We don't have the Tcl lock since Tcl is threaded. */
2497 PyErr_SetString(PyExc_RuntimeError,
2498 "_tkinter.deletefilehandler not supported "
2499 "for threaded Tcl");
2500 return NULL;
2501 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002502#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002503
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002504 if (self) {
2505 CHECK_TCL_APPARTMENT;
2506 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002507
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002508 tfile = PyObject_AsFileDescriptor(file);
2509 if (tfile < 0)
2510 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002513
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002514 /* Ought to check for null Tcl_File object... */
2515 ENTER_TCL
2516 Tcl_DeleteFileHandler(tfile);
2517 LEAVE_TCL
2518 Py_INCREF(Py_None);
2519 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002520}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002521#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002522
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002524/**** Tktt Object (timer token) ****/
2525
Jeremy Hylton938ace62002-07-17 16:30:39 +00002526static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002527
Guido van Rossum00d93061998-05-28 23:06:38 +00002528typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002529 PyObject_HEAD
2530 Tcl_TimerToken token;
2531 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002532} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002533
2534static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002535Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002536{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002537 TkttObject *v = (TkttObject *)self;
2538 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002539
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002540 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2541 return NULL;
2542 if (v->token != NULL) {
2543 Tcl_DeleteTimerHandler(v->token);
2544 v->token = NULL;
2545 }
2546 if (func != NULL) {
2547 v->func = NULL;
2548 Py_DECREF(func);
2549 Py_DECREF(v); /* See Tktt_New() */
2550 }
2551 Py_INCREF(Py_None);
2552 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002553}
2554
2555static PyMethodDef Tktt_methods[] =
2556{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002557 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2558 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002559};
2560
2561static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002562Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002563{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002564 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002565
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002566 v = PyObject_New(TkttObject, &Tktt_Type);
2567 if (v == NULL)
2568 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002569
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002570 Py_INCREF(func);
2571 v->token = NULL;
2572 v->func = func;
2573
2574 /* Extra reference, deleted when called or when handler is deleted */
2575 Py_INCREF(v);
2576 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002577}
2578
2579static void
Fred Drake509d79a2000-07-08 04:04:38 +00002580Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002581{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002582 TkttObject *v = (TkttObject *)self;
2583 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002585 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002586
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002587 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002588}
2589
Guido van Rossum597ac201998-05-12 14:36:19 +00002590static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002591Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002592{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002593 TkttObject *v = (TkttObject *)self;
2594 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002596 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2597 v->func == NULL ? ", handler deleted" : "");
2598 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002599}
2600
2601static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002602Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002603{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002604 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002605}
2606
2607static PyTypeObject Tktt_Type =
2608{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002609 PyVarObject_HEAD_INIT(NULL, 0)
2610 "tktimertoken", /*tp_name */
2611 sizeof(TkttObject), /*tp_basicsize */
2612 0, /*tp_itemsize */
2613 Tktt_Dealloc, /*tp_dealloc */
2614 0, /*tp_print */
2615 Tktt_GetAttr, /*tp_getattr */
2616 0, /*tp_setattr */
2617 0, /*tp_compare */
2618 Tktt_Repr, /*tp_repr */
2619 0, /*tp_as_number */
2620 0, /*tp_as_sequence */
2621 0, /*tp_as_mapping */
2622 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002623};
2624
Barry Warsawfa701a81997-01-16 00:15:11 +00002625
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002626
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002627/** Timer Handler **/
2628
2629static void
Fred Drake509d79a2000-07-08 04:04:38 +00002630TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002631{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002632 TkttObject *v = (TkttObject *)clientData;
2633 PyObject *func = v->func;
2634 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002635
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002636 if (func == NULL)
2637 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002638
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002639 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002640
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002641 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002642
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002643 res = PyEval_CallObject(func, NULL);
2644 Py_DECREF(func);
2645 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002646
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002647 if (res == NULL) {
2648 errorInCmd = 1;
2649 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2650 }
2651 else
2652 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002653
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002654 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002655}
2656
2657static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002658Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002659{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002660 int milliseconds;
2661 PyObject *func;
2662 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002663
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002664 if (!self && Py_Py3kWarningFlag) {
2665 if (PyErr_Warn(PyExc_DeprecationWarning,
2666 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2667 return NULL;
2668 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002669
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002670 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2671 &milliseconds, &func))
2672 return NULL;
2673 if (!PyCallable_Check(func)) {
2674 PyErr_SetString(PyExc_TypeError, "bad argument list");
2675 return NULL;
2676 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002677
Martin v. Löwisa9656492003-03-30 08:44:58 +00002678#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002679 if (!self && !tcl_lock) {
2680 /* We don't have the Tcl lock since Tcl is threaded. */
2681 PyErr_SetString(PyExc_RuntimeError,
2682 "_tkinter.createtimerhandler not supported "
2683 "for threaded Tcl");
2684 return NULL;
2685 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002686#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002687
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002688 if (self) {
2689 CHECK_TCL_APPARTMENT;
2690 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002691
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002692 v = Tktt_New(func);
2693 if (v) {
2694 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2695 (ClientData)v);
2696 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002697
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002698 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002699}
2700
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002701
Guido van Rossum18468821994-06-20 07:49:28 +00002702/** Event Loop **/
2703
Guido van Rossum18468821994-06-20 07:49:28 +00002704static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002705Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002706{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002707 int threshold = 0;
2708 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002709#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002710 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002711#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002712
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002713 if (!self && Py_Py3kWarningFlag) {
2714 if (PyErr_Warn(PyExc_DeprecationWarning,
2715 "_tkinter.mainloop is gone in 3.x") < 0)
2716 return NULL;
2717 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002718
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002719 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2720 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002721
Martin v. Löwisa9656492003-03-30 08:44:58 +00002722#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002723 if (!self && !tcl_lock) {
2724 /* We don't have the Tcl lock since Tcl is threaded. */
2725 PyErr_SetString(PyExc_RuntimeError,
2726 "_tkinter.mainloop not supported "
2727 "for threaded Tcl");
2728 return NULL;
2729 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002730#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002731
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002732 if (self) {
2733 CHECK_TCL_APPARTMENT;
2734 self->dispatching = 1;
2735 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002736
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002737 quitMainLoop = 0;
2738 while (Tk_GetNumMainWindows() > threshold &&
2739 !quitMainLoop &&
2740 !errorInCmd)
2741 {
2742 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002743
2744#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002745 if (self && self->threaded) {
2746 /* Allow other Python threads to run. */
2747 ENTER_TCL
2748 result = Tcl_DoOneEvent(0);
2749 LEAVE_TCL
2750 }
2751 else {
2752 Py_BEGIN_ALLOW_THREADS
2753 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2754 tcl_tstate = tstate;
2755 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2756 tcl_tstate = NULL;
2757 if(tcl_lock)PyThread_release_lock(tcl_lock);
2758 if (result == 0)
2759 Sleep(Tkinter_busywaitinterval);
2760 Py_END_ALLOW_THREADS
2761 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002762#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002763 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002764#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002765
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002766 if (PyErr_CheckSignals() != 0) {
2767 if (self)
2768 self->dispatching = 0;
2769 return NULL;
2770 }
2771 if (result < 0)
2772 break;
2773 }
2774 if (self)
2775 self->dispatching = 0;
2776 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002777
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002778 if (errorInCmd) {
2779 errorInCmd = 0;
2780 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2781 excInCmd = valInCmd = trbInCmd = NULL;
2782 return NULL;
2783 }
2784 Py_INCREF(Py_None);
2785 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002786}
2787
2788static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002789Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002790{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002791 int flags = 0;
2792 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002793
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002794 if (!self && Py_Py3kWarningFlag) {
2795 if (PyErr_Warn(PyExc_DeprecationWarning,
2796 "_tkinter.dooneevent is gone in 3.x") < 0)
2797 return NULL;
2798 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002799
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002800 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2801 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002802
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002803 ENTER_TCL
2804 rv = Tcl_DoOneEvent(flags);
2805 LEAVE_TCL
2806 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002807}
2808
2809static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002810Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002811{
2812
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002813 if (!self && Py_Py3kWarningFlag) {
2814 if (PyErr_Warn(PyExc_DeprecationWarning,
2815 "_tkinter.quit is gone in 3.x") < 0)
2816 return NULL;
2817 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002818
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002819 if (!PyArg_ParseTuple(args, ":quit"))
2820 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002821
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002822 quitMainLoop = 1;
2823 Py_INCREF(Py_None);
2824 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002825}
2826
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002827static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002828Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002829{
2830
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002831 if (!PyArg_ParseTuple(args, ":interpaddr"))
2832 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002833
Victor Stinner930c3c92013-09-05 00:26:15 +02002834 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002835}
2836
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002837static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002838Tkapp_TkInit(PyObject *self, PyObject *args)
2839{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002840 Tcl_Interp *interp = Tkapp_Interp(self);
2841 const char * _tk_exists = NULL;
2842 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002843
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002844#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002845 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2846 * first call failed.
2847 * To avoid the deadlock, we just refuse the second call through
2848 * a static variable.
2849 */
2850 if (tk_load_failed) {
2851 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2852 return NULL;
2853 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002854#endif
2855
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002856 /* We want to guard against calling Tk_Init() multiple times */
2857 CHECK_TCL_APPARTMENT;
2858 ENTER_TCL
2859 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2860 ENTER_OVERLAP
2861 if (err == TCL_ERROR) {
2862 /* This sets an exception, but we cannot return right
2863 away because we need to exit the overlap first. */
2864 Tkinter_Error(self);
2865 } else {
2866 _tk_exists = Tkapp_Result(self);
2867 }
2868 LEAVE_OVERLAP_TCL
2869 if (err == TCL_ERROR) {
2870 return NULL;
2871 }
2872 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2873 if (Tk_Init(interp) == TCL_ERROR) {
2874 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002875#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002876 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002877#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002878 return NULL;
2879 }
2880 }
2881 Py_INCREF(Py_None);
2882 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002883}
Barry Warsawfa701a81997-01-16 00:15:11 +00002884
Martin v. Löwisffad6332002-11-26 09:28:05 +00002885static PyObject *
2886Tkapp_WantObjects(PyObject *self, PyObject *args)
2887{
2888
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002889 int wantobjects = -1;
2890 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2891 return NULL;
2892 if (wantobjects == -1)
2893 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2894 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002895
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002896 Py_INCREF(Py_None);
2897 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002898}
2899
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002900static PyObject *
2901Tkapp_WillDispatch(PyObject *self, PyObject *args)
2902{
2903
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002904 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002905
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002906 Py_INCREF(Py_None);
2907 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002908}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002909
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002910
Guido van Rossum18468821994-06-20 07:49:28 +00002911/**** Tkapp Method List ****/
2912
2913static PyMethodDef Tkapp_methods[] =
2914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002915 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2916 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2917 {"call", Tkapp_Call, METH_VARARGS},
2918 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2919 {"eval", Tkapp_Eval, METH_VARARGS},
2920 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2921 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2922 {"record", Tkapp_Record, METH_VARARGS},
2923 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2924 {"setvar", Tkapp_SetVar, METH_VARARGS},
2925 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2926 {"getvar", Tkapp_GetVar, METH_VARARGS},
2927 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2928 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2929 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2930 {"getint", Tkapp_GetInt, METH_VARARGS},
2931 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2932 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2933 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2934 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2935 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2936 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2937 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2938 {"split", Tkapp_Split, METH_VARARGS},
2939 {"merge", Tkapp_Merge, METH_VARARGS},
2940 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2941 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002942#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002943 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2944 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002945#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002946 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2947 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2948 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2949 {"quit", Tkapp_Quit, METH_VARARGS},
2950 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2951 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2952 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002953};
2954
Barry Warsawfa701a81997-01-16 00:15:11 +00002955
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002956
Guido van Rossum18468821994-06-20 07:49:28 +00002957/**** Tkapp Type Methods ****/
2958
2959static void
Fred Drake509d79a2000-07-08 04:04:38 +00002960Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002961{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002962 /*CHECK_TCL_APPARTMENT;*/
2963 ENTER_TCL
2964 Tcl_DeleteInterp(Tkapp_Interp(self));
2965 LEAVE_TCL
2966 PyObject_Del(self);
2967 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002968}
2969
2970static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002971Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002972{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002973 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002974}
2975
2976static PyTypeObject Tkapp_Type =
2977{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002978 PyVarObject_HEAD_INIT(NULL, 0)
2979 "tkapp", /*tp_name */
2980 sizeof(TkappObject), /*tp_basicsize */
2981 0, /*tp_itemsize */
2982 Tkapp_Dealloc, /*tp_dealloc */
2983 0, /*tp_print */
2984 Tkapp_GetAttr, /*tp_getattr */
2985 0, /*tp_setattr */
2986 0, /*tp_compare */
2987 0, /*tp_repr */
2988 0, /*tp_as_number */
2989 0, /*tp_as_sequence */
2990 0, /*tp_as_mapping */
2991 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002992};
2993
Barry Warsawfa701a81997-01-16 00:15:11 +00002994
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002995
Guido van Rossum18468821994-06-20 07:49:28 +00002996/**** Tkinter Module ****/
2997
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002998typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002999 PyObject* tuple;
3000 int size; /* current size */
3001 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003002} FlattenContext;
3003
3004static int
3005_bump(FlattenContext* context, int size)
3006{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003007 /* expand tuple to hold (at least) size new items.
3008 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003009
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003010 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003011
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003012 if (maxsize < context->size + size)
3013 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003014
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003015 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003016
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003017 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003018}
3019
3020static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003021_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003022{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003023 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003024
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003025 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003027 if (depth > 1000) {
3028 PyErr_SetString(PyExc_ValueError,
3029 "nesting too deep in _flatten");
3030 return 0;
3031 } else if (PyList_Check(item)) {
3032 size = PyList_GET_SIZE(item);
3033 /* preallocate (assume no nesting) */
3034 if (context->size + size > context->maxsize &&
3035 !_bump(context, size))
3036 return 0;
3037 /* copy items to output tuple */
3038 for (i = 0; i < size; i++) {
3039 PyObject *o = PyList_GET_ITEM(item, i);
3040 if (PyList_Check(o) || PyTuple_Check(o)) {
3041 if (!_flatten1(context, o, depth + 1))
3042 return 0;
3043 } else if (o != Py_None) {
3044 if (context->size + 1 > context->maxsize &&
3045 !_bump(context, 1))
3046 return 0;
3047 Py_INCREF(o);
3048 PyTuple_SET_ITEM(context->tuple,
3049 context->size++, o);
3050 }
3051 }
3052 } else if (PyTuple_Check(item)) {
3053 /* same, for tuples */
3054 size = PyTuple_GET_SIZE(item);
3055 if (context->size + size > context->maxsize &&
3056 !_bump(context, size))
3057 return 0;
3058 for (i = 0; i < size; i++) {
3059 PyObject *o = PyTuple_GET_ITEM(item, i);
3060 if (PyList_Check(o) || PyTuple_Check(o)) {
3061 if (!_flatten1(context, o, depth + 1))
3062 return 0;
3063 } else if (o != Py_None) {
3064 if (context->size + 1 > context->maxsize &&
3065 !_bump(context, 1))
3066 return 0;
3067 Py_INCREF(o);
3068 PyTuple_SET_ITEM(context->tuple,
3069 context->size++, o);
3070 }
3071 }
3072 } else {
3073 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3074 return 0;
3075 }
3076 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003077}
3078
3079static PyObject *
3080Tkinter_Flatten(PyObject* self, PyObject* args)
3081{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003082 FlattenContext context;
3083 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003084
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003085 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3086 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003087
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003088 context.maxsize = PySequence_Size(item);
3089 if (context.maxsize < 0)
3090 return NULL;
3091 if (context.maxsize == 0)
3092 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003094 context.tuple = PyTuple_New(context.maxsize);
3095 if (!context.tuple)
3096 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003097
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003098 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003099
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003100 if (!_flatten1(&context, item,0))
3101 return NULL;
3102
3103 if (_PyTuple_Resize(&context.tuple, context.size))
3104 return NULL;
3105
3106 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003107}
3108
Guido van Rossum18468821994-06-20 07:49:28 +00003109static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003110Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003111{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003112 char *screenName = NULL;
3113 char *baseName = NULL;
3114 char *className = NULL;
3115 int interactive = 0;
3116 int wantobjects = 0;
3117 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3118 int sync = 0; /* pass -sync to wish */
3119 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003120
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003121 baseName = strrchr(Py_GetProgramName(), '/');
3122 if (baseName != NULL)
3123 baseName++;
3124 else
3125 baseName = Py_GetProgramName();
3126 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003127
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003128 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3129 &screenName, &baseName, &className,
3130 &interactive, &wantobjects, &wantTk,
3131 &sync, &use))
3132 return NULL;
3133
3134 return (PyObject *) Tkapp_New(screenName, baseName, className,
3135 interactive, wantobjects, wantTk,
3136 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003137}
3138
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003139static PyObject *
3140Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3141{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003142 int new_val;
3143 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3144 return NULL;
3145 if (new_val < 0) {
3146 PyErr_SetString(PyExc_ValueError,
3147 "busywaitinterval must be >= 0");
3148 return NULL;
3149 }
3150 Tkinter_busywaitinterval = new_val;
3151 Py_INCREF(Py_None);
3152 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003153}
3154
3155static char setbusywaitinterval_doc[] =
3156"setbusywaitinterval(n) -> None\n\
3157\n\
3158Set the busy-wait interval in milliseconds between successive\n\
3159calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3160It should be set to a divisor of the maximum time between\n\
3161frames in an animation.";
3162
3163static PyObject *
3164Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3165{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003166 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003167}
3168
3169static char getbusywaitinterval_doc[] =
3170"getbusywaitinterval() -> int\n\
3171\n\
3172Return the current busy-wait interval between successive\n\
3173calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3174
Guido van Rossum18468821994-06-20 07:49:28 +00003175static PyMethodDef moduleMethods[] =
3176{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003177 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3178 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003179#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003180 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3181 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003182#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003183 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3184 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3185 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3186 {"quit", Tkapp_Quit, METH_VARARGS},
3187 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3188 setbusywaitinterval_doc},
3189 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3190 METH_NOARGS, getbusywaitinterval_doc},
3191 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003192};
3193
Guido van Rossum7bf15641998-05-22 18:28:17 +00003194#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003195
3196static int stdin_ready = 0;
3197
Guido van Rossumad4db171998-06-13 13:56:28 +00003198#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003199static void
Fred Drake509d79a2000-07-08 04:04:38 +00003200MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003201{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003202 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003203}
Guido van Rossumad4db171998-06-13 13:56:28 +00003204#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003205
Martin v. Löwisa9656492003-03-30 08:44:58 +00003206#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003207static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003208#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003209
Guido van Rossum18468821994-06-20 07:49:28 +00003210static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003211EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003212{
Guido van Rossumad4db171998-06-13 13:56:28 +00003213#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003214 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003215#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003216#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003218#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003219 stdin_ready = 0;
3220 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003221#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003222 tfile = fileno(stdin);
3223 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003224#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003225 while (!errorInCmd && !stdin_ready) {
3226 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003227#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003228 if (_kbhit()) {
3229 stdin_ready = 1;
3230 break;
3231 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003232#endif
3233#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003234 Py_BEGIN_ALLOW_THREADS
3235 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3236 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003237
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003238 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003239
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003240 tcl_tstate = NULL;
3241 if(tcl_lock)PyThread_release_lock(tcl_lock);
3242 if (result == 0)
3243 Sleep(Tkinter_busywaitinterval);
3244 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003245#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003246 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003247#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003248
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003249 if (result < 0)
3250 break;
3251 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003252#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003253 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003254#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003255 if (errorInCmd) {
3256 errorInCmd = 0;
3257 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3258 excInCmd = valInCmd = trbInCmd = NULL;
3259 PyErr_Print();
3260 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003261#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003262 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003263#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003265}
Guido van Rossum18468821994-06-20 07:49:28 +00003266
Guido van Rossum00d93061998-05-28 23:06:38 +00003267#endif
3268
Guido van Rossum7bf15641998-05-22 18:28:17 +00003269static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003270EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003271{
Guido van Rossum00d93061998-05-28 23:06:38 +00003272#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003273 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003274#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003275 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003276#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003277 PyOS_InputHook = EventHook;
3278 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003279#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003280}
3281
3282static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003283DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003284{
Guido van Rossum00d93061998-05-28 23:06:38 +00003285#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003286 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3287 PyOS_InputHook = NULL;
3288 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003289#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003290}
3291
Barry Warsawfa701a81997-01-16 00:15:11 +00003292
3293/* all errors will be checked in one fell swoop in init_tkinter() */
3294static void
Fred Drake509d79a2000-07-08 04:04:38 +00003295ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003296{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003297 PyObject *v = PyInt_FromLong(val);
3298 if (v) {
3299 PyDict_SetItemString(d, name, v);
3300 Py_DECREF(v);
3301 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003302}
3303static void
Fred Drake509d79a2000-07-08 04:04:38 +00003304ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003305{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003306 PyObject *v = PyString_FromString(val);
3307 if (v) {
3308 PyDict_SetItemString(d, name, v);
3309 Py_DECREF(v);
3310 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003311}
3312
3313
Mark Hammond62b1ab12002-07-23 06:31:15 +00003314PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003315init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003316{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003317 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003318
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003319 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003320
3321#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003322 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003323#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003324
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003325 m = Py_InitModule("_tkinter", moduleMethods);
3326 if (m == NULL)
3327 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003328
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003329 d = PyModule_GetDict(m);
3330 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3331 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 ins_long(d, "READABLE", TCL_READABLE);
3334 ins_long(d, "WRITABLE", TCL_WRITABLE);
3335 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3336 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3337 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3338 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3339 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3340 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3341 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3342 ins_string(d, "TK_VERSION", TK_VERSION);
3343 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003344
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003345 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003346
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003347 Py_TYPE(&Tktt_Type) = &PyType_Type;
3348 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003349
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003350 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3351 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003352
3353#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003354 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3355 * start waking up. Note that Tcl_FindExecutable will do this, this
3356 * code must be above it! The original warning from
3357 * tkMacOSXAppInit.c is copied below.
3358 *
3359 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3360 * Tcl interpreter for now. It probably should work to do this
3361 * in the other order, but for now it doesn't seem to.
3362 *
3363 */
3364 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003365#endif
3366
3367
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003368 /* This helps the dynamic loader; in Unicode aware Tcl versions
3369 it also helps Tcl find its encodings. */
3370 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003371
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003372 if (PyErr_Occurred())
3373 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003374
Guido van Rossum43ff8681998-07-14 18:02:13 +00003375#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003376 /* This was not a good idea; through <Destroy> bindings,
3377 Tcl_Finalize() may invoke Python code but at that point the
3378 interpreter and thread state have already been destroyed! */
3379 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003380#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003381
Guido van Rossum18468821994-06-20 07:49:28 +00003382}