blob: 808d48188932d93f82719d5ba6acbfceadb5bedc [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
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001024#if PY_SIZE_MAX > INT_MAX
1025#define CHECK_STRING_LENGTH(s) do { \
1026 if (s != NULL && strlen(s) >= INT_MAX) { \
1027 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1028 return NULL; \
1029 } } while(0)
1030#else
1031#define CHECK_STRING_LENGTH(s)
1032#endif
1033
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001034static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001035AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001036{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001037 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001038
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001039 if (PyString_Check(value))
1040 return Tcl_NewStringObj(PyString_AS_STRING(value),
1041 PyString_GET_SIZE(value));
1042 else if (PyBool_Check(value))
1043 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1044 else if (PyInt_Check(value))
1045 return Tcl_NewLongObj(PyInt_AS_LONG(value));
1046 else if (PyFloat_Check(value))
1047 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1048 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001049 Tcl_Obj **argv;
1050 Py_ssize_t size, i;
1051
1052 size = PyTuple_Size(value);
1053 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1054 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1055 return NULL;
1056 }
1057 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001058 if(!argv)
1059 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001060 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001061 argv[i] = AsObj(PyTuple_GetItem(value,i));
1062 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1063 ckfree(FREECAST argv);
1064 return result;
1065 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001066#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001067 else if (PyUnicode_Check(value)) {
1068 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1069 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1070 /* This #ifdef assumes that Tcl uses UCS-2.
1071 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001072#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001073 Tcl_UniChar *outbuf = NULL;
1074 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001075 size_t allocsize;
1076 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1077 PyErr_SetString(PyExc_OverflowError, "string is too long");
1078 return NULL;
1079 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001080 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1081 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001082 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001083 if (allocsize >= size)
1084 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1085 /* Else overflow occurred, and we take the next exit */
1086 if (!outbuf) {
1087 PyErr_NoMemory();
1088 return NULL;
1089 }
1090 for (i = 0; i < size; i++) {
1091 if (inbuf[i] >= 0x10000) {
1092 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001093 PyErr_Format(Tkinter_TclError,
1094 "character U+%x is above the range "
1095 "(U+0000-U+FFFF) allowed by Tcl",
1096 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001097 ckfree(FREECAST outbuf);
1098 return NULL;
1099 }
1100 outbuf[i] = inbuf[i];
1101 }
1102 result = Tcl_NewUnicodeObj(outbuf, size);
1103 ckfree(FREECAST outbuf);
1104 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001105#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001106 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001107#endif
1108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001109 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001110#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001111 else if(PyTclObject_Check(value)) {
1112 Tcl_Obj *v = ((PyTclObject*)value)->value;
1113 Tcl_IncrRefCount(v);
1114 return v;
1115 }
1116 else {
1117 PyObject *v = PyObject_Str(value);
1118 if (!v)
1119 return 0;
1120 result = AsObj(v);
1121 Py_DECREF(v);
1122 return result;
1123 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001124}
1125
Martin v. Löwisffad6332002-11-26 09:28:05 +00001126static PyObject*
1127FromObj(PyObject* tkapp, Tcl_Obj *value)
1128{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001129 PyObject *result = NULL;
1130 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001131
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001132 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001133 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001134 return result;
1135 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001136
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001137 if (value->typePtr == app->BooleanType) {
1138 result = value->internalRep.longValue ? Py_True : Py_False;
1139 Py_INCREF(result);
1140 return result;
1141 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001142
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001143 if (value->typePtr == app->ByteArrayType) {
1144 int size;
1145 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1146 return PyString_FromStringAndSize(data, size);
1147 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001148
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001149 if (value->typePtr == app->DoubleType) {
1150 return PyFloat_FromDouble(value->internalRep.doubleValue);
1151 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001152
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001153 if (value->typePtr == app->IntType) {
1154 return PyInt_FromLong(value->internalRep.longValue);
1155 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001156
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001157 if (value->typePtr == app->ListType) {
1158 int size;
1159 int i, status;
1160 PyObject *elem;
1161 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001162
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001163 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1164 if (status == TCL_ERROR)
1165 return Tkinter_Error(tkapp);
1166 result = PyTuple_New(size);
1167 if (!result)
1168 return NULL;
1169 for (i = 0; i < size; i++) {
1170 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1171 value, i, &tcl_elem);
1172 if (status == TCL_ERROR) {
1173 Py_DECREF(result);
1174 return Tkinter_Error(tkapp);
1175 }
1176 elem = FromObj(tkapp, tcl_elem);
1177 if (!elem) {
1178 Py_DECREF(result);
1179 return NULL;
1180 }
1181 PyTuple_SetItem(result, i, elem);
1182 }
1183 return result;
1184 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001185
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001186 if (value->typePtr == app->ProcBodyType) {
1187 /* fall through: return tcl object. */
1188 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001189
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001190 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001191#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001192#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001193 PyObject *result;
1194 int size;
1195 Tcl_UniChar *input;
1196 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001197
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001198 size = Tcl_GetCharLength(value);
1199 result = PyUnicode_FromUnicode(NULL, size);
1200 if (!result)
1201 return NULL;
1202 input = Tcl_GetUnicode(value);
1203 output = PyUnicode_AS_UNICODE(result);
1204 while (size--)
1205 *output++ = *input++;
1206 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001207#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001208 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1209 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001210#endif
1211#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001212 int size;
1213 char *c;
1214 c = Tcl_GetStringFromObj(value, &size);
1215 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001217 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001218
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220}
1221
Guilherme Polo1972d162009-03-27 21:43:08 +00001222#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001223/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224TCL_DECLARE_MUTEX(call_mutex)
1225
1226typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001227 Tcl_Event ev; /* Must be first */
1228 TkappObject *self;
1229 PyObject *args;
1230 int flags;
1231 PyObject **res;
1232 PyObject **exc_type, **exc_value, **exc_tb;
1233 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001234} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001235#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236
1237void
1238Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001239{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001240 int i;
1241 for (i = 0; i < objc; i++)
1242 Tcl_DecrRefCount(objv[i]);
1243 if (objv != objStore)
1244 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245}
Guido van Rossum18468821994-06-20 07:49:28 +00001246
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001247/* Convert Python objects to Tcl objects. This must happen in the
1248 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001249
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001250static Tcl_Obj**
1251Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1252{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001253 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001254 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001255 if (args == NULL)
1256 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001257
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001258 else if (!PyTuple_Check(args)) {
1259 objv[0] = AsObj(args);
1260 if (objv[0] == 0)
1261 goto finally;
1262 objc = 1;
1263 Tcl_IncrRefCount(objv[0]);
1264 }
1265 else {
1266 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001267
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001268 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001269 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1270 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1271 return NULL;
1272 }
1273 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001274 if (objv == NULL) {
1275 PyErr_NoMemory();
1276 objc = 0;
1277 goto finally;
1278 }
1279 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001280
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001281 for (i = 0; i < objc; i++) {
1282 PyObject *v = PyTuple_GetItem(args, i);
1283 if (v == Py_None) {
1284 objc = i;
1285 break;
1286 }
1287 objv[i] = AsObj(v);
1288 if (!objv[i]) {
1289 /* Reset objc, so it attempts to clear
1290 objects only up to i. */
1291 objc = i;
1292 goto finally;
1293 }
1294 Tcl_IncrRefCount(objv[i]);
1295 }
1296 }
1297 *pobjc = objc;
1298 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001300 Tkapp_CallDeallocArgs(objv, objStore, objc);
1301 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001302}
Guido van Rossum212643f1998-04-29 16:22:14 +00001303
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001305
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306static PyObject*
1307Tkapp_CallResult(TkappObject *self)
1308{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001309 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001310 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001311 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001312 /* Not sure whether the IncrRef is necessary, but something
1313 may overwrite the interpreter result while we are
1314 converting it. */
1315 Tcl_IncrRefCount(value);
1316 res = FromObj((PyObject*)self, value);
1317 Tcl_DecrRefCount(value);
1318 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001319 int len;
1320 const char *s = Tcl_GetStringFromObj(value, &len);
1321 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001322 }
1323 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324}
Guido van Rossum632de272000-03-29 00:19:50 +00001325
Guilherme Polo1972d162009-03-27 21:43:08 +00001326#ifdef WITH_THREAD
1327
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328/* Tkapp_CallProc is the event procedure that is executed in the context of
1329 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1330 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001331
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001332static int
1333Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1334{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001335 Tcl_Obj *objStore[ARGSZ];
1336 Tcl_Obj **objv;
1337 int objc;
1338 int i;
1339 ENTER_PYTHON
1340 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1341 if (!objv) {
1342 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1343 *(e->res) = NULL;
1344 }
1345 LEAVE_PYTHON
1346 if (!objv)
1347 goto done;
1348 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1349 ENTER_PYTHON
1350 if (i == TCL_ERROR) {
1351 *(e->res) = NULL;
1352 *(e->exc_type) = NULL;
1353 *(e->exc_tb) = NULL;
1354 *(e->exc_value) = PyObject_CallFunction(
1355 Tkinter_TclError, "s",
1356 Tcl_GetStringResult(e->self->interp));
1357 }
1358 else {
1359 *(e->res) = Tkapp_CallResult(e->self);
1360 }
1361 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001362
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001363 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001364done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001365 /* Wake up calling thread. */
1366 Tcl_MutexLock(&call_mutex);
1367 Tcl_ConditionNotify(e->done);
1368 Tcl_MutexUnlock(&call_mutex);
1369 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001370}
1371
Guilherme Polo1972d162009-03-27 21:43:08 +00001372#endif
1373
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001374/* This is the main entry point for calling a Tcl command.
1375 It supports three cases, with regard to threading:
1376 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1377 the context of the calling thread.
1378 2. Tcl is threaded, caller of the command is in the interpreter thread:
1379 Execute the command in the calling thread. Since the Tcl lock will
1380 not be used, we can merge that with case 1.
1381 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1382 the interpreter thread. Allocation of Tcl objects needs to occur in the
1383 interpreter thread, so we ship the PyObject* args to the target thread,
1384 and perform processing there. */
1385
1386static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001387Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001389 Tcl_Obj *objStore[ARGSZ];
1390 Tcl_Obj **objv = NULL;
1391 int objc, i;
1392 PyObject *res = NULL;
1393 TkappObject *self = (TkappObject*)selfptr;
1394 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001395
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001396 /* If args is a single tuple, replace with contents of tuple */
1397 if (1 == PyTuple_Size(args)){
1398 PyObject* item = PyTuple_GetItem(args, 0);
1399 if (PyTuple_Check(item))
1400 args = item;
1401 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001402#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001403 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1404 /* We cannot call the command directly. Instead, we must
1405 marshal the parameters to the interpreter thread. */
1406 Tkapp_CallEvent *ev;
1407 Tcl_Condition cond = NULL;
1408 PyObject *exc_type, *exc_value, *exc_tb;
1409 if (!WaitForMainloop(self))
1410 return NULL;
1411 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1412 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1413 ev->self = self;
1414 ev->args = args;
1415 ev->res = &res;
1416 ev->exc_type = &exc_type;
1417 ev->exc_value = &exc_value;
1418 ev->exc_tb = &exc_tb;
1419 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001421 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001422
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001423 if (res == NULL) {
1424 if (exc_type)
1425 PyErr_Restore(exc_type, exc_value, exc_tb);
1426 else
1427 PyErr_SetObject(Tkinter_TclError, exc_value);
1428 }
1429 Tcl_ConditionFinalize(&cond);
1430 }
1431 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001432#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001433 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001434
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001435 objv = Tkapp_CallArgs(args, objStore, &objc);
1436 if (!objv)
1437 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001439 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001441 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001442
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001443 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001445 if (i == TCL_ERROR)
1446 Tkinter_Error(selfptr);
1447 else
1448 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001450 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001452 Tkapp_CallDeallocArgs(objv, objStore, objc);
1453 }
1454 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001455}
1456
1457
1458static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001459Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001460{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001461 /* Could do the same here as for Tkapp_Call(), but this is not used
1462 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1463 way for the user to do what all its Global* variants do (save and
1464 reset the scope pointer, call the local version, restore the saved
1465 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001466
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001467 char *cmd;
1468 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001469
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001470 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001472 cmd = Merge(args);
1473 if (cmd) {
1474 int err;
1475 ENTER_TCL
1476 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1477 ENTER_OVERLAP
1478 if (err == TCL_ERROR)
1479 res = Tkinter_Error(self);
1480 else
1481 res = PyString_FromString(Tkapp_Result(self));
1482 LEAVE_OVERLAP_TCL
1483 ckfree(cmd);
1484 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001486 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001487}
1488
1489static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001490Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001491{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001492 char *script;
1493 PyObject *res = NULL;
1494 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001495
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001496 if (!PyArg_ParseTuple(args, "s:eval", &script))
1497 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001498
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001499 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001500 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001502 ENTER_TCL
1503 err = Tcl_Eval(Tkapp_Interp(self), script);
1504 ENTER_OVERLAP
1505 if (err == TCL_ERROR)
1506 res = Tkinter_Error(self);
1507 else
1508 res = PyString_FromString(Tkapp_Result(self));
1509 LEAVE_OVERLAP_TCL
1510 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001511}
1512
1513static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001514Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001515{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001516 char *script;
1517 PyObject *res = NULL;
1518 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001519
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001520 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1521 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001522
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001523 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001525 ENTER_TCL
1526 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1527 ENTER_OVERLAP
1528 if (err == TCL_ERROR)
1529 res = Tkinter_Error(self);
1530 else
1531 res = PyString_FromString(Tkapp_Result(self));
1532 LEAVE_OVERLAP_TCL
1533 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001534}
1535
1536static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001537Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001538{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001539 char *fileName;
1540 PyObject *res = NULL;
1541 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001542
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001543 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1544 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001545
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001546 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001547 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001548
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 ENTER_TCL
1550 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1551 ENTER_OVERLAP
1552 if (err == TCL_ERROR)
1553 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001554
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001555 else
1556 res = PyString_FromString(Tkapp_Result(self));
1557 LEAVE_OVERLAP_TCL
1558 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001559}
1560
1561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001562Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001563{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001564 char *script;
1565 PyObject *res = NULL;
1566 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001567
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001568 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001569 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001570
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001571 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001572 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001574 ENTER_TCL
1575 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1576 ENTER_OVERLAP
1577 if (err == TCL_ERROR)
1578 res = Tkinter_Error(self);
1579 else
1580 res = PyString_FromString(Tkapp_Result(self));
1581 LEAVE_OVERLAP_TCL
1582 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001583}
1584
1585static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001586Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001587{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001588 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001589
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001590 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1591 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001592 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001593 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001594
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001595 ENTER_TCL
1596 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1597 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001598
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001599 Py_INCREF(Py_None);
1600 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001601}
1602
Barry Warsawfa701a81997-01-16 00:15:11 +00001603
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001604
Guido van Rossum18468821994-06-20 07:49:28 +00001605/** Tcl Variable **/
1606
Guilherme Polo1972d162009-03-27 21:43:08 +00001607typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1608
1609#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610TCL_DECLARE_MUTEX(var_mutex)
1611
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001612typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001613 Tcl_Event ev; /* must be first */
1614 PyObject *self;
1615 PyObject *args;
1616 int flags;
1617 EventFunc func;
1618 PyObject **res;
1619 PyObject **exc_type;
1620 PyObject **exc_val;
1621 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001622} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001623#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001624
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001625static int
1626varname_converter(PyObject *in, void *_out)
1627{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001628 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001629 char **out = (char**)_out;
1630 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001631 if (PyString_Size(in) > INT_MAX) {
1632 PyErr_SetString(PyExc_OverflowError, "string is too long");
1633 return 0;
1634 }
1635 s = PyString_AsString(in);
1636 if (strlen(s) != PyString_Size(in)) {
1637 PyErr_SetString(PyExc_ValueError, "null character in string");
1638 return 0;
1639 }
1640 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001641 return 1;
1642 }
1643 if (PyTclObject_Check(in)) {
1644 *out = PyTclObject_TclString(in);
1645 return 1;
1646 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001647 PyErr_Format(PyExc_TypeError,
1648 "must be str or Tcl_Obj, not %.50s",
1649 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001650 return 0;
1651}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001652
Guilherme Polo1972d162009-03-27 21:43:08 +00001653#ifdef WITH_THREAD
1654
Martin v. Löwis111c1802008-06-13 07:47:47 +00001655static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001656var_perform(VarEvent *ev)
1657{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001658 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1659 if (!*(ev->res)) {
1660 PyObject *exc, *val, *tb;
1661 PyErr_Fetch(&exc, &val, &tb);
1662 PyErr_NormalizeException(&exc, &val, &tb);
1663 *(ev->exc_type) = exc;
1664 *(ev->exc_val) = val;
1665 Py_DECREF(tb);
1666 }
1667
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001668}
1669
1670static int
1671var_proc(VarEvent* ev, int flags)
1672{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001673 ENTER_PYTHON
1674 var_perform(ev);
1675 Tcl_MutexLock(&var_mutex);
1676 Tcl_ConditionNotify(ev->cond);
1677 Tcl_MutexUnlock(&var_mutex);
1678 LEAVE_PYTHON
1679 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001680}
1681
Guilherme Polo1972d162009-03-27 21:43:08 +00001682#endif
1683
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001684static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001685var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001686{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001687#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001688 TkappObject *self = (TkappObject*)selfptr;
1689 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1690 TkappObject *self = (TkappObject*)selfptr;
1691 VarEvent *ev;
1692 PyObject *res, *exc_type, *exc_val;
1693 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001694
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001695 /* The current thread is not the interpreter thread. Marshal
1696 the call to the interpreter thread, then wait for
1697 completion. */
1698 if (!WaitForMainloop(self))
1699 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001700
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001701 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1702
1703 ev->self = selfptr;
1704 ev->args = args;
1705 ev->flags = flags;
1706 ev->func = func;
1707 ev->res = &res;
1708 ev->exc_type = &exc_type;
1709 ev->exc_val = &exc_val;
1710 ev->cond = &cond;
1711 ev->ev.proc = (Tcl_EventProc*)var_proc;
1712 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1713 Tcl_ConditionFinalize(&cond);
1714 if (!res) {
1715 PyErr_SetObject(exc_type, exc_val);
1716 Py_DECREF(exc_type);
1717 Py_DECREF(exc_val);
1718 return NULL;
1719 }
1720 return res;
1721 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001722#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001723 /* Tcl is not threaded, or this is the interpreter thread. */
1724 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001725}
1726
Guido van Rossum18468821994-06-20 07:49:28 +00001727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001728SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001729{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001730 char *name1, *name2;
1731 PyObject *newValue;
1732 PyObject *res = NULL;
1733 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001734
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001735 switch (PyTuple_GET_SIZE(args)) {
1736 case 2:
1737 if (!PyArg_ParseTuple(args, "O&O:setvar",
1738 varname_converter, &name1, &newValue))
1739 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001740 /* XXX Acquire tcl lock??? */
1741 newval = AsObj(newValue);
1742 if (newval == NULL)
1743 return NULL;
1744 ENTER_TCL
1745 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1746 newval, flags);
1747 ENTER_OVERLAP
1748 if (!ok)
1749 Tkinter_Error(self);
1750 else {
1751 res = Py_None;
1752 Py_INCREF(res);
1753 }
1754 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001755 break;
1756 case 3:
1757 if (!PyArg_ParseTuple(args, "ssO:setvar",
1758 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001759 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001760 CHECK_STRING_LENGTH(name1);
1761 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001762 /* XXX must hold tcl lock already??? */
1763 newval = AsObj(newValue);
1764 ENTER_TCL
1765 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1766 ENTER_OVERLAP
1767 if (!ok)
1768 Tkinter_Error(self);
1769 else {
1770 res = Py_None;
1771 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001772 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001773 LEAVE_OVERLAP_TCL
1774 break;
1775 default:
1776 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1777 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001778 }
1779 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001780}
1781
1782static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001783Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001784{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001785 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001786}
1787
1788static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001789Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001790{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001792}
1793
Barry Warsawfa701a81997-01-16 00:15:11 +00001794
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001795
Guido van Rossum18468821994-06-20 07:49:28 +00001796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001799 char *name1, *name2=NULL;
1800 PyObject *res = NULL;
1801 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001802
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001803 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1804 varname_converter, &name1, &name2))
1805 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001806
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001807 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001808 ENTER_TCL
1809 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1810 ENTER_OVERLAP
1811 if (tres == NULL) {
1812 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1813 } else {
1814 if (((TkappObject*)self)->wantobjects) {
1815 res = FromObj(self, tres);
1816 }
1817 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001818 int len;
1819 char *s = Tcl_GetStringFromObj(tres, &len);
1820 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001821 }
1822 }
1823 LEAVE_OVERLAP_TCL
1824 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001825}
1826
1827static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001828Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001829{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001830 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001831}
1832
1833static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001834Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001835{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001836 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001837}
1838
Barry Warsawfa701a81997-01-16 00:15:11 +00001839
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001840
Guido van Rossum18468821994-06-20 07:49:28 +00001841static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001842UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001843{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001844 char *name1, *name2=NULL;
1845 int code;
1846 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001847
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001848 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1849 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001850
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001851 CHECK_STRING_LENGTH(name1);
1852 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001853 ENTER_TCL
1854 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1855 ENTER_OVERLAP
1856 if (code == TCL_ERROR)
1857 res = Tkinter_Error(self);
1858 else {
1859 Py_INCREF(Py_None);
1860 res = Py_None;
1861 }
1862 LEAVE_OVERLAP_TCL
1863 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001864}
1865
1866static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001867Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001868{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001870}
1871
1872static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001873Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001874{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001875 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001876}
1877
Barry Warsawfa701a81997-01-16 00:15:11 +00001878
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001879
Guido van Rossum18468821994-06-20 07:49:28 +00001880/** Tcl to Python **/
1881
1882static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001883Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001884{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001885 char *s;
1886 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001887
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001888 if (PyTuple_Size(args) == 1) {
1889 PyObject* o = PyTuple_GetItem(args, 0);
1890 if (PyInt_Check(o)) {
1891 Py_INCREF(o);
1892 return o;
1893 }
1894 }
1895 if (!PyArg_ParseTuple(args, "s:getint", &s))
1896 return NULL;
1897 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1898 return Tkinter_Error(self);
1899 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001900}
1901
1902static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001903Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001904{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001905 char *s;
1906 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001907
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001908 if (PyTuple_Size(args) == 1) {
1909 PyObject *o = PyTuple_GetItem(args, 0);
1910 if (PyFloat_Check(o)) {
1911 Py_INCREF(o);
1912 return o;
1913 }
1914 }
1915 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1916 return NULL;
1917 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1918 return Tkinter_Error(self);
1919 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001920}
1921
1922static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001923Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001924{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001925 char *s;
1926 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001927
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001928 if (PyTuple_Size(args) == 1) {
1929 PyObject *o = PyTuple_GetItem(args, 0);
1930 if (PyInt_Check(o)) {
1931 Py_INCREF(o);
1932 return o;
1933 }
1934 }
1935 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1936 return NULL;
1937 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1938 return Tkinter_Error(self);
1939 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001940}
1941
1942static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001943Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001944{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001945 char *s;
1946 PyObject *res = NULL;
1947 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001949 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1950 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001951
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001952 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001953 CHECK_TCL_APPARTMENT;
1954
1955 ENTER_TCL
1956 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1957 ENTER_OVERLAP
1958 if (retval == TCL_ERROR)
1959 res = Tkinter_Error(self);
1960 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001961 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001962 LEAVE_OVERLAP_TCL
1963 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001964}
1965
1966static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001967Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001968{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001969 char *s;
1970 PyObject *res = NULL;
1971 int retval;
1972 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001973
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001974 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1975 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001976
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001977 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001978 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001979
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001980 ENTER_TCL
1981 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1982 ENTER_OVERLAP
1983 if (retval == TCL_ERROR)
1984 res = Tkinter_Error(self);
1985 else
1986 res = Py_BuildValue("l", v);
1987 LEAVE_OVERLAP_TCL
1988 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001989}
1990
1991static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001992Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001993{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001994 char *s;
1995 PyObject *res = NULL;
1996 double v;
1997 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001998
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001999 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2000 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002001 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002002 CHECK_TCL_APPARTMENT;
2003 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2004 ENTER_TCL
2005 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2006 ENTER_OVERLAP
2007 PyFPE_END_PROTECT(retval)
2008 if (retval == TCL_ERROR)
2009 res = Tkinter_Error(self);
2010 else
2011 res = Py_BuildValue("d", v);
2012 LEAVE_OVERLAP_TCL
2013 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002014}
2015
2016static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002017Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002018{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002019 char *s;
2020 PyObject *res = NULL;
2021 int retval;
2022 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002023
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002024 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2025 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002026 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002027 CHECK_TCL_APPARTMENT;
2028 ENTER_TCL
2029 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2030 ENTER_OVERLAP
2031 if (retval == TCL_ERROR)
2032 res = Tkinter_Error(self);
2033 else
2034 res = Py_BuildValue("i", v);
2035 LEAVE_OVERLAP_TCL
2036 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002037}
2038
Barry Warsawfa701a81997-01-16 00:15:11 +00002039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002040
Guido van Rossum18468821994-06-20 07:49:28 +00002041static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002042Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002043{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002044 char *list;
2045 int argc;
2046 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002047 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002048 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002049
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002050 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2051 return NULL;
2052 if (PyTclObject_Check(arg)) {
2053 int objc;
2054 Tcl_Obj **objv;
2055 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2056 ((PyTclObject*)arg)->value,
2057 &objc, &objv) == TCL_ERROR) {
2058 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002059 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002060 if (!(v = PyTuple_New(objc)))
2061 return NULL;
2062 for (i = 0; i < objc; i++) {
2063 PyObject *s = FromObj(self, objv[i]);
2064 if (!s || PyTuple_SetItem(v, i, s)) {
2065 Py_DECREF(v);
2066 return NULL;
2067 }
2068 }
2069 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002070 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002071 if (PyTuple_Check(arg)) {
2072 Py_INCREF(arg);
2073 return arg;
2074 }
2075
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002076 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2077 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002078
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002079 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002080 if (Tcl_SplitList(Tkapp_Interp(self), list,
2081 &argc, &argv) == TCL_ERROR) {
2082 PyMem_Free(list);
2083 return Tkinter_Error(self);
2084 }
Guido van Rossum18468821994-06-20 07:49:28 +00002085
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002086 if (!(v = PyTuple_New(argc)))
2087 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002088
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002089 for (i = 0; i < argc; i++) {
2090 PyObject *s = PyString_FromString(argv[i]);
2091 if (!s || PyTuple_SetItem(v, i, s)) {
2092 Py_DECREF(v);
2093 v = NULL;
2094 goto finally;
2095 }
2096 }
Guido van Rossum18468821994-06-20 07:49:28 +00002097
Barry Warsawfa701a81997-01-16 00:15:11 +00002098 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002099 ckfree(FREECAST argv);
2100 PyMem_Free(list);
2101 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002102}
2103
2104static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002105Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002106{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002107 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002108 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002109
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002110 if (!PyArg_ParseTuple(args, "O:split", &arg))
2111 return NULL;
2112 if (PyTclObject_Check(arg)) {
2113 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2114 int objc;
2115 Tcl_Obj **objv;
2116 int i;
2117 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2118 &objc, &objv) == TCL_ERROR) {
2119 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002120 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002121 if (objc == 0)
2122 return PyString_FromString("");
2123 if (objc == 1)
2124 return FromObj(self, objv[0]);
2125 if (!(v = PyTuple_New(objc)))
2126 return NULL;
2127 for (i = 0; i < objc; i++) {
2128 PyObject *s = FromObj(self, objv[i]);
2129 if (!s || PyTuple_SetItem(v, i, s)) {
2130 Py_DECREF(v);
2131 return NULL;
2132 }
2133 }
2134 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002135 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002136 if (PyTuple_Check(arg))
2137 return SplitObj(arg);
2138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002139 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2140 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002141 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002142 v = Split(list);
2143 PyMem_Free(list);
2144 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002145}
2146
2147static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002148Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002149{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002150 char *s = Merge(args);
2151 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002152
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002153 if (s) {
2154 res = PyString_FromString(s);
2155 ckfree(s);
2156 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002157
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002158 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002159}
2160
Barry Warsawfa701a81997-01-16 00:15:11 +00002161
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002162
Guido van Rossum18468821994-06-20 07:49:28 +00002163/** Tcl Command **/
2164
Guido van Rossum00d93061998-05-28 23:06:38 +00002165/* Client data struct */
2166typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002167 PyObject *self;
2168 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002169} PythonCmd_ClientData;
2170
2171static int
Fred Drake509d79a2000-07-08 04:04:38 +00002172PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002173{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002174 errorInCmd = 1;
2175 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2176 LEAVE_PYTHON
2177 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002178}
2179
Guido van Rossum18468821994-06-20 07:49:28 +00002180/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002181 * function or method.
2182 */
Guido van Rossum18468821994-06-20 07:49:28 +00002183static int
Fred Drake509d79a2000-07-08 04:04:38 +00002184PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002185{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002186 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2187 PyObject *func, *arg, *res;
2188 int i, rv;
2189 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002190
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002191 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002192
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002193 /* TBD: no error checking here since we know, via the
2194 * Tkapp_CreateCommand() that the client data is a two-tuple
2195 */
2196 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002197
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002198 /* Create argument list (argv1, ..., argvN) */
2199 if (!(arg = PyTuple_New(argc - 1)))
2200 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002201
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002203 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002204 if (!s || PyTuple_SetItem(arg, i, s)) {
2205 Py_DECREF(arg);
2206 return PythonCmd_Error(interp);
2207 }
2208 }
2209 res = PyEval_CallObject(func, arg);
2210 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002211
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002212 if (res == NULL)
2213 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002215 obj_res = AsObj(res);
2216 if (obj_res == NULL) {
2217 Py_DECREF(res);
2218 return PythonCmd_Error(interp);
2219 }
2220 else {
2221 Tcl_SetObjResult(interp, obj_res);
2222 rv = TCL_OK;
2223 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002224
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002225 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002226
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002227 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002228
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002229 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002230}
2231
2232static void
Fred Drake509d79a2000-07-08 04:04:38 +00002233PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002234{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002235 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002237 ENTER_PYTHON
2238 Py_XDECREF(data->self);
2239 Py_XDECREF(data->func);
2240 PyMem_DEL(data);
2241 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002242}
2243
Barry Warsawfa701a81997-01-16 00:15:11 +00002244
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002245
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002246
Guilherme Polo1972d162009-03-27 21:43:08 +00002247#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002248TCL_DECLARE_MUTEX(command_mutex)
2249
2250typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002251 Tcl_Event ev;
2252 Tcl_Interp* interp;
2253 char *name;
2254 int create;
2255 int *status;
2256 ClientData *data;
2257 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002258} CommandEvent;
2259
2260static int
2261Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002262{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002263 if (ev->create)
2264 *ev->status = Tcl_CreateCommand(
2265 ev->interp, ev->name, PythonCmd,
2266 ev->data, PythonCmdDelete) == NULL;
2267 else
2268 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2269 Tcl_MutexLock(&command_mutex);
2270 Tcl_ConditionNotify(ev->done);
2271 Tcl_MutexUnlock(&command_mutex);
2272 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002273}
Guilherme Polo1972d162009-03-27 21:43:08 +00002274#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002275
2276static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002277Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002278{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002279 TkappObject *self = (TkappObject*)selfptr;
2280 PythonCmd_ClientData *data;
2281 char *cmdName;
2282 PyObject *func;
2283 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002284
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002285 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2286 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002287 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002288 if (!PyCallable_Check(func)) {
2289 PyErr_SetString(PyExc_TypeError, "command not callable");
2290 return NULL;
2291 }
Guido van Rossum18468821994-06-20 07:49:28 +00002292
Martin v. Löwisa9656492003-03-30 08:44:58 +00002293#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002294 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2295 !WaitForMainloop(self))
2296 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002297#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002298
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002299 data = PyMem_NEW(PythonCmd_ClientData, 1);
2300 if (!data)
2301 return PyErr_NoMemory();
2302 Py_INCREF(self);
2303 Py_INCREF(func);
2304 data->self = selfptr;
2305 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002306
2307#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002308 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2309 Tcl_Condition cond = NULL;
2310 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2311 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2312 ev->interp = self->interp;
2313 ev->create = 1;
2314 ev->name = cmdName;
2315 ev->data = (ClientData)data;
2316 ev->status = &err;
2317 ev->done = &cond;
2318 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2319 Tcl_ConditionFinalize(&cond);
2320 }
2321 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002322#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002323 {
2324 ENTER_TCL
2325 err = Tcl_CreateCommand(
2326 Tkapp_Interp(self), cmdName, PythonCmd,
2327 (ClientData)data, PythonCmdDelete) == NULL;
2328 LEAVE_TCL
2329 }
2330 if (err) {
2331 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2332 PyMem_DEL(data);
2333 return NULL;
2334 }
Guido van Rossum18468821994-06-20 07:49:28 +00002335
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002336 Py_INCREF(Py_None);
2337 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002338}
2339
Barry Warsawfa701a81997-01-16 00:15:11 +00002340
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002341
Guido van Rossum18468821994-06-20 07:49:28 +00002342static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002343Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002344{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002345 TkappObject *self = (TkappObject*)selfptr;
2346 char *cmdName;
2347 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002348
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002349 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2350 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002351 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002352
2353#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002354 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2355 Tcl_Condition cond = NULL;
2356 CommandEvent *ev;
2357 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2358 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2359 ev->interp = self->interp;
2360 ev->create = 0;
2361 ev->name = cmdName;
2362 ev->status = &err;
2363 ev->done = &cond;
2364 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2365 &command_mutex);
2366 Tcl_ConditionFinalize(&cond);
2367 }
2368 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002369#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002370 {
2371 ENTER_TCL
2372 err = Tcl_DeleteCommand(self->interp, cmdName);
2373 LEAVE_TCL
2374 }
2375 if (err == -1) {
2376 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2377 return NULL;
2378 }
2379 Py_INCREF(Py_None);
2380 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002381}
2382
Barry Warsawfa701a81997-01-16 00:15:11 +00002383
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002384
Guido van Rossum00d93061998-05-28 23:06:38 +00002385#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002386/** File Handler **/
2387
Guido van Rossum00d93061998-05-28 23:06:38 +00002388typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002389 PyObject *func;
2390 PyObject *file;
2391 int id;
2392 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002393} FileHandler_ClientData;
2394
2395static FileHandler_ClientData *HeadFHCD;
2396
2397static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002398NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002399{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002400 FileHandler_ClientData *p;
2401 p = PyMem_NEW(FileHandler_ClientData, 1);
2402 if (p != NULL) {
2403 Py_XINCREF(func);
2404 Py_XINCREF(file);
2405 p->func = func;
2406 p->file = file;
2407 p->id = id;
2408 p->next = HeadFHCD;
2409 HeadFHCD = p;
2410 }
2411 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002412}
2413
2414static void
Fred Drake509d79a2000-07-08 04:04:38 +00002415DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002416{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002417 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002418
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002419 pp = &HeadFHCD;
2420 while ((p = *pp) != NULL) {
2421 if (p->id == id) {
2422 *pp = p->next;
2423 Py_XDECREF(p->func);
2424 Py_XDECREF(p->file);
2425 PyMem_DEL(p);
2426 }
2427 else
2428 pp = &p->next;
2429 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002430}
2431
Guido van Rossuma597dde1995-01-10 20:56:29 +00002432static void
Fred Drake509d79a2000-07-08 04:04:38 +00002433FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002434{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002435 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2436 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002437
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002438 ENTER_PYTHON
2439 func = data->func;
2440 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442 arg = Py_BuildValue("(Oi)", file, (long) mask);
2443 res = PyEval_CallObject(func, arg);
2444 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002445
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002446 if (res == NULL) {
2447 errorInCmd = 1;
2448 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2449 }
2450 Py_XDECREF(res);
2451 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002452}
2453
Guido van Rossum18468821994-06-20 07:49:28 +00002454static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002455Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2456 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002457{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002458 FileHandler_ClientData *data;
2459 PyObject *file, *func;
2460 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002462 if (!self && Py_Py3kWarningFlag) {
2463 if (PyErr_Warn(PyExc_DeprecationWarning,
2464 "_tkinter.createfilehandler is gone in 3.x") < 0)
2465 return NULL;
2466 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002467
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002468 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2469 &file, &mask, &func))
2470 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002471
Martin v. Löwisa9656492003-03-30 08:44:58 +00002472#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002473 if (!self && !tcl_lock) {
2474 /* We don't have the Tcl lock since Tcl is threaded. */
2475 PyErr_SetString(PyExc_RuntimeError,
2476 "_tkinter.createfilehandler not supported "
2477 "for threaded Tcl");
2478 return NULL;
2479 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002480#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002481
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002482 if (self) {
2483 CHECK_TCL_APPARTMENT;
2484 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002486 tfile = PyObject_AsFileDescriptor(file);
2487 if (tfile < 0)
2488 return NULL;
2489 if (!PyCallable_Check(func)) {
2490 PyErr_SetString(PyExc_TypeError, "bad argument list");
2491 return NULL;
2492 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002493
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002494 data = NewFHCD(func, file, tfile);
2495 if (data == NULL)
2496 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002497
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002498 /* Ought to check for null Tcl_File object... */
2499 ENTER_TCL
2500 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2501 LEAVE_TCL
2502 Py_INCREF(Py_None);
2503 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002504}
2505
2506static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002507Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002508{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002509 PyObject *file;
2510 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 if (!self && Py_Py3kWarningFlag) {
2513 if (PyErr_Warn(PyExc_DeprecationWarning,
2514 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2515 return NULL;
2516 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002517
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002518 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2519 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002520
Martin v. Löwisa9656492003-03-30 08:44:58 +00002521#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002522 if (!self && !tcl_lock) {
2523 /* We don't have the Tcl lock since Tcl is threaded. */
2524 PyErr_SetString(PyExc_RuntimeError,
2525 "_tkinter.deletefilehandler not supported "
2526 "for threaded Tcl");
2527 return NULL;
2528 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002529#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002531 if (self) {
2532 CHECK_TCL_APPARTMENT;
2533 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002535 tfile = PyObject_AsFileDescriptor(file);
2536 if (tfile < 0)
2537 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002538
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002539 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002540
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002541 /* Ought to check for null Tcl_File object... */
2542 ENTER_TCL
2543 Tcl_DeleteFileHandler(tfile);
2544 LEAVE_TCL
2545 Py_INCREF(Py_None);
2546 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002547}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002548#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002549
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002550
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002551/**** Tktt Object (timer token) ****/
2552
Jeremy Hylton938ace62002-07-17 16:30:39 +00002553static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002554
Guido van Rossum00d93061998-05-28 23:06:38 +00002555typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002556 PyObject_HEAD
2557 Tcl_TimerToken token;
2558 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002559} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002560
2561static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002562Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002563{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002564 TkttObject *v = (TkttObject *)self;
2565 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002566
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002567 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2568 return NULL;
2569 if (v->token != NULL) {
2570 Tcl_DeleteTimerHandler(v->token);
2571 v->token = NULL;
2572 }
2573 if (func != NULL) {
2574 v->func = NULL;
2575 Py_DECREF(func);
2576 Py_DECREF(v); /* See Tktt_New() */
2577 }
2578 Py_INCREF(Py_None);
2579 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002580}
2581
2582static PyMethodDef Tktt_methods[] =
2583{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002584 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2585 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002586};
2587
2588static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002589Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002590{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002591 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002592
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002593 v = PyObject_New(TkttObject, &Tktt_Type);
2594 if (v == NULL)
2595 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002596
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002597 Py_INCREF(func);
2598 v->token = NULL;
2599 v->func = func;
2600
2601 /* Extra reference, deleted when called or when handler is deleted */
2602 Py_INCREF(v);
2603 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002604}
2605
2606static void
Fred Drake509d79a2000-07-08 04:04:38 +00002607Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002608{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002609 TkttObject *v = (TkttObject *)self;
2610 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002611
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002612 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002613
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002614 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002615}
2616
Guido van Rossum597ac201998-05-12 14:36:19 +00002617static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002618Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002619{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002620 TkttObject *v = (TkttObject *)self;
2621 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002622
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002623 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2624 v->func == NULL ? ", handler deleted" : "");
2625 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002626}
2627
2628static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002629Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002630{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002631 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002632}
2633
2634static PyTypeObject Tktt_Type =
2635{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002636 PyVarObject_HEAD_INIT(NULL, 0)
2637 "tktimertoken", /*tp_name */
2638 sizeof(TkttObject), /*tp_basicsize */
2639 0, /*tp_itemsize */
2640 Tktt_Dealloc, /*tp_dealloc */
2641 0, /*tp_print */
2642 Tktt_GetAttr, /*tp_getattr */
2643 0, /*tp_setattr */
2644 0, /*tp_compare */
2645 Tktt_Repr, /*tp_repr */
2646 0, /*tp_as_number */
2647 0, /*tp_as_sequence */
2648 0, /*tp_as_mapping */
2649 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002650};
2651
Barry Warsawfa701a81997-01-16 00:15:11 +00002652
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002653
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002654/** Timer Handler **/
2655
2656static void
Fred Drake509d79a2000-07-08 04:04:38 +00002657TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002658{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002659 TkttObject *v = (TkttObject *)clientData;
2660 PyObject *func = v->func;
2661 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002662
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002663 if (func == NULL)
2664 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002665
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002666 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002667
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002668 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002669
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002670 res = PyEval_CallObject(func, NULL);
2671 Py_DECREF(func);
2672 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002673
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002674 if (res == NULL) {
2675 errorInCmd = 1;
2676 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2677 }
2678 else
2679 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002680
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002681 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002682}
2683
2684static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002685Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002686{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002687 int milliseconds;
2688 PyObject *func;
2689 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002690
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002691 if (!self && Py_Py3kWarningFlag) {
2692 if (PyErr_Warn(PyExc_DeprecationWarning,
2693 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2694 return NULL;
2695 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002696
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002697 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2698 &milliseconds, &func))
2699 return NULL;
2700 if (!PyCallable_Check(func)) {
2701 PyErr_SetString(PyExc_TypeError, "bad argument list");
2702 return NULL;
2703 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002704
Martin v. Löwisa9656492003-03-30 08:44:58 +00002705#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002706 if (!self && !tcl_lock) {
2707 /* We don't have the Tcl lock since Tcl is threaded. */
2708 PyErr_SetString(PyExc_RuntimeError,
2709 "_tkinter.createtimerhandler not supported "
2710 "for threaded Tcl");
2711 return NULL;
2712 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002713#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002714
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002715 if (self) {
2716 CHECK_TCL_APPARTMENT;
2717 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002718
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002719 v = Tktt_New(func);
2720 if (v) {
2721 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2722 (ClientData)v);
2723 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002724
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002725 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726}
2727
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002728
Guido van Rossum18468821994-06-20 07:49:28 +00002729/** Event Loop **/
2730
Guido van Rossum18468821994-06-20 07:49:28 +00002731static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002732Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002733{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002734 int threshold = 0;
2735 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002736#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002737 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002738#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002739
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002740 if (!self && Py_Py3kWarningFlag) {
2741 if (PyErr_Warn(PyExc_DeprecationWarning,
2742 "_tkinter.mainloop is gone in 3.x") < 0)
2743 return NULL;
2744 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002745
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2747 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002748
Martin v. Löwisa9656492003-03-30 08:44:58 +00002749#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002750 if (!self && !tcl_lock) {
2751 /* We don't have the Tcl lock since Tcl is threaded. */
2752 PyErr_SetString(PyExc_RuntimeError,
2753 "_tkinter.mainloop not supported "
2754 "for threaded Tcl");
2755 return NULL;
2756 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002757#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002758
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002759 if (self) {
2760 CHECK_TCL_APPARTMENT;
2761 self->dispatching = 1;
2762 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002764 quitMainLoop = 0;
2765 while (Tk_GetNumMainWindows() > threshold &&
2766 !quitMainLoop &&
2767 !errorInCmd)
2768 {
2769 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002770
2771#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002772 if (self && self->threaded) {
2773 /* Allow other Python threads to run. */
2774 ENTER_TCL
2775 result = Tcl_DoOneEvent(0);
2776 LEAVE_TCL
2777 }
2778 else {
2779 Py_BEGIN_ALLOW_THREADS
2780 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2781 tcl_tstate = tstate;
2782 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2783 tcl_tstate = NULL;
2784 if(tcl_lock)PyThread_release_lock(tcl_lock);
2785 if (result == 0)
2786 Sleep(Tkinter_busywaitinterval);
2787 Py_END_ALLOW_THREADS
2788 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002789#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002790 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002791#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002792
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002793 if (PyErr_CheckSignals() != 0) {
2794 if (self)
2795 self->dispatching = 0;
2796 return NULL;
2797 }
2798 if (result < 0)
2799 break;
2800 }
2801 if (self)
2802 self->dispatching = 0;
2803 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002804
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002805 if (errorInCmd) {
2806 errorInCmd = 0;
2807 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2808 excInCmd = valInCmd = trbInCmd = NULL;
2809 return NULL;
2810 }
2811 Py_INCREF(Py_None);
2812 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002813}
2814
2815static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002816Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002817{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002818 int flags = 0;
2819 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002820
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002821 if (!self && Py_Py3kWarningFlag) {
2822 if (PyErr_Warn(PyExc_DeprecationWarning,
2823 "_tkinter.dooneevent is gone in 3.x") < 0)
2824 return NULL;
2825 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002826
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002827 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2828 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002829
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002830 ENTER_TCL
2831 rv = Tcl_DoOneEvent(flags);
2832 LEAVE_TCL
2833 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002834}
2835
2836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002837Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002838{
2839
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002840 if (!self && Py_Py3kWarningFlag) {
2841 if (PyErr_Warn(PyExc_DeprecationWarning,
2842 "_tkinter.quit is gone in 3.x") < 0)
2843 return NULL;
2844 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002845
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002846 if (!PyArg_ParseTuple(args, ":quit"))
2847 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002848
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002849 quitMainLoop = 1;
2850 Py_INCREF(Py_None);
2851 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002852}
2853
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002854static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002855Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002856{
2857
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002858 if (!PyArg_ParseTuple(args, ":interpaddr"))
2859 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002860
Victor Stinner930c3c92013-09-05 00:26:15 +02002861 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002862}
2863
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002864static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002865Tkapp_TkInit(PyObject *self, PyObject *args)
2866{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002867 Tcl_Interp *interp = Tkapp_Interp(self);
2868 const char * _tk_exists = NULL;
2869 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002870
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002871#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002872 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2873 * first call failed.
2874 * To avoid the deadlock, we just refuse the second call through
2875 * a static variable.
2876 */
2877 if (tk_load_failed) {
2878 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2879 return NULL;
2880 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002881#endif
2882
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002883 /* We want to guard against calling Tk_Init() multiple times */
2884 CHECK_TCL_APPARTMENT;
2885 ENTER_TCL
2886 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2887 ENTER_OVERLAP
2888 if (err == TCL_ERROR) {
2889 /* This sets an exception, but we cannot return right
2890 away because we need to exit the overlap first. */
2891 Tkinter_Error(self);
2892 } else {
2893 _tk_exists = Tkapp_Result(self);
2894 }
2895 LEAVE_OVERLAP_TCL
2896 if (err == TCL_ERROR) {
2897 return NULL;
2898 }
2899 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2900 if (Tk_Init(interp) == TCL_ERROR) {
2901 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002902#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002903 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002904#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002905 return NULL;
2906 }
2907 }
2908 Py_INCREF(Py_None);
2909 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002910}
Barry Warsawfa701a81997-01-16 00:15:11 +00002911
Martin v. Löwisffad6332002-11-26 09:28:05 +00002912static PyObject *
2913Tkapp_WantObjects(PyObject *self, PyObject *args)
2914{
2915
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002916 int wantobjects = -1;
2917 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2918 return NULL;
2919 if (wantobjects == -1)
2920 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2921 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002922
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002923 Py_INCREF(Py_None);
2924 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002925}
2926
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002927static PyObject *
2928Tkapp_WillDispatch(PyObject *self, PyObject *args)
2929{
2930
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002931 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002932
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002933 Py_INCREF(Py_None);
2934 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002935}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002936
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002937
Guido van Rossum18468821994-06-20 07:49:28 +00002938/**** Tkapp Method List ****/
2939
2940static PyMethodDef Tkapp_methods[] =
2941{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002942 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2943 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2944 {"call", Tkapp_Call, METH_VARARGS},
2945 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2946 {"eval", Tkapp_Eval, METH_VARARGS},
2947 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2948 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2949 {"record", Tkapp_Record, METH_VARARGS},
2950 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2951 {"setvar", Tkapp_SetVar, METH_VARARGS},
2952 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2953 {"getvar", Tkapp_GetVar, METH_VARARGS},
2954 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2955 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2956 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2957 {"getint", Tkapp_GetInt, METH_VARARGS},
2958 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2959 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2960 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2961 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2962 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2963 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2964 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2965 {"split", Tkapp_Split, METH_VARARGS},
2966 {"merge", Tkapp_Merge, METH_VARARGS},
2967 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2968 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002969#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002970 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2971 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002972#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002973 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2974 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2975 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2976 {"quit", Tkapp_Quit, METH_VARARGS},
2977 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2978 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2979 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002980};
2981
Barry Warsawfa701a81997-01-16 00:15:11 +00002982
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002983
Guido van Rossum18468821994-06-20 07:49:28 +00002984/**** Tkapp Type Methods ****/
2985
2986static void
Fred Drake509d79a2000-07-08 04:04:38 +00002987Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002988{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002989 /*CHECK_TCL_APPARTMENT;*/
2990 ENTER_TCL
2991 Tcl_DeleteInterp(Tkapp_Interp(self));
2992 LEAVE_TCL
2993 PyObject_Del(self);
2994 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002995}
2996
2997static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002998Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002999{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003000 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003001}
3002
3003static PyTypeObject Tkapp_Type =
3004{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003005 PyVarObject_HEAD_INIT(NULL, 0)
3006 "tkapp", /*tp_name */
3007 sizeof(TkappObject), /*tp_basicsize */
3008 0, /*tp_itemsize */
3009 Tkapp_Dealloc, /*tp_dealloc */
3010 0, /*tp_print */
3011 Tkapp_GetAttr, /*tp_getattr */
3012 0, /*tp_setattr */
3013 0, /*tp_compare */
3014 0, /*tp_repr */
3015 0, /*tp_as_number */
3016 0, /*tp_as_sequence */
3017 0, /*tp_as_mapping */
3018 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003019};
3020
Barry Warsawfa701a81997-01-16 00:15:11 +00003021
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003022
Guido van Rossum18468821994-06-20 07:49:28 +00003023/**** Tkinter Module ****/
3024
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003025typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003026 PyObject* tuple;
3027 int size; /* current size */
3028 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003029} FlattenContext;
3030
3031static int
3032_bump(FlattenContext* context, int size)
3033{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003034 /* expand tuple to hold (at least) size new items.
3035 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003036
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003037 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003038
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003039 if (maxsize < context->size + size)
3040 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003042 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003043
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003044 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003045}
3046
3047static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003048_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003049{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003050 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003052 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003053
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003054 if (depth > 1000) {
3055 PyErr_SetString(PyExc_ValueError,
3056 "nesting too deep in _flatten");
3057 return 0;
3058 } else if (PyList_Check(item)) {
3059 size = PyList_GET_SIZE(item);
3060 /* preallocate (assume no nesting) */
3061 if (context->size + size > context->maxsize &&
3062 !_bump(context, size))
3063 return 0;
3064 /* copy items to output tuple */
3065 for (i = 0; i < size; i++) {
3066 PyObject *o = PyList_GET_ITEM(item, i);
3067 if (PyList_Check(o) || PyTuple_Check(o)) {
3068 if (!_flatten1(context, o, depth + 1))
3069 return 0;
3070 } else if (o != Py_None) {
3071 if (context->size + 1 > context->maxsize &&
3072 !_bump(context, 1))
3073 return 0;
3074 Py_INCREF(o);
3075 PyTuple_SET_ITEM(context->tuple,
3076 context->size++, o);
3077 }
3078 }
3079 } else if (PyTuple_Check(item)) {
3080 /* same, for tuples */
3081 size = PyTuple_GET_SIZE(item);
3082 if (context->size + size > context->maxsize &&
3083 !_bump(context, size))
3084 return 0;
3085 for (i = 0; i < size; i++) {
3086 PyObject *o = PyTuple_GET_ITEM(item, i);
3087 if (PyList_Check(o) || PyTuple_Check(o)) {
3088 if (!_flatten1(context, o, depth + 1))
3089 return 0;
3090 } else if (o != Py_None) {
3091 if (context->size + 1 > context->maxsize &&
3092 !_bump(context, 1))
3093 return 0;
3094 Py_INCREF(o);
3095 PyTuple_SET_ITEM(context->tuple,
3096 context->size++, o);
3097 }
3098 }
3099 } else {
3100 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3101 return 0;
3102 }
3103 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003104}
3105
3106static PyObject *
3107Tkinter_Flatten(PyObject* self, PyObject* args)
3108{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003109 FlattenContext context;
3110 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003111
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003112 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3113 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003115 context.maxsize = PySequence_Size(item);
3116 if (context.maxsize < 0)
3117 return NULL;
3118 if (context.maxsize == 0)
3119 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003120
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003121 context.tuple = PyTuple_New(context.maxsize);
3122 if (!context.tuple)
3123 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003124
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003125 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003126
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003127 if (!_flatten1(&context, item,0))
3128 return NULL;
3129
3130 if (_PyTuple_Resize(&context.tuple, context.size))
3131 return NULL;
3132
3133 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003134}
3135
Guido van Rossum18468821994-06-20 07:49:28 +00003136static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003137Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003138{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003139 char *screenName = NULL;
3140 char *baseName = NULL;
3141 char *className = NULL;
3142 int interactive = 0;
3143 int wantobjects = 0;
3144 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3145 int sync = 0; /* pass -sync to wish */
3146 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003147
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003148 baseName = strrchr(Py_GetProgramName(), '/');
3149 if (baseName != NULL)
3150 baseName++;
3151 else
3152 baseName = Py_GetProgramName();
3153 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003155 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3156 &screenName, &baseName, &className,
3157 &interactive, &wantobjects, &wantTk,
3158 &sync, &use))
3159 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003160 CHECK_STRING_LENGTH(screenName);
3161 CHECK_STRING_LENGTH(baseName);
3162 CHECK_STRING_LENGTH(className);
3163 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003164
3165 return (PyObject *) Tkapp_New(screenName, baseName, className,
3166 interactive, wantobjects, wantTk,
3167 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003168}
3169
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003170static PyObject *
3171Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3172{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003173 int new_val;
3174 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3175 return NULL;
3176 if (new_val < 0) {
3177 PyErr_SetString(PyExc_ValueError,
3178 "busywaitinterval must be >= 0");
3179 return NULL;
3180 }
3181 Tkinter_busywaitinterval = new_val;
3182 Py_INCREF(Py_None);
3183 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003184}
3185
3186static char setbusywaitinterval_doc[] =
3187"setbusywaitinterval(n) -> None\n\
3188\n\
3189Set the busy-wait interval in milliseconds between successive\n\
3190calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3191It should be set to a divisor of the maximum time between\n\
3192frames in an animation.";
3193
3194static PyObject *
3195Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3196{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003197 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003198}
3199
3200static char getbusywaitinterval_doc[] =
3201"getbusywaitinterval() -> int\n\
3202\n\
3203Return the current busy-wait interval between successive\n\
3204calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3205
Guido van Rossum18468821994-06-20 07:49:28 +00003206static PyMethodDef moduleMethods[] =
3207{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003208 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3209 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003210#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003211 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3212 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003213#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003214 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3215 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3216 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3217 {"quit", Tkapp_Quit, METH_VARARGS},
3218 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3219 setbusywaitinterval_doc},
3220 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3221 METH_NOARGS, getbusywaitinterval_doc},
3222 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003223};
3224
Guido van Rossum7bf15641998-05-22 18:28:17 +00003225#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003226
3227static int stdin_ready = 0;
3228
Guido van Rossumad4db171998-06-13 13:56:28 +00003229#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003230static void
Fred Drake509d79a2000-07-08 04:04:38 +00003231MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003232{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003233 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003234}
Guido van Rossumad4db171998-06-13 13:56:28 +00003235#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003236
Martin v. Löwisa9656492003-03-30 08:44:58 +00003237#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003238static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003239#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003240
Guido van Rossum18468821994-06-20 07:49:28 +00003241static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003242EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003243{
Guido van Rossumad4db171998-06-13 13:56:28 +00003244#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003245 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003246#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003247#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003248 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003249#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003250 stdin_ready = 0;
3251 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003252#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003253 tfile = fileno(stdin);
3254 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003255#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003256 while (!errorInCmd && !stdin_ready) {
3257 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003258#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003259 if (_kbhit()) {
3260 stdin_ready = 1;
3261 break;
3262 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003263#endif
3264#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003265 Py_BEGIN_ALLOW_THREADS
3266 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3267 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003268
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003269 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003270
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003271 tcl_tstate = NULL;
3272 if(tcl_lock)PyThread_release_lock(tcl_lock);
3273 if (result == 0)
3274 Sleep(Tkinter_busywaitinterval);
3275 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003276#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003277 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003278#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003279
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003280 if (result < 0)
3281 break;
3282 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003283#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003284 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003285#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003286 if (errorInCmd) {
3287 errorInCmd = 0;
3288 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3289 excInCmd = valInCmd = trbInCmd = NULL;
3290 PyErr_Print();
3291 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003292#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003293 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003294#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003295 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003296}
Guido van Rossum18468821994-06-20 07:49:28 +00003297
Guido van Rossum00d93061998-05-28 23:06:38 +00003298#endif
3299
Guido van Rossum7bf15641998-05-22 18:28:17 +00003300static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003301EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003302{
Guido van Rossum00d93061998-05-28 23:06:38 +00003303#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003304 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003305#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003306 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003307#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003308 PyOS_InputHook = EventHook;
3309 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003310#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003311}
3312
3313static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003314DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003315{
Guido van Rossum00d93061998-05-28 23:06:38 +00003316#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003317 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3318 PyOS_InputHook = NULL;
3319 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003320#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003321}
3322
Barry Warsawfa701a81997-01-16 00:15:11 +00003323
3324/* all errors will be checked in one fell swoop in init_tkinter() */
3325static void
Fred Drake509d79a2000-07-08 04:04:38 +00003326ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003327{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003328 PyObject *v = PyInt_FromLong(val);
3329 if (v) {
3330 PyDict_SetItemString(d, name, v);
3331 Py_DECREF(v);
3332 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003333}
3334static void
Fred Drake509d79a2000-07-08 04:04:38 +00003335ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003336{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003337 PyObject *v = PyString_FromString(val);
3338 if (v) {
3339 PyDict_SetItemString(d, name, v);
3340 Py_DECREF(v);
3341 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003342}
3343
3344
Mark Hammond62b1ab12002-07-23 06:31:15 +00003345PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003346init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003347{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003348 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003349
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003350 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003351
3352#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003353 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003354#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003355
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003356 m = Py_InitModule("_tkinter", moduleMethods);
3357 if (m == NULL)
3358 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003359
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003360 d = PyModule_GetDict(m);
3361 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3362 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003363
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003364 ins_long(d, "READABLE", TCL_READABLE);
3365 ins_long(d, "WRITABLE", TCL_WRITABLE);
3366 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3367 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3368 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3369 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3370 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3371 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3372 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3373 ins_string(d, "TK_VERSION", TK_VERSION);
3374 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003375
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003376 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003377
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003378 Py_TYPE(&Tktt_Type) = &PyType_Type;
3379 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003381 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3382 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003383
3384#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003385 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3386 * start waking up. Note that Tcl_FindExecutable will do this, this
3387 * code must be above it! The original warning from
3388 * tkMacOSXAppInit.c is copied below.
3389 *
3390 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3391 * Tcl interpreter for now. It probably should work to do this
3392 * in the other order, but for now it doesn't seem to.
3393 *
3394 */
3395 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003396#endif
3397
3398
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003399 /* This helps the dynamic loader; in Unicode aware Tcl versions
3400 it also helps Tcl find its encodings. */
3401 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003402
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003403 if (PyErr_Occurred())
3404 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003405
Guido van Rossum43ff8681998-07-14 18:02:13 +00003406#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003407 /* This was not a good idea; through <Destroy> bindings,
3408 Tcl_Finalize() may invoke Python code but at that point the
3409 interpreter and thread state have already been destroyed! */
3410 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003411#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003412
Guido van Rossum18468821994-06-20 07:49:28 +00003413}