blob: 4aa8594e765116a2817d64242f0d2c63d6d68e4f [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;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001897 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001898 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1899 return Tkinter_Error(self);
1900 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001901}
1902
1903static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001904Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001905{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001906 char *s;
1907 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001908
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 if (PyTuple_Size(args) == 1) {
1910 PyObject *o = PyTuple_GetItem(args, 0);
1911 if (PyFloat_Check(o)) {
1912 Py_INCREF(o);
1913 return o;
1914 }
1915 }
1916 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1917 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001918 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001919 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1920 return Tkinter_Error(self);
1921 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001927 char *s;
1928 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001929
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001930 if (PyTuple_Size(args) == 1) {
1931 PyObject *o = PyTuple_GetItem(args, 0);
1932 if (PyInt_Check(o)) {
1933 Py_INCREF(o);
1934 return o;
1935 }
1936 }
1937 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1938 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001939 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001940 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1941 return Tkinter_Error(self);
1942 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001943}
1944
1945static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001946Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001947{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001948 char *s;
1949 PyObject *res = NULL;
1950 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001951
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001952 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1953 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001954
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001955 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001956 CHECK_TCL_APPARTMENT;
1957
1958 ENTER_TCL
1959 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1960 ENTER_OVERLAP
1961 if (retval == TCL_ERROR)
1962 res = Tkinter_Error(self);
1963 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001964 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001965 LEAVE_OVERLAP_TCL
1966 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001967}
1968
1969static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001970Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001971{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001972 char *s;
1973 PyObject *res = NULL;
1974 int retval;
1975 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001976
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001977 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1978 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001979
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001980 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001981 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001982
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001983 ENTER_TCL
1984 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1985 ENTER_OVERLAP
1986 if (retval == TCL_ERROR)
1987 res = Tkinter_Error(self);
1988 else
1989 res = Py_BuildValue("l", v);
1990 LEAVE_OVERLAP_TCL
1991 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001992}
1993
1994static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001995Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001996{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001997 char *s;
1998 PyObject *res = NULL;
1999 double v;
2000 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002001
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002002 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2003 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002004 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002005 CHECK_TCL_APPARTMENT;
2006 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2007 ENTER_TCL
2008 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2009 ENTER_OVERLAP
2010 PyFPE_END_PROTECT(retval)
2011 if (retval == TCL_ERROR)
2012 res = Tkinter_Error(self);
2013 else
2014 res = Py_BuildValue("d", v);
2015 LEAVE_OVERLAP_TCL
2016 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002017}
2018
2019static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002020Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002021{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002022 char *s;
2023 PyObject *res = NULL;
2024 int retval;
2025 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002027 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2028 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002029 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002030 CHECK_TCL_APPARTMENT;
2031 ENTER_TCL
2032 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2033 ENTER_OVERLAP
2034 if (retval == TCL_ERROR)
2035 res = Tkinter_Error(self);
2036 else
2037 res = Py_BuildValue("i", v);
2038 LEAVE_OVERLAP_TCL
2039 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002040}
2041
Barry Warsawfa701a81997-01-16 00:15:11 +00002042
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002043
Guido van Rossum18468821994-06-20 07:49:28 +00002044static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002045Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002046{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002047 char *list;
2048 int argc;
2049 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002050 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002051 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002052
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002053 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2054 return NULL;
2055 if (PyTclObject_Check(arg)) {
2056 int objc;
2057 Tcl_Obj **objv;
2058 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2059 ((PyTclObject*)arg)->value,
2060 &objc, &objv) == TCL_ERROR) {
2061 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002062 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002063 if (!(v = PyTuple_New(objc)))
2064 return NULL;
2065 for (i = 0; i < objc; i++) {
2066 PyObject *s = FromObj(self, objv[i]);
2067 if (!s || PyTuple_SetItem(v, i, s)) {
2068 Py_DECREF(v);
2069 return NULL;
2070 }
2071 }
2072 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002073 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002074 if (PyTuple_Check(arg)) {
2075 Py_INCREF(arg);
2076 return arg;
2077 }
2078
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002079 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2080 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002082 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002083 if (Tcl_SplitList(Tkapp_Interp(self), list,
2084 &argc, &argv) == TCL_ERROR) {
2085 PyMem_Free(list);
2086 return Tkinter_Error(self);
2087 }
Guido van Rossum18468821994-06-20 07:49:28 +00002088
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002089 if (!(v = PyTuple_New(argc)))
2090 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 for (i = 0; i < argc; i++) {
2093 PyObject *s = PyString_FromString(argv[i]);
2094 if (!s || PyTuple_SetItem(v, i, s)) {
2095 Py_DECREF(v);
2096 v = NULL;
2097 goto finally;
2098 }
2099 }
Guido van Rossum18468821994-06-20 07:49:28 +00002100
Barry Warsawfa701a81997-01-16 00:15:11 +00002101 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002102 ckfree(FREECAST argv);
2103 PyMem_Free(list);
2104 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002105}
2106
2107static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002108Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002109{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002110 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002112
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002113 if (!PyArg_ParseTuple(args, "O:split", &arg))
2114 return NULL;
2115 if (PyTclObject_Check(arg)) {
2116 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2117 int objc;
2118 Tcl_Obj **objv;
2119 int i;
2120 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2121 &objc, &objv) == TCL_ERROR) {
2122 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002123 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002124 if (objc == 0)
2125 return PyString_FromString("");
2126 if (objc == 1)
2127 return FromObj(self, objv[0]);
2128 if (!(v = PyTuple_New(objc)))
2129 return NULL;
2130 for (i = 0; i < objc; i++) {
2131 PyObject *s = FromObj(self, objv[i]);
2132 if (!s || PyTuple_SetItem(v, i, s)) {
2133 Py_DECREF(v);
2134 return NULL;
2135 }
2136 }
2137 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002138 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002139 if (PyTuple_Check(arg))
2140 return SplitObj(arg);
2141
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002142 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2143 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002144 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002145 v = Split(list);
2146 PyMem_Free(list);
2147 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002148}
2149
2150static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002151Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002152{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002153 char *s = Merge(args);
2154 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002155
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002156 if (s) {
2157 res = PyString_FromString(s);
2158 ckfree(s);
2159 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002160
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002161 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002162}
2163
Barry Warsawfa701a81997-01-16 00:15:11 +00002164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002165
Guido van Rossum18468821994-06-20 07:49:28 +00002166/** Tcl Command **/
2167
Guido van Rossum00d93061998-05-28 23:06:38 +00002168/* Client data struct */
2169typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002170 PyObject *self;
2171 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002172} PythonCmd_ClientData;
2173
2174static int
Fred Drake509d79a2000-07-08 04:04:38 +00002175PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002176{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002177 errorInCmd = 1;
2178 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2179 LEAVE_PYTHON
2180 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002181}
2182
Guido van Rossum18468821994-06-20 07:49:28 +00002183/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002184 * function or method.
2185 */
Guido van Rossum18468821994-06-20 07:49:28 +00002186static int
Fred Drake509d79a2000-07-08 04:04:38 +00002187PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002188{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002189 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2190 PyObject *func, *arg, *res;
2191 int i, rv;
2192 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002193
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002194 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002195
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002196 /* TBD: no error checking here since we know, via the
2197 * Tkapp_CreateCommand() that the client data is a two-tuple
2198 */
2199 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002200
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002201 /* Create argument list (argv1, ..., argvN) */
2202 if (!(arg = PyTuple_New(argc - 1)))
2203 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002205 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002206 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002207 if (!s || PyTuple_SetItem(arg, i, s)) {
2208 Py_DECREF(arg);
2209 return PythonCmd_Error(interp);
2210 }
2211 }
2212 res = PyEval_CallObject(func, arg);
2213 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002215 if (res == NULL)
2216 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002217
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002218 obj_res = AsObj(res);
2219 if (obj_res == NULL) {
2220 Py_DECREF(res);
2221 return PythonCmd_Error(interp);
2222 }
2223 else {
2224 Tcl_SetObjResult(interp, obj_res);
2225 rv = TCL_OK;
2226 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002227
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002228 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002229
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002230 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002231
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002232 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002233}
2234
2235static void
Fred Drake509d79a2000-07-08 04:04:38 +00002236PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002237{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002238 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002239
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002240 ENTER_PYTHON
2241 Py_XDECREF(data->self);
2242 Py_XDECREF(data->func);
2243 PyMem_DEL(data);
2244 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002245}
2246
Barry Warsawfa701a81997-01-16 00:15:11 +00002247
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002248
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002249
Guilherme Polo1972d162009-03-27 21:43:08 +00002250#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002251TCL_DECLARE_MUTEX(command_mutex)
2252
2253typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002254 Tcl_Event ev;
2255 Tcl_Interp* interp;
2256 char *name;
2257 int create;
2258 int *status;
2259 ClientData *data;
2260 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002261} CommandEvent;
2262
2263static int
2264Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002265{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002266 if (ev->create)
2267 *ev->status = Tcl_CreateCommand(
2268 ev->interp, ev->name, PythonCmd,
2269 ev->data, PythonCmdDelete) == NULL;
2270 else
2271 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2272 Tcl_MutexLock(&command_mutex);
2273 Tcl_ConditionNotify(ev->done);
2274 Tcl_MutexUnlock(&command_mutex);
2275 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002276}
Guilherme Polo1972d162009-03-27 21:43:08 +00002277#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002278
2279static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002280Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002281{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002282 TkappObject *self = (TkappObject*)selfptr;
2283 PythonCmd_ClientData *data;
2284 char *cmdName;
2285 PyObject *func;
2286 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002287
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002288 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2289 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002290 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002291 if (!PyCallable_Check(func)) {
2292 PyErr_SetString(PyExc_TypeError, "command not callable");
2293 return NULL;
2294 }
Guido van Rossum18468821994-06-20 07:49:28 +00002295
Martin v. Löwisa9656492003-03-30 08:44:58 +00002296#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002297 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2298 !WaitForMainloop(self))
2299 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002300#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002301
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002302 data = PyMem_NEW(PythonCmd_ClientData, 1);
2303 if (!data)
2304 return PyErr_NoMemory();
2305 Py_INCREF(self);
2306 Py_INCREF(func);
2307 data->self = selfptr;
2308 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002309
2310#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002311 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2312 Tcl_Condition cond = NULL;
2313 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2314 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2315 ev->interp = self->interp;
2316 ev->create = 1;
2317 ev->name = cmdName;
2318 ev->data = (ClientData)data;
2319 ev->status = &err;
2320 ev->done = &cond;
2321 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2322 Tcl_ConditionFinalize(&cond);
2323 }
2324 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002325#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002326 {
2327 ENTER_TCL
2328 err = Tcl_CreateCommand(
2329 Tkapp_Interp(self), cmdName, PythonCmd,
2330 (ClientData)data, PythonCmdDelete) == NULL;
2331 LEAVE_TCL
2332 }
2333 if (err) {
2334 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2335 PyMem_DEL(data);
2336 return NULL;
2337 }
Guido van Rossum18468821994-06-20 07:49:28 +00002338
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002339 Py_INCREF(Py_None);
2340 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002341}
2342
Barry Warsawfa701a81997-01-16 00:15:11 +00002343
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002344
Guido van Rossum18468821994-06-20 07:49:28 +00002345static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002346Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002347{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002348 TkappObject *self = (TkappObject*)selfptr;
2349 char *cmdName;
2350 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002351
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002352 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2353 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002354 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002355
2356#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002357 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2358 Tcl_Condition cond = NULL;
2359 CommandEvent *ev;
2360 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2361 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2362 ev->interp = self->interp;
2363 ev->create = 0;
2364 ev->name = cmdName;
2365 ev->status = &err;
2366 ev->done = &cond;
2367 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2368 &command_mutex);
2369 Tcl_ConditionFinalize(&cond);
2370 }
2371 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002372#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002373 {
2374 ENTER_TCL
2375 err = Tcl_DeleteCommand(self->interp, cmdName);
2376 LEAVE_TCL
2377 }
2378 if (err == -1) {
2379 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2380 return NULL;
2381 }
2382 Py_INCREF(Py_None);
2383 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002384}
2385
Barry Warsawfa701a81997-01-16 00:15:11 +00002386
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002387
Guido van Rossum00d93061998-05-28 23:06:38 +00002388#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002389/** File Handler **/
2390
Guido van Rossum00d93061998-05-28 23:06:38 +00002391typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002392 PyObject *func;
2393 PyObject *file;
2394 int id;
2395 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002396} FileHandler_ClientData;
2397
2398static FileHandler_ClientData *HeadFHCD;
2399
2400static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002401NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002402{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002403 FileHandler_ClientData *p;
2404 p = PyMem_NEW(FileHandler_ClientData, 1);
2405 if (p != NULL) {
2406 Py_XINCREF(func);
2407 Py_XINCREF(file);
2408 p->func = func;
2409 p->file = file;
2410 p->id = id;
2411 p->next = HeadFHCD;
2412 HeadFHCD = p;
2413 }
2414 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002415}
2416
2417static void
Fred Drake509d79a2000-07-08 04:04:38 +00002418DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002419{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002420 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002421
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002422 pp = &HeadFHCD;
2423 while ((p = *pp) != NULL) {
2424 if (p->id == id) {
2425 *pp = p->next;
2426 Py_XDECREF(p->func);
2427 Py_XDECREF(p->file);
2428 PyMem_DEL(p);
2429 }
2430 else
2431 pp = &p->next;
2432 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002433}
2434
Guido van Rossuma597dde1995-01-10 20:56:29 +00002435static void
Fred Drake509d79a2000-07-08 04:04:38 +00002436FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002437{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002438 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2439 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002441 ENTER_PYTHON
2442 func = data->func;
2443 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002444
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002445 arg = Py_BuildValue("(Oi)", file, (long) mask);
2446 res = PyEval_CallObject(func, arg);
2447 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002448
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002449 if (res == NULL) {
2450 errorInCmd = 1;
2451 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2452 }
2453 Py_XDECREF(res);
2454 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002455}
2456
Guido van Rossum18468821994-06-20 07:49:28 +00002457static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002458Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2459 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002460{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002461 FileHandler_ClientData *data;
2462 PyObject *file, *func;
2463 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002464
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002465 if (!self && Py_Py3kWarningFlag) {
2466 if (PyErr_Warn(PyExc_DeprecationWarning,
2467 "_tkinter.createfilehandler is gone in 3.x") < 0)
2468 return NULL;
2469 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002470
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002471 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2472 &file, &mask, &func))
2473 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002474
Martin v. Löwisa9656492003-03-30 08:44:58 +00002475#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002476 if (!self && !tcl_lock) {
2477 /* We don't have the Tcl lock since Tcl is threaded. */
2478 PyErr_SetString(PyExc_RuntimeError,
2479 "_tkinter.createfilehandler not supported "
2480 "for threaded Tcl");
2481 return NULL;
2482 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002483#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002484
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002485 if (self) {
2486 CHECK_TCL_APPARTMENT;
2487 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002489 tfile = PyObject_AsFileDescriptor(file);
2490 if (tfile < 0)
2491 return NULL;
2492 if (!PyCallable_Check(func)) {
2493 PyErr_SetString(PyExc_TypeError, "bad argument list");
2494 return NULL;
2495 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002496
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002497 data = NewFHCD(func, file, tfile);
2498 if (data == NULL)
2499 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002500
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002501 /* Ought to check for null Tcl_File object... */
2502 ENTER_TCL
2503 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2504 LEAVE_TCL
2505 Py_INCREF(Py_None);
2506 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002507}
2508
2509static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002510Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002511{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 PyObject *file;
2513 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002514
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002515 if (!self && Py_Py3kWarningFlag) {
2516 if (PyErr_Warn(PyExc_DeprecationWarning,
2517 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2518 return NULL;
2519 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002520
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002521 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2522 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002523
Martin v. Löwisa9656492003-03-30 08:44:58 +00002524#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002525 if (!self && !tcl_lock) {
2526 /* We don't have the Tcl lock since Tcl is threaded. */
2527 PyErr_SetString(PyExc_RuntimeError,
2528 "_tkinter.deletefilehandler not supported "
2529 "for threaded Tcl");
2530 return NULL;
2531 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002532#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002533
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002534 if (self) {
2535 CHECK_TCL_APPARTMENT;
2536 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002537
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002538 tfile = PyObject_AsFileDescriptor(file);
2539 if (tfile < 0)
2540 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002541
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002542 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002543
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002544 /* Ought to check for null Tcl_File object... */
2545 ENTER_TCL
2546 Tcl_DeleteFileHandler(tfile);
2547 LEAVE_TCL
2548 Py_INCREF(Py_None);
2549 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002550}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002551#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002552
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002553
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002554/**** Tktt Object (timer token) ****/
2555
Jeremy Hylton938ace62002-07-17 16:30:39 +00002556static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002557
Guido van Rossum00d93061998-05-28 23:06:38 +00002558typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002559 PyObject_HEAD
2560 Tcl_TimerToken token;
2561 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002562} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002563
2564static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002565Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002566{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002567 TkttObject *v = (TkttObject *)self;
2568 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002569
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002570 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2571 return NULL;
2572 if (v->token != NULL) {
2573 Tcl_DeleteTimerHandler(v->token);
2574 v->token = NULL;
2575 }
2576 if (func != NULL) {
2577 v->func = NULL;
2578 Py_DECREF(func);
2579 Py_DECREF(v); /* See Tktt_New() */
2580 }
2581 Py_INCREF(Py_None);
2582 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002583}
2584
2585static PyMethodDef Tktt_methods[] =
2586{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002587 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2588 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002589};
2590
2591static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002592Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002593{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002594 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002596 v = PyObject_New(TkttObject, &Tktt_Type);
2597 if (v == NULL)
2598 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002599
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002600 Py_INCREF(func);
2601 v->token = NULL;
2602 v->func = func;
2603
2604 /* Extra reference, deleted when called or when handler is deleted */
2605 Py_INCREF(v);
2606 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002607}
2608
2609static void
Fred Drake509d79a2000-07-08 04:04:38 +00002610Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002611{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002612 TkttObject *v = (TkttObject *)self;
2613 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002614
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002615 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002616
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002617 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002618}
2619
Guido van Rossum597ac201998-05-12 14:36:19 +00002620static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002621Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002622{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002623 TkttObject *v = (TkttObject *)self;
2624 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002625
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002626 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2627 v->func == NULL ? ", handler deleted" : "");
2628 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002629}
2630
2631static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002632Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002633{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002634 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002635}
2636
2637static PyTypeObject Tktt_Type =
2638{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002639 PyVarObject_HEAD_INIT(NULL, 0)
2640 "tktimertoken", /*tp_name */
2641 sizeof(TkttObject), /*tp_basicsize */
2642 0, /*tp_itemsize */
2643 Tktt_Dealloc, /*tp_dealloc */
2644 0, /*tp_print */
2645 Tktt_GetAttr, /*tp_getattr */
2646 0, /*tp_setattr */
2647 0, /*tp_compare */
2648 Tktt_Repr, /*tp_repr */
2649 0, /*tp_as_number */
2650 0, /*tp_as_sequence */
2651 0, /*tp_as_mapping */
2652 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002653};
2654
Barry Warsawfa701a81997-01-16 00:15:11 +00002655
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002656
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002657/** Timer Handler **/
2658
2659static void
Fred Drake509d79a2000-07-08 04:04:38 +00002660TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002661{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002662 TkttObject *v = (TkttObject *)clientData;
2663 PyObject *func = v->func;
2664 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002665
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002666 if (func == NULL)
2667 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002668
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002669 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002670
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002671 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002672
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002673 res = PyEval_CallObject(func, NULL);
2674 Py_DECREF(func);
2675 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002676
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002677 if (res == NULL) {
2678 errorInCmd = 1;
2679 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2680 }
2681 else
2682 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002684 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002685}
2686
2687static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002688Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002689{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002690 int milliseconds;
2691 PyObject *func;
2692 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002693
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002694 if (!self && Py_Py3kWarningFlag) {
2695 if (PyErr_Warn(PyExc_DeprecationWarning,
2696 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2697 return NULL;
2698 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002699
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002700 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2701 &milliseconds, &func))
2702 return NULL;
2703 if (!PyCallable_Check(func)) {
2704 PyErr_SetString(PyExc_TypeError, "bad argument list");
2705 return NULL;
2706 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002707
Martin v. Löwisa9656492003-03-30 08:44:58 +00002708#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002709 if (!self && !tcl_lock) {
2710 /* We don't have the Tcl lock since Tcl is threaded. */
2711 PyErr_SetString(PyExc_RuntimeError,
2712 "_tkinter.createtimerhandler not supported "
2713 "for threaded Tcl");
2714 return NULL;
2715 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002716#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002717
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002718 if (self) {
2719 CHECK_TCL_APPARTMENT;
2720 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002721
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002722 v = Tktt_New(func);
2723 if (v) {
2724 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2725 (ClientData)v);
2726 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002727
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002728 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002729}
2730
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002731
Guido van Rossum18468821994-06-20 07:49:28 +00002732/** Event Loop **/
2733
Guido van Rossum18468821994-06-20 07:49:28 +00002734static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002735Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002736{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002737 int threshold = 0;
2738 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002739#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002740 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002741#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002742
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002743 if (!self && Py_Py3kWarningFlag) {
2744 if (PyErr_Warn(PyExc_DeprecationWarning,
2745 "_tkinter.mainloop is gone in 3.x") < 0)
2746 return NULL;
2747 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002748
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002749 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2750 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002751
Martin v. Löwisa9656492003-03-30 08:44:58 +00002752#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002753 if (!self && !tcl_lock) {
2754 /* We don't have the Tcl lock since Tcl is threaded. */
2755 PyErr_SetString(PyExc_RuntimeError,
2756 "_tkinter.mainloop not supported "
2757 "for threaded Tcl");
2758 return NULL;
2759 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002760#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002761
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002762 if (self) {
2763 CHECK_TCL_APPARTMENT;
2764 self->dispatching = 1;
2765 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002766
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002767 quitMainLoop = 0;
2768 while (Tk_GetNumMainWindows() > threshold &&
2769 !quitMainLoop &&
2770 !errorInCmd)
2771 {
2772 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002773
2774#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002775 if (self && self->threaded) {
2776 /* Allow other Python threads to run. */
2777 ENTER_TCL
2778 result = Tcl_DoOneEvent(0);
2779 LEAVE_TCL
2780 }
2781 else {
2782 Py_BEGIN_ALLOW_THREADS
2783 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2784 tcl_tstate = tstate;
2785 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2786 tcl_tstate = NULL;
2787 if(tcl_lock)PyThread_release_lock(tcl_lock);
2788 if (result == 0)
2789 Sleep(Tkinter_busywaitinterval);
2790 Py_END_ALLOW_THREADS
2791 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002792#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002793 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002794#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002795
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002796 if (PyErr_CheckSignals() != 0) {
2797 if (self)
2798 self->dispatching = 0;
2799 return NULL;
2800 }
2801 if (result < 0)
2802 break;
2803 }
2804 if (self)
2805 self->dispatching = 0;
2806 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002807
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002808 if (errorInCmd) {
2809 errorInCmd = 0;
2810 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2811 excInCmd = valInCmd = trbInCmd = NULL;
2812 return NULL;
2813 }
2814 Py_INCREF(Py_None);
2815 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002816}
2817
2818static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002819Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002820{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002821 int flags = 0;
2822 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002823
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002824 if (!self && Py_Py3kWarningFlag) {
2825 if (PyErr_Warn(PyExc_DeprecationWarning,
2826 "_tkinter.dooneevent is gone in 3.x") < 0)
2827 return NULL;
2828 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002829
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002830 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2831 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002832
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002833 ENTER_TCL
2834 rv = Tcl_DoOneEvent(flags);
2835 LEAVE_TCL
2836 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002837}
2838
2839static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002840Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002841{
2842
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002843 if (!self && Py_Py3kWarningFlag) {
2844 if (PyErr_Warn(PyExc_DeprecationWarning,
2845 "_tkinter.quit is gone in 3.x") < 0)
2846 return NULL;
2847 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002848
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002849 if (!PyArg_ParseTuple(args, ":quit"))
2850 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002851
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002852 quitMainLoop = 1;
2853 Py_INCREF(Py_None);
2854 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002855}
2856
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002857static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002858Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002859{
2860
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002861 if (!PyArg_ParseTuple(args, ":interpaddr"))
2862 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002863
Victor Stinner930c3c92013-09-05 00:26:15 +02002864 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002865}
2866
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002867static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002868Tkapp_TkInit(PyObject *self, PyObject *args)
2869{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002870 Tcl_Interp *interp = Tkapp_Interp(self);
2871 const char * _tk_exists = NULL;
2872 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002873
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002874#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002875 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2876 * first call failed.
2877 * To avoid the deadlock, we just refuse the second call through
2878 * a static variable.
2879 */
2880 if (tk_load_failed) {
2881 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2882 return NULL;
2883 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002884#endif
2885
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002886 /* We want to guard against calling Tk_Init() multiple times */
2887 CHECK_TCL_APPARTMENT;
2888 ENTER_TCL
2889 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2890 ENTER_OVERLAP
2891 if (err == TCL_ERROR) {
2892 /* This sets an exception, but we cannot return right
2893 away because we need to exit the overlap first. */
2894 Tkinter_Error(self);
2895 } else {
2896 _tk_exists = Tkapp_Result(self);
2897 }
2898 LEAVE_OVERLAP_TCL
2899 if (err == TCL_ERROR) {
2900 return NULL;
2901 }
2902 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2903 if (Tk_Init(interp) == TCL_ERROR) {
2904 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002905#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002906 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002907#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002908 return NULL;
2909 }
2910 }
2911 Py_INCREF(Py_None);
2912 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002913}
Barry Warsawfa701a81997-01-16 00:15:11 +00002914
Martin v. Löwisffad6332002-11-26 09:28:05 +00002915static PyObject *
2916Tkapp_WantObjects(PyObject *self, PyObject *args)
2917{
2918
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002919 int wantobjects = -1;
2920 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2921 return NULL;
2922 if (wantobjects == -1)
2923 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2924 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002925
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926 Py_INCREF(Py_None);
2927 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002928}
2929
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002930static PyObject *
2931Tkapp_WillDispatch(PyObject *self, PyObject *args)
2932{
2933
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002934 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002935
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002936 Py_INCREF(Py_None);
2937 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002938}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002939
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002940
Guido van Rossum18468821994-06-20 07:49:28 +00002941/**** Tkapp Method List ****/
2942
2943static PyMethodDef Tkapp_methods[] =
2944{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002945 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2946 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2947 {"call", Tkapp_Call, METH_VARARGS},
2948 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2949 {"eval", Tkapp_Eval, METH_VARARGS},
2950 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2951 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2952 {"record", Tkapp_Record, METH_VARARGS},
2953 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2954 {"setvar", Tkapp_SetVar, METH_VARARGS},
2955 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2956 {"getvar", Tkapp_GetVar, METH_VARARGS},
2957 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2958 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2959 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2960 {"getint", Tkapp_GetInt, METH_VARARGS},
2961 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2962 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2963 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2964 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2965 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2966 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2967 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2968 {"split", Tkapp_Split, METH_VARARGS},
2969 {"merge", Tkapp_Merge, METH_VARARGS},
2970 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2971 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002972#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002973 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2974 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002975#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002976 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2977 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2978 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2979 {"quit", Tkapp_Quit, METH_VARARGS},
2980 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2981 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2982 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002983};
2984
Barry Warsawfa701a81997-01-16 00:15:11 +00002985
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002986
Guido van Rossum18468821994-06-20 07:49:28 +00002987/**** Tkapp Type Methods ****/
2988
2989static void
Fred Drake509d79a2000-07-08 04:04:38 +00002990Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002991{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002992 /*CHECK_TCL_APPARTMENT;*/
2993 ENTER_TCL
2994 Tcl_DeleteInterp(Tkapp_Interp(self));
2995 LEAVE_TCL
2996 PyObject_Del(self);
2997 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002998}
2999
3000static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003001Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003002{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003003 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003004}
3005
3006static PyTypeObject Tkapp_Type =
3007{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003008 PyVarObject_HEAD_INIT(NULL, 0)
3009 "tkapp", /*tp_name */
3010 sizeof(TkappObject), /*tp_basicsize */
3011 0, /*tp_itemsize */
3012 Tkapp_Dealloc, /*tp_dealloc */
3013 0, /*tp_print */
3014 Tkapp_GetAttr, /*tp_getattr */
3015 0, /*tp_setattr */
3016 0, /*tp_compare */
3017 0, /*tp_repr */
3018 0, /*tp_as_number */
3019 0, /*tp_as_sequence */
3020 0, /*tp_as_mapping */
3021 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003022};
3023
Barry Warsawfa701a81997-01-16 00:15:11 +00003024
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003025
Guido van Rossum18468821994-06-20 07:49:28 +00003026/**** Tkinter Module ****/
3027
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003028typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003029 PyObject* tuple;
3030 int size; /* current size */
3031 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003032} FlattenContext;
3033
3034static int
3035_bump(FlattenContext* context, int size)
3036{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003037 /* expand tuple to hold (at least) size new items.
3038 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003040 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003042 if (maxsize < context->size + size)
3043 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003044
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003045 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003046
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003047 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003048}
3049
3050static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003051_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003052{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003053 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003054
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003055 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003057 if (depth > 1000) {
3058 PyErr_SetString(PyExc_ValueError,
3059 "nesting too deep in _flatten");
3060 return 0;
3061 } else if (PyList_Check(item)) {
3062 size = PyList_GET_SIZE(item);
3063 /* preallocate (assume no nesting) */
3064 if (context->size + size > context->maxsize &&
3065 !_bump(context, size))
3066 return 0;
3067 /* copy items to output tuple */
3068 for (i = 0; i < size; i++) {
3069 PyObject *o = PyList_GET_ITEM(item, i);
3070 if (PyList_Check(o) || PyTuple_Check(o)) {
3071 if (!_flatten1(context, o, depth + 1))
3072 return 0;
3073 } else if (o != Py_None) {
3074 if (context->size + 1 > context->maxsize &&
3075 !_bump(context, 1))
3076 return 0;
3077 Py_INCREF(o);
3078 PyTuple_SET_ITEM(context->tuple,
3079 context->size++, o);
3080 }
3081 }
3082 } else if (PyTuple_Check(item)) {
3083 /* same, for tuples */
3084 size = PyTuple_GET_SIZE(item);
3085 if (context->size + size > context->maxsize &&
3086 !_bump(context, size))
3087 return 0;
3088 for (i = 0; i < size; i++) {
3089 PyObject *o = PyTuple_GET_ITEM(item, i);
3090 if (PyList_Check(o) || PyTuple_Check(o)) {
3091 if (!_flatten1(context, o, depth + 1))
3092 return 0;
3093 } else if (o != Py_None) {
3094 if (context->size + 1 > context->maxsize &&
3095 !_bump(context, 1))
3096 return 0;
3097 Py_INCREF(o);
3098 PyTuple_SET_ITEM(context->tuple,
3099 context->size++, o);
3100 }
3101 }
3102 } else {
3103 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3104 return 0;
3105 }
3106 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003107}
3108
3109static PyObject *
3110Tkinter_Flatten(PyObject* self, PyObject* args)
3111{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003112 FlattenContext context;
3113 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003115 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3116 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003118 context.maxsize = PySequence_Size(item);
3119 if (context.maxsize < 0)
3120 return NULL;
3121 if (context.maxsize == 0)
3122 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003123
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003124 context.tuple = PyTuple_New(context.maxsize);
3125 if (!context.tuple)
3126 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003127
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003128 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003130 if (!_flatten1(&context, item,0))
3131 return NULL;
3132
3133 if (_PyTuple_Resize(&context.tuple, context.size))
3134 return NULL;
3135
3136 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003137}
3138
Guido van Rossum18468821994-06-20 07:49:28 +00003139static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003140Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003141{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003142 char *screenName = NULL;
3143 char *baseName = NULL;
3144 char *className = NULL;
3145 int interactive = 0;
3146 int wantobjects = 0;
3147 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3148 int sync = 0; /* pass -sync to wish */
3149 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003151 baseName = strrchr(Py_GetProgramName(), '/');
3152 if (baseName != NULL)
3153 baseName++;
3154 else
3155 baseName = Py_GetProgramName();
3156 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003157
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003158 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3159 &screenName, &baseName, &className,
3160 &interactive, &wantobjects, &wantTk,
3161 &sync, &use))
3162 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003163 CHECK_STRING_LENGTH(screenName);
3164 CHECK_STRING_LENGTH(baseName);
3165 CHECK_STRING_LENGTH(className);
3166 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003167
3168 return (PyObject *) Tkapp_New(screenName, baseName, className,
3169 interactive, wantobjects, wantTk,
3170 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003171}
3172
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003173static PyObject *
3174Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3175{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 int new_val;
3177 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3178 return NULL;
3179 if (new_val < 0) {
3180 PyErr_SetString(PyExc_ValueError,
3181 "busywaitinterval must be >= 0");
3182 return NULL;
3183 }
3184 Tkinter_busywaitinterval = new_val;
3185 Py_INCREF(Py_None);
3186 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003187}
3188
3189static char setbusywaitinterval_doc[] =
3190"setbusywaitinterval(n) -> None\n\
3191\n\
3192Set the busy-wait interval in milliseconds between successive\n\
3193calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3194It should be set to a divisor of the maximum time between\n\
3195frames in an animation.";
3196
3197static PyObject *
3198Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3199{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003200 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003201}
3202
3203static char getbusywaitinterval_doc[] =
3204"getbusywaitinterval() -> int\n\
3205\n\
3206Return the current busy-wait interval between successive\n\
3207calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3208
Guido van Rossum18468821994-06-20 07:49:28 +00003209static PyMethodDef moduleMethods[] =
3210{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003211 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3212 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003213#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003214 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3215 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003216#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3218 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3219 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3220 {"quit", Tkapp_Quit, METH_VARARGS},
3221 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3222 setbusywaitinterval_doc},
3223 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3224 METH_NOARGS, getbusywaitinterval_doc},
3225 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003226};
3227
Guido van Rossum7bf15641998-05-22 18:28:17 +00003228#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003229
3230static int stdin_ready = 0;
3231
Guido van Rossumad4db171998-06-13 13:56:28 +00003232#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003233static void
Fred Drake509d79a2000-07-08 04:04:38 +00003234MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003235{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003236 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003237}
Guido van Rossumad4db171998-06-13 13:56:28 +00003238#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003239
Martin v. Löwisa9656492003-03-30 08:44:58 +00003240#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003241static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003242#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003243
Guido van Rossum18468821994-06-20 07:49:28 +00003244static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003245EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003246{
Guido van Rossumad4db171998-06-13 13:56:28 +00003247#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003248 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003249#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003250#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003251 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003252#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003253 stdin_ready = 0;
3254 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003255#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003256 tfile = fileno(stdin);
3257 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003258#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003259 while (!errorInCmd && !stdin_ready) {
3260 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003261#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003262 if (_kbhit()) {
3263 stdin_ready = 1;
3264 break;
3265 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003266#endif
3267#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003268 Py_BEGIN_ALLOW_THREADS
3269 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3270 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003271
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003272 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003273
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003274 tcl_tstate = NULL;
3275 if(tcl_lock)PyThread_release_lock(tcl_lock);
3276 if (result == 0)
3277 Sleep(Tkinter_busywaitinterval);
3278 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003279#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003280 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003281#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003282
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003283 if (result < 0)
3284 break;
3285 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003286#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003287 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003288#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003289 if (errorInCmd) {
3290 errorInCmd = 0;
3291 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3292 excInCmd = valInCmd = trbInCmd = NULL;
3293 PyErr_Print();
3294 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003295#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003296 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003297#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003298 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003299}
Guido van Rossum18468821994-06-20 07:49:28 +00003300
Guido van Rossum00d93061998-05-28 23:06:38 +00003301#endif
3302
Guido van Rossum7bf15641998-05-22 18:28:17 +00003303static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003304EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003305{
Guido van Rossum00d93061998-05-28 23:06:38 +00003306#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003307 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003308#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003309 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003310#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003311 PyOS_InputHook = EventHook;
3312 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003313#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003314}
3315
3316static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003317DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003318{
Guido van Rossum00d93061998-05-28 23:06:38 +00003319#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003320 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3321 PyOS_InputHook = NULL;
3322 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003323#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003324}
3325
Barry Warsawfa701a81997-01-16 00:15:11 +00003326
3327/* all errors will be checked in one fell swoop in init_tkinter() */
3328static void
Fred Drake509d79a2000-07-08 04:04:38 +00003329ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003330{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003331 PyObject *v = PyInt_FromLong(val);
3332 if (v) {
3333 PyDict_SetItemString(d, name, v);
3334 Py_DECREF(v);
3335 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003336}
3337static void
Fred Drake509d79a2000-07-08 04:04:38 +00003338ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003339{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003340 PyObject *v = PyString_FromString(val);
3341 if (v) {
3342 PyDict_SetItemString(d, name, v);
3343 Py_DECREF(v);
3344 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003345}
3346
3347
Mark Hammond62b1ab12002-07-23 06:31:15 +00003348PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003349init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003350{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003351 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003353 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003354
3355#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003356 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003357#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003358
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003359 m = Py_InitModule("_tkinter", moduleMethods);
3360 if (m == NULL)
3361 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003362
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003363 d = PyModule_GetDict(m);
3364 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3365 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003366
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003367 ins_long(d, "READABLE", TCL_READABLE);
3368 ins_long(d, "WRITABLE", TCL_WRITABLE);
3369 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3370 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3371 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3372 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3373 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3374 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3375 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3376 ins_string(d, "TK_VERSION", TK_VERSION);
3377 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003378
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003379 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003381 Py_TYPE(&Tktt_Type) = &PyType_Type;
3382 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003383
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003384 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3385 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003386
3387#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003388 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3389 * start waking up. Note that Tcl_FindExecutable will do this, this
3390 * code must be above it! The original warning from
3391 * tkMacOSXAppInit.c is copied below.
3392 *
3393 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3394 * Tcl interpreter for now. It probably should work to do this
3395 * in the other order, but for now it doesn't seem to.
3396 *
3397 */
3398 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003399#endif
3400
3401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003402 /* This helps the dynamic loader; in Unicode aware Tcl versions
3403 it also helps Tcl find its encodings. */
3404 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003405
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003406 if (PyErr_Occurred())
3407 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003408
Guido van Rossum43ff8681998-07-14 18:02:13 +00003409#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003410 /* This was not a good idea; through <Destroy> bindings,
3411 Tcl_Finalize() may invoke Python code but at that point the
3412 interpreter and thread state have already been destroyed! */
3413 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003414#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003415
Guido van Rossum18468821994-06-20 07:49:28 +00003416}