blob: 8288c961b6d1dd15b5ac890d9500d063d95f90b7 [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);
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300471 if (buf == NULL) {
472 PyErr_NoMemory();
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200473 return NULL;
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300474 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200475 while (s != e) {
476 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
477 *q++ = '\0';
478 s += 2;
479 }
480 else
481 *q++ = *s++;
482 }
483 s = buf;
484 size = q - s;
485 r = PyUnicode_DecodeUTF8(s, size, NULL);
486 PyMem_Free(buf);
487 }
488 }
489 return r;
490}
491#endif
492
493static PyObject *
494fromTclStringAndSize(const char *s, Py_ssize_t size)
495{
496 PyObject *r;
497#ifdef Py_USING_UNICODE
498 Py_ssize_t i;
499 /* If Tcl string contains any bytes with the top bit set,
500 it's UTF-8 and we should decode it to Unicode */
501 for (i = 0; i < size; i++)
502 if (s[i] & 0x80)
503 break;
504 if (i != size) {
505 /* It isn't an ASCII string. */
506 r = unicode_FromTclStringAndSize(s, size);
507 if (r)
508 return r;
509 PyErr_Clear();
510 }
511#endif
512 r = PyString_FromStringAndSize(s, size);
513 return r;
514}
515
516static PyObject *
517fromTclString(const char *s)
518{
519 return fromTclStringAndSize(s, strlen(s));
520}
521
522
Guido van Rossum18468821994-06-20 07:49:28 +0000523static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000524Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000525{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000526 int argc;
527 char **argv;
528 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000529
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000530 if (list == NULL) {
531 Py_INCREF(Py_None);
532 return Py_None;
533 }
Guido van Rossum18468821994-06-20 07:49:28 +0000534
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000535 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
536 /* Not a list.
537 * Could be a quoted string containing funnies, e.g. {"}.
538 * Return the string itself.
539 */
540 return PyString_FromString(list);
541 }
Guido van Rossum18468821994-06-20 07:49:28 +0000542
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000543 if (argc == 0)
544 v = PyString_FromString("");
545 else if (argc == 1)
546 v = PyString_FromString(argv[0]);
547 else if ((v = PyTuple_New(argc)) != NULL) {
548 int i;
549 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000550
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000551 for (i = 0; i < argc; i++) {
552 if ((w = Split(argv[i])) == NULL) {
553 Py_DECREF(v);
554 v = NULL;
555 break;
556 }
557 PyTuple_SetItem(v, i, w);
558 }
559 }
560 Tcl_Free(FREECAST argv);
561 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000562}
563
Martin v. Löwisffad6332002-11-26 09:28:05 +0000564/* In some cases, Tcl will still return strings that are supposed to be
565 lists. SplitObj walks through a nested tuple, finding string objects that
566 need to be split. */
567
Martin v. Löwis111c1802008-06-13 07:47:47 +0000568static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000569SplitObj(PyObject *arg)
570{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000571 if (PyTuple_Check(arg)) {
572 int i, size;
573 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000574
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000575 size = PyTuple_Size(arg);
576 result = NULL;
577 /* Recursively invoke SplitObj for all tuple items.
578 If this does not return a new object, no action is
579 needed. */
580 for(i = 0; i < size; i++) {
581 elem = PyTuple_GetItem(arg, i);
582 newelem = SplitObj(elem);
583 if (!newelem) {
584 Py_XDECREF(result);
585 return NULL;
586 }
587 if (!result) {
588 int k;
589 if (newelem == elem) {
590 Py_DECREF(newelem);
591 continue;
592 }
593 result = PyTuple_New(size);
594 if (!result)
595 return NULL;
596 for(k = 0; k < i; k++) {
597 elem = PyTuple_GetItem(arg, k);
598 Py_INCREF(elem);
599 PyTuple_SetItem(result, k, elem);
600 }
601 }
602 PyTuple_SetItem(result, i, newelem);
603 }
604 if (result)
605 return result;
606 /* Fall through, returning arg. */
607 }
608 else if (PyString_Check(arg)) {
609 int argc;
610 char **argv;
611 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000612
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000613 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
614 Py_INCREF(arg);
615 return arg;
616 }
617 Tcl_Free(FREECAST argv);
618 if (argc > 1)
619 return Split(PyString_AsString(arg));
620 /* Fall through, returning arg. */
621 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300622 else if (PyUnicode_Check(arg)) {
623 int argc;
624 char **argv;
625 char *list;
626 PyObject *s = PyUnicode_AsUTF8String(arg);
627
628 if (s == NULL) {
629 Py_INCREF(arg);
630 return arg;
631 }
632 list = PyString_AsString(s);
633
634 if (list == NULL ||
635 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
636 Py_DECREF(s);
637 Py_INCREF(arg);
638 return arg;
639 }
640 Tcl_Free(FREECAST argv);
641 if (argc > 1) {
642 PyObject *v = Split(list);
643 Py_DECREF(s);
644 return v;
645 }
646 Py_DECREF(s);
647 /* Fall through, returning arg. */
648 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000649 Py_INCREF(arg);
650 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000651}
Barry Warsawfa701a81997-01-16 00:15:11 +0000652
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000653
Guido van Rossum18468821994-06-20 07:49:28 +0000654/**** Tkapp Object ****/
655
656#ifndef WITH_APPINIT
657int
Fred Drake509d79a2000-07-08 04:04:38 +0000658Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000659{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000660 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000661
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000662 if (Tcl_Init(interp) == TCL_ERROR) {
663 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
664 return TCL_ERROR;
665 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000666
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000667 _tkinter_skip_tk_init = Tcl_GetVar(interp,
668 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
669 if (_tkinter_skip_tk_init != NULL &&
670 strcmp(_tkinter_skip_tk_init, "1") == 0) {
671 return TCL_OK;
672 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000673
674#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000675 if (tk_load_failed) {
676 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
677 return TCL_ERROR;
678 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000679#endif
680
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000681 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000682#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000684#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000685 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
686 return TCL_ERROR;
687 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000688
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000689 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000690}
691#endif /* !WITH_APPINIT */
692
Guido van Rossum18468821994-06-20 07:49:28 +0000693
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695
696/* Initialize the Tk application; see the `main' function in
697 * `tkMain.c'.
698 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000699
Thomas Wouters58d05102000-07-24 14:43:35 +0000700static void EnableEventHook(void); /* Forward */
701static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000702
Barry Warsawfa701a81997-01-16 00:15:11 +0000703static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000705 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000706{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000707 TkappObject *v;
708 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000709
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000710 v = PyObject_New(TkappObject, &Tkapp_Type);
711 if (v == NULL)
712 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000713
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000714 v->interp = Tcl_CreateInterp();
715 v->wantobjects = wantobjects;
716 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
717 TCL_GLOBAL_ONLY) != NULL;
718 v->thread_id = Tcl_GetCurrentThread();
719 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000720
721#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000722 if (v->threaded) {
723 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
724 Py_DECREF(v);
725 return 0;
726 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000727#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000728#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000729 if (v->threaded && tcl_lock) {
730 /* If Tcl is threaded, we don't need the lock. */
731 PyThread_free_lock(tcl_lock);
732 tcl_lock = NULL;
733 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000734#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000735
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000736 v->BooleanType = Tcl_GetObjType("boolean");
737 v->ByteArrayType = Tcl_GetObjType("bytearray");
738 v->DoubleType = Tcl_GetObjType("double");
739 v->IntType = Tcl_GetObjType("int");
740 v->ListType = Tcl_GetObjType("list");
741 v->ProcBodyType = Tcl_GetObjType("procbody");
742 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000743
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000744 /* Delete the 'exit' command, which can screw things up */
745 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000746
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000747 if (screenName != NULL)
748 Tcl_SetVar2(v->interp, "env", "DISPLAY",
749 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000750
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000751 if (interactive)
752 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
753 else
754 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000755
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 /* This is used to get the application class for Tk 4.1 and up */
757 argv0 = (char*)ckalloc(strlen(className) + 1);
758 if (!argv0) {
759 PyErr_NoMemory();
760 Py_DECREF(v);
761 return NULL;
762 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000763
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000764 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200765 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
766 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
768 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000769
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000770 if (! wantTk) {
771 Tcl_SetVar(v->interp,
772 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
773 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000774#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000775 else if (tk_load_failed) {
776 Tcl_SetVar(v->interp,
777 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
778 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000779#endif
David Aschere2b4b322004-02-18 05:59:53 +0000780
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000781 /* some initial arguments need to be in argv */
782 if (sync || use) {
783 char *args;
784 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000785
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000786 if (sync)
787 len += sizeof "-sync";
788 if (use)
789 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000790
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000791 args = (char*)ckalloc(len);
792 if (!args) {
793 PyErr_NoMemory();
794 Py_DECREF(v);
795 return NULL;
796 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000797
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000798 args[0] = '\0';
799 if (sync)
800 strcat(args, "-sync");
801 if (use) {
802 if (sync)
803 strcat(args, " ");
804 strcat(args, "-use ");
805 strcat(args, use);
806 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000807
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000808 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
809 ckfree(args);
810 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000811
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000812 if (Tcl_AppInit(v->interp) != TCL_OK) {
813 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000814#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 if (wantTk) {
816 const char *_tkinter_tk_failed;
817 _tkinter_tk_failed = Tcl_GetVar(v->interp,
818 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000819
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000820 if ( _tkinter_tk_failed != NULL &&
821 strcmp(_tkinter_tk_failed, "1") == 0) {
822 tk_load_failed = 1;
823 }
824 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000825#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000826 Py_DECREF((PyObject *)v);
827 return (TkappObject *)result;
828 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000829
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000831
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000832 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000833}
834
Barry Warsawfa701a81997-01-16 00:15:11 +0000835
Guilherme Polo1972d162009-03-27 21:43:08 +0000836#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000837static void
838Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000839 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000840{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000841 Py_BEGIN_ALLOW_THREADS;
842 Tcl_MutexLock(mutex);
843 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
844 Tcl_ThreadAlert(self->thread_id);
845 Tcl_ConditionWait(cond, mutex, NULL);
846 Tcl_MutexUnlock(mutex);
847 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000848}
Guilherme Polo1972d162009-03-27 21:43:08 +0000849#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000850
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000851
Guido van Rossum18468821994-06-20 07:49:28 +0000852/** Tcl Eval **/
853
Martin v. Löwisffad6332002-11-26 09:28:05 +0000854typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000855 PyObject_HEAD
856 Tcl_Obj *value;
857 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858} PyTclObject;
859
860staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000861#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862
863static PyObject *
864newPyTclObject(Tcl_Obj *arg)
865{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000866 PyTclObject *self;
867 self = PyObject_New(PyTclObject, &PyTclObject_Type);
868 if (self == NULL)
869 return NULL;
870 Tcl_IncrRefCount(arg);
871 self->value = arg;
872 self->string = NULL;
873 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874}
875
876static void
877PyTclObject_dealloc(PyTclObject *self)
878{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000879 Tcl_DecrRefCount(self->value);
880 Py_XDECREF(self->string);
881 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000882}
883
884static PyObject *
885PyTclObject_str(PyTclObject *self)
886{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000887 if (self->string && PyString_Check(self->string)) {
888 Py_INCREF(self->string);
889 return self->string;
890 }
891 /* XXX Could cache value if it is an ASCII string. */
892 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893}
894
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000895static char*
896PyTclObject_TclString(PyObject *self)
897{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000898 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000899}
900
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000901/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000902PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000903"the string representation of this object, either as string or Unicode");
904
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000905static PyObject *
906PyTclObject_string(PyTclObject *self, void *ignored)
907{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000908 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200909 int len;
910 char *s = Tcl_GetStringFromObj(self->value, &len);
911 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000912 if (!self->string)
913 return NULL;
914 }
915 Py_INCREF(self->string);
916 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000917}
918
919#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000920PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
921
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000922static PyObject *
923PyTclObject_unicode(PyTclObject *self, void *ignored)
924{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000925 char *s;
926 int len;
927 if (self->string && PyUnicode_Check(self->string)) {
928 Py_INCREF(self->string);
929 return self->string;
930 }
931 /* XXX Could chache result if it is non-ASCII. */
932 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200933 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000934}
935#endif
936
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937static PyObject *
938PyTclObject_repr(PyTclObject *self)
939{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000940 char buf[50];
941 PyOS_snprintf(buf, 50, "<%s object at %p>",
942 self->value->typePtr->name, self->value);
943 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000944}
945
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000946static int
947PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
948{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000949 int res;
950 res = strcmp(Tcl_GetString(self->value),
951 Tcl_GetString(other->value));
952 if (res < 0) return -1;
953 if (res > 0) return 1;
954 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000955}
956
Martin v. Löwis39195712003-01-04 00:33:13 +0000957PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
958
Martin v. Löwisffad6332002-11-26 09:28:05 +0000959static PyObject*
960get_typename(PyTclObject* obj, void* ignored)
961{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000962 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000963}
964
Martin v. Löwis39195712003-01-04 00:33:13 +0000965
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000967 {"typename", (getter)get_typename, NULL, get_typename__doc__},
968 {"string", (getter)PyTclObject_string, NULL,
969 PyTclObject_string__doc__},
970 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971};
972
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000973static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000974#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000975 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
976 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000977#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000978 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000979};
980
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000982 PyObject_HEAD_INIT(NULL)
983 0, /*ob_size*/
984 "_tkinter.Tcl_Obj", /*tp_name*/
985 sizeof(PyTclObject), /*tp_basicsize*/
986 0, /*tp_itemsize*/
987 /* methods */
988 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
989 0, /*tp_print*/
990 0, /*tp_getattr*/
991 0, /*tp_setattr*/
992 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
993 (reprfunc)PyTclObject_repr, /*tp_repr*/
994 0, /*tp_as_number*/
995 0, /*tp_as_sequence*/
996 0, /*tp_as_mapping*/
997 0, /*tp_hash*/
998 0, /*tp_call*/
999 (reprfunc)PyTclObject_str, /*tp_str*/
1000 PyObject_GenericGetAttr,/*tp_getattro*/
1001 0, /*tp_setattro*/
1002 0, /*tp_as_buffer*/
1003 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1004 0, /*tp_doc*/
1005 0, /*tp_traverse*/
1006 0, /*tp_clear*/
1007 0, /*tp_richcompare*/
1008 0, /*tp_weaklistoffset*/
1009 0, /*tp_iter*/
1010 0, /*tp_iternext*/
1011 PyTclObject_methods, /*tp_methods*/
1012 0, /*tp_members*/
1013 PyTclObject_getsetlist, /*tp_getset*/
1014 0, /*tp_base*/
1015 0, /*tp_dict*/
1016 0, /*tp_descr_get*/
1017 0, /*tp_descr_set*/
1018 0, /*tp_dictoffset*/
1019 0, /*tp_init*/
1020 0, /*tp_alloc*/
1021 0, /*tp_new*/
1022 0, /*tp_free*/
1023 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024};
1025
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001026#if PY_SIZE_MAX > INT_MAX
1027#define CHECK_STRING_LENGTH(s) do { \
1028 if (s != NULL && strlen(s) >= INT_MAX) { \
1029 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1030 return NULL; \
1031 } } while(0)
1032#else
1033#define CHECK_STRING_LENGTH(s)
1034#endif
1035
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001036static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001037AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001038{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001039 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001040
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001041 if (PyString_Check(value))
1042 return Tcl_NewStringObj(PyString_AS_STRING(value),
1043 PyString_GET_SIZE(value));
1044 else if (PyBool_Check(value))
1045 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1046 else if (PyInt_Check(value))
1047 return Tcl_NewLongObj(PyInt_AS_LONG(value));
1048 else if (PyFloat_Check(value))
1049 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1050 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001051 Tcl_Obj **argv;
1052 Py_ssize_t size, i;
1053
1054 size = PyTuple_Size(value);
1055 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1056 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1057 return NULL;
1058 }
1059 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001060 if(!argv)
1061 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001062 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001063 argv[i] = AsObj(PyTuple_GetItem(value,i));
1064 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1065 ckfree(FREECAST argv);
1066 return result;
1067 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001068#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001069 else if (PyUnicode_Check(value)) {
1070 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1071 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1072 /* This #ifdef assumes that Tcl uses UCS-2.
1073 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001074#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 Tcl_UniChar *outbuf = NULL;
1076 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001077 size_t allocsize;
1078 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1079 PyErr_SetString(PyExc_OverflowError, "string is too long");
1080 return NULL;
1081 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001082 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1083 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001084 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001085 if (allocsize >= size)
1086 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1087 /* Else overflow occurred, and we take the next exit */
1088 if (!outbuf) {
1089 PyErr_NoMemory();
1090 return NULL;
1091 }
1092 for (i = 0; i < size; i++) {
1093 if (inbuf[i] >= 0x10000) {
1094 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001095 PyErr_Format(Tkinter_TclError,
1096 "character U+%x is above the range "
1097 "(U+0000-U+FFFF) allowed by Tcl",
1098 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001099 ckfree(FREECAST outbuf);
1100 return NULL;
1101 }
1102 outbuf[i] = inbuf[i];
1103 }
1104 result = Tcl_NewUnicodeObj(outbuf, size);
1105 ckfree(FREECAST outbuf);
1106 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001107#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001108 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001109#endif
1110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001111 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001112#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001113 else if(PyTclObject_Check(value)) {
1114 Tcl_Obj *v = ((PyTclObject*)value)->value;
1115 Tcl_IncrRefCount(v);
1116 return v;
1117 }
1118 else {
1119 PyObject *v = PyObject_Str(value);
1120 if (!v)
1121 return 0;
1122 result = AsObj(v);
1123 Py_DECREF(v);
1124 return result;
1125 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001126}
1127
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128static PyObject*
1129FromObj(PyObject* tkapp, Tcl_Obj *value)
1130{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001131 PyObject *result = NULL;
1132 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001133
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001134 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001135 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001136 return result;
1137 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001139 if (value->typePtr == app->BooleanType) {
1140 result = value->internalRep.longValue ? Py_True : Py_False;
1141 Py_INCREF(result);
1142 return result;
1143 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001144
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001145 if (value->typePtr == app->ByteArrayType) {
1146 int size;
1147 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1148 return PyString_FromStringAndSize(data, size);
1149 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001151 if (value->typePtr == app->DoubleType) {
1152 return PyFloat_FromDouble(value->internalRep.doubleValue);
1153 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001155 if (value->typePtr == app->IntType) {
1156 return PyInt_FromLong(value->internalRep.longValue);
1157 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 if (value->typePtr == app->ListType) {
1160 int size;
1161 int i, status;
1162 PyObject *elem;
1163 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001165 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1166 if (status == TCL_ERROR)
1167 return Tkinter_Error(tkapp);
1168 result = PyTuple_New(size);
1169 if (!result)
1170 return NULL;
1171 for (i = 0; i < size; i++) {
1172 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1173 value, i, &tcl_elem);
1174 if (status == TCL_ERROR) {
1175 Py_DECREF(result);
1176 return Tkinter_Error(tkapp);
1177 }
1178 elem = FromObj(tkapp, tcl_elem);
1179 if (!elem) {
1180 Py_DECREF(result);
1181 return NULL;
1182 }
1183 PyTuple_SetItem(result, i, elem);
1184 }
1185 return result;
1186 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001187
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001188 if (value->typePtr == app->ProcBodyType) {
1189 /* fall through: return tcl object. */
1190 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001191
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001192 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001193#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001194#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001195 PyObject *result;
1196 int size;
1197 Tcl_UniChar *input;
1198 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001199
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001200 size = Tcl_GetCharLength(value);
1201 result = PyUnicode_FromUnicode(NULL, size);
1202 if (!result)
1203 return NULL;
1204 input = Tcl_GetUnicode(value);
1205 output = PyUnicode_AS_UNICODE(result);
1206 while (size--)
1207 *output++ = *input++;
1208 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001210 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1211 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001212#endif
1213#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 int size;
1215 char *c;
1216 c = Tcl_GetStringFromObj(value, &size);
1217 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001218#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001221 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001222}
1223
Guilherme Polo1972d162009-03-27 21:43:08 +00001224#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001225/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226TCL_DECLARE_MUTEX(call_mutex)
1227
1228typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001229 Tcl_Event ev; /* Must be first */
1230 TkappObject *self;
1231 PyObject *args;
1232 int flags;
1233 PyObject **res;
1234 PyObject **exc_type, **exc_value, **exc_tb;
1235 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001237#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238
1239void
1240Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001241{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001242 int i;
1243 for (i = 0; i < objc; i++)
1244 Tcl_DecrRefCount(objv[i]);
1245 if (objv != objStore)
1246 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001247}
Guido van Rossum18468821994-06-20 07:49:28 +00001248
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249/* Convert Python objects to Tcl objects. This must happen in the
1250 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001251
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252static Tcl_Obj**
1253Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1254{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001255 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001256 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001257 if (args == NULL)
1258 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001259
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001260 else if (!PyTuple_Check(args)) {
1261 objv[0] = AsObj(args);
1262 if (objv[0] == 0)
1263 goto finally;
1264 objc = 1;
1265 Tcl_IncrRefCount(objv[0]);
1266 }
1267 else {
1268 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001269
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001270 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001271 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1272 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1273 return NULL;
1274 }
1275 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001276 if (objv == NULL) {
1277 PyErr_NoMemory();
1278 objc = 0;
1279 goto finally;
1280 }
1281 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001282
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001283 for (i = 0; i < objc; i++) {
1284 PyObject *v = PyTuple_GetItem(args, i);
1285 if (v == Py_None) {
1286 objc = i;
1287 break;
1288 }
1289 objv[i] = AsObj(v);
1290 if (!objv[i]) {
1291 /* Reset objc, so it attempts to clear
1292 objects only up to i. */
1293 objc = i;
1294 goto finally;
1295 }
1296 Tcl_IncrRefCount(objv[i]);
1297 }
1298 }
1299 *pobjc = objc;
1300 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 Tkapp_CallDeallocArgs(objv, objStore, objc);
1303 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304}
Guido van Rossum212643f1998-04-29 16:22:14 +00001305
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001307
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308static PyObject*
1309Tkapp_CallResult(TkappObject *self)
1310{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001311 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001312 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001313 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001314 /* Not sure whether the IncrRef is necessary, but something
1315 may overwrite the interpreter result while we are
1316 converting it. */
1317 Tcl_IncrRefCount(value);
1318 res = FromObj((PyObject*)self, value);
1319 Tcl_DecrRefCount(value);
1320 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001321 int len;
1322 const char *s = Tcl_GetStringFromObj(value, &len);
1323 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001324 }
1325 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326}
Guido van Rossum632de272000-03-29 00:19:50 +00001327
Guilherme Polo1972d162009-03-27 21:43:08 +00001328#ifdef WITH_THREAD
1329
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330/* Tkapp_CallProc is the event procedure that is executed in the context of
1331 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1332 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001333
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334static int
1335Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1336{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001337 Tcl_Obj *objStore[ARGSZ];
1338 Tcl_Obj **objv;
1339 int objc;
1340 int i;
1341 ENTER_PYTHON
1342 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1343 if (!objv) {
1344 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1345 *(e->res) = NULL;
1346 }
1347 LEAVE_PYTHON
1348 if (!objv)
1349 goto done;
1350 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1351 ENTER_PYTHON
1352 if (i == TCL_ERROR) {
1353 *(e->res) = NULL;
1354 *(e->exc_type) = NULL;
1355 *(e->exc_tb) = NULL;
1356 *(e->exc_value) = PyObject_CallFunction(
1357 Tkinter_TclError, "s",
1358 Tcl_GetStringResult(e->self->interp));
1359 }
1360 else {
1361 *(e->res) = Tkapp_CallResult(e->self);
1362 }
1363 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001364
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001365 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001366done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001367 /* Wake up calling thread. */
1368 Tcl_MutexLock(&call_mutex);
1369 Tcl_ConditionNotify(e->done);
1370 Tcl_MutexUnlock(&call_mutex);
1371 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372}
1373
Guilherme Polo1972d162009-03-27 21:43:08 +00001374#endif
1375
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376/* This is the main entry point for calling a Tcl command.
1377 It supports three cases, with regard to threading:
1378 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1379 the context of the calling thread.
1380 2. Tcl is threaded, caller of the command is in the interpreter thread:
1381 Execute the command in the calling thread. Since the Tcl lock will
1382 not be used, we can merge that with case 1.
1383 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1384 the interpreter thread. Allocation of Tcl objects needs to occur in the
1385 interpreter thread, so we ship the PyObject* args to the target thread,
1386 and perform processing there. */
1387
1388static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001389Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001391 Tcl_Obj *objStore[ARGSZ];
1392 Tcl_Obj **objv = NULL;
1393 int objc, i;
1394 PyObject *res = NULL;
1395 TkappObject *self = (TkappObject*)selfptr;
1396 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001398 /* If args is a single tuple, replace with contents of tuple */
1399 if (1 == PyTuple_Size(args)){
1400 PyObject* item = PyTuple_GetItem(args, 0);
1401 if (PyTuple_Check(item))
1402 args = item;
1403 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001404#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001405 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1406 /* We cannot call the command directly. Instead, we must
1407 marshal the parameters to the interpreter thread. */
1408 Tkapp_CallEvent *ev;
1409 Tcl_Condition cond = NULL;
1410 PyObject *exc_type, *exc_value, *exc_tb;
1411 if (!WaitForMainloop(self))
1412 return NULL;
1413 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1414 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1415 ev->self = self;
1416 ev->args = args;
1417 ev->res = &res;
1418 ev->exc_type = &exc_type;
1419 ev->exc_value = &exc_value;
1420 ev->exc_tb = &exc_tb;
1421 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001422
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001423 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001424
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001425 if (res == NULL) {
1426 if (exc_type)
1427 PyErr_Restore(exc_type, exc_value, exc_tb);
1428 else
1429 PyErr_SetObject(Tkinter_TclError, exc_value);
1430 }
1431 Tcl_ConditionFinalize(&cond);
1432 }
1433 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001434#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001435 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001436
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001437 objv = Tkapp_CallArgs(args, objStore, &objc);
1438 if (!objv)
1439 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001441 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001442
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001443 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001445 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001447 if (i == TCL_ERROR)
1448 Tkinter_Error(selfptr);
1449 else
1450 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001452 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001454 Tkapp_CallDeallocArgs(objv, objStore, objc);
1455 }
1456 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001457}
1458
1459
1460static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001461Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001462{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001463 /* Could do the same here as for Tkapp_Call(), but this is not used
1464 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1465 way for the user to do what all its Global* variants do (save and
1466 reset the scope pointer, call the local version, restore the saved
1467 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001468
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001469 char *cmd;
1470 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001471
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001472 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001474 cmd = Merge(args);
1475 if (cmd) {
1476 int err;
1477 ENTER_TCL
1478 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1479 ENTER_OVERLAP
1480 if (err == TCL_ERROR)
1481 res = Tkinter_Error(self);
1482 else
1483 res = PyString_FromString(Tkapp_Result(self));
1484 LEAVE_OVERLAP_TCL
1485 ckfree(cmd);
1486 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001487
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001488 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001489}
1490
1491static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001492Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001493{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001494 char *script;
1495 PyObject *res = NULL;
1496 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001497
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001498 if (!PyArg_ParseTuple(args, "s:eval", &script))
1499 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001500
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001501 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001502 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001503
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001504 ENTER_TCL
1505 err = Tcl_Eval(Tkapp_Interp(self), script);
1506 ENTER_OVERLAP
1507 if (err == TCL_ERROR)
1508 res = Tkinter_Error(self);
1509 else
1510 res = PyString_FromString(Tkapp_Result(self));
1511 LEAVE_OVERLAP_TCL
1512 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001513}
1514
1515static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001516Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001517{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001518 char *script;
1519 PyObject *res = NULL;
1520 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001521
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001522 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1523 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001524
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001525 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001526
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001527 ENTER_TCL
1528 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1529 ENTER_OVERLAP
1530 if (err == TCL_ERROR)
1531 res = Tkinter_Error(self);
1532 else
1533 res = PyString_FromString(Tkapp_Result(self));
1534 LEAVE_OVERLAP_TCL
1535 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001536}
1537
1538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001539Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001540{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001541 char *fileName;
1542 PyObject *res = NULL;
1543 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001544
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001545 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1546 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001547
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001548 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001550
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001551 ENTER_TCL
1552 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1553 ENTER_OVERLAP
1554 if (err == TCL_ERROR)
1555 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001556
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001557 else
1558 res = PyString_FromString(Tkapp_Result(self));
1559 LEAVE_OVERLAP_TCL
1560 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001561}
1562
1563static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001564Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001565{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001566 char *script;
1567 PyObject *res = NULL;
1568 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001569
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001570 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001571 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001572
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001573 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001574 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001576 ENTER_TCL
1577 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1578 ENTER_OVERLAP
1579 if (err == TCL_ERROR)
1580 res = Tkinter_Error(self);
1581 else
1582 res = PyString_FromString(Tkapp_Result(self));
1583 LEAVE_OVERLAP_TCL
1584 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001585}
1586
1587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001588Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001589{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001590 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001591
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001592 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1593 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001594 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001595 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001597 ENTER_TCL
1598 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1599 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001600
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001601 Py_INCREF(Py_None);
1602 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001603}
1604
Barry Warsawfa701a81997-01-16 00:15:11 +00001605
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001606
Guido van Rossum18468821994-06-20 07:49:28 +00001607/** Tcl Variable **/
1608
Guilherme Polo1972d162009-03-27 21:43:08 +00001609typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1610
1611#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001612TCL_DECLARE_MUTEX(var_mutex)
1613
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001614typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001615 Tcl_Event ev; /* must be first */
1616 PyObject *self;
1617 PyObject *args;
1618 int flags;
1619 EventFunc func;
1620 PyObject **res;
1621 PyObject **exc_type;
1622 PyObject **exc_val;
1623 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001624} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001625#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001626
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001627static int
1628varname_converter(PyObject *in, void *_out)
1629{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001630 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001631 char **out = (char**)_out;
1632 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001633 if (PyString_Size(in) > INT_MAX) {
1634 PyErr_SetString(PyExc_OverflowError, "string is too long");
1635 return 0;
1636 }
1637 s = PyString_AsString(in);
1638 if (strlen(s) != PyString_Size(in)) {
1639 PyErr_SetString(PyExc_ValueError, "null character in string");
1640 return 0;
1641 }
1642 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001643 return 1;
1644 }
1645 if (PyTclObject_Check(in)) {
1646 *out = PyTclObject_TclString(in);
1647 return 1;
1648 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001649 PyErr_Format(PyExc_TypeError,
1650 "must be str or Tcl_Obj, not %.50s",
1651 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001652 return 0;
1653}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001654
Guilherme Polo1972d162009-03-27 21:43:08 +00001655#ifdef WITH_THREAD
1656
Martin v. Löwis111c1802008-06-13 07:47:47 +00001657static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001658var_perform(VarEvent *ev)
1659{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001660 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1661 if (!*(ev->res)) {
1662 PyObject *exc, *val, *tb;
1663 PyErr_Fetch(&exc, &val, &tb);
1664 PyErr_NormalizeException(&exc, &val, &tb);
1665 *(ev->exc_type) = exc;
1666 *(ev->exc_val) = val;
1667 Py_DECREF(tb);
1668 }
1669
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001670}
1671
1672static int
1673var_proc(VarEvent* ev, int flags)
1674{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001675 ENTER_PYTHON
1676 var_perform(ev);
1677 Tcl_MutexLock(&var_mutex);
1678 Tcl_ConditionNotify(ev->cond);
1679 Tcl_MutexUnlock(&var_mutex);
1680 LEAVE_PYTHON
1681 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001682}
1683
Guilherme Polo1972d162009-03-27 21:43:08 +00001684#endif
1685
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001686static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001687var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001688{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001689#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001690 TkappObject *self = (TkappObject*)selfptr;
1691 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1692 TkappObject *self = (TkappObject*)selfptr;
1693 VarEvent *ev;
1694 PyObject *res, *exc_type, *exc_val;
1695 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001696
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001697 /* The current thread is not the interpreter thread. Marshal
1698 the call to the interpreter thread, then wait for
1699 completion. */
1700 if (!WaitForMainloop(self))
1701 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001702
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001703 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1704
1705 ev->self = selfptr;
1706 ev->args = args;
1707 ev->flags = flags;
1708 ev->func = func;
1709 ev->res = &res;
1710 ev->exc_type = &exc_type;
1711 ev->exc_val = &exc_val;
1712 ev->cond = &cond;
1713 ev->ev.proc = (Tcl_EventProc*)var_proc;
1714 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1715 Tcl_ConditionFinalize(&cond);
1716 if (!res) {
1717 PyErr_SetObject(exc_type, exc_val);
1718 Py_DECREF(exc_type);
1719 Py_DECREF(exc_val);
1720 return NULL;
1721 }
1722 return res;
1723 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001724#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001725 /* Tcl is not threaded, or this is the interpreter thread. */
1726 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001727}
1728
Guido van Rossum18468821994-06-20 07:49:28 +00001729static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001730SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001731{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001732 char *name1, *name2;
1733 PyObject *newValue;
1734 PyObject *res = NULL;
1735 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001736
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001737 switch (PyTuple_GET_SIZE(args)) {
1738 case 2:
1739 if (!PyArg_ParseTuple(args, "O&O:setvar",
1740 varname_converter, &name1, &newValue))
1741 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001742 /* XXX Acquire tcl lock??? */
1743 newval = AsObj(newValue);
1744 if (newval == NULL)
1745 return NULL;
1746 ENTER_TCL
1747 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1748 newval, flags);
1749 ENTER_OVERLAP
1750 if (!ok)
1751 Tkinter_Error(self);
1752 else {
1753 res = Py_None;
1754 Py_INCREF(res);
1755 }
1756 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001757 break;
1758 case 3:
1759 if (!PyArg_ParseTuple(args, "ssO:setvar",
1760 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001761 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001762 CHECK_STRING_LENGTH(name1);
1763 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001764 /* XXX must hold tcl lock already??? */
1765 newval = AsObj(newValue);
1766 ENTER_TCL
1767 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1768 ENTER_OVERLAP
1769 if (!ok)
1770 Tkinter_Error(self);
1771 else {
1772 res = Py_None;
1773 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001774 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001775 LEAVE_OVERLAP_TCL
1776 break;
1777 default:
1778 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1779 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001780 }
1781 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001782}
1783
1784static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001785Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001786{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001787 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001788}
1789
1790static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001791Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001792{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001793 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
Barry Warsawfa701a81997-01-16 00:15:11 +00001796
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001797
Guido van Rossum18468821994-06-20 07:49:28 +00001798static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001799GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001800{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001801 char *name1, *name2=NULL;
1802 PyObject *res = NULL;
1803 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001804
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001805 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1806 varname_converter, &name1, &name2))
1807 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001808
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001809 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 ENTER_TCL
1811 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1812 ENTER_OVERLAP
1813 if (tres == NULL) {
1814 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1815 } else {
1816 if (((TkappObject*)self)->wantobjects) {
1817 res = FromObj(self, tres);
1818 }
1819 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001820 int len;
1821 char *s = Tcl_GetStringFromObj(tres, &len);
1822 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001823 }
1824 }
1825 LEAVE_OVERLAP_TCL
1826 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001827}
1828
1829static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001830Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001831{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001832 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001833}
1834
1835static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001836Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001837{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001838 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001839}
1840
Barry Warsawfa701a81997-01-16 00:15:11 +00001841
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001842
Guido van Rossum18468821994-06-20 07:49:28 +00001843static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001844UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001845{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001846 char *name1, *name2=NULL;
1847 int code;
1848 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001849
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001850 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1851 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001852
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001853 CHECK_STRING_LENGTH(name1);
1854 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001855 ENTER_TCL
1856 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1857 ENTER_OVERLAP
1858 if (code == TCL_ERROR)
1859 res = Tkinter_Error(self);
1860 else {
1861 Py_INCREF(Py_None);
1862 res = Py_None;
1863 }
1864 LEAVE_OVERLAP_TCL
1865 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001866}
1867
1868static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001869Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001870{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001871 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001872}
1873
1874static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001875Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001876{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001877 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001878}
1879
Barry Warsawfa701a81997-01-16 00:15:11 +00001880
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001881
Guido van Rossum18468821994-06-20 07:49:28 +00001882/** Tcl to Python **/
1883
1884static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001885Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001886{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001887 char *s;
1888 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001890 if (PyTuple_Size(args) == 1) {
1891 PyObject* o = PyTuple_GetItem(args, 0);
1892 if (PyInt_Check(o)) {
1893 Py_INCREF(o);
1894 return o;
1895 }
1896 }
1897 if (!PyArg_ParseTuple(args, "s:getint", &s))
1898 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001899 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001900 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1901 return Tkinter_Error(self);
1902 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001903}
1904
1905static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001906Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001907{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001908 char *s;
1909 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001910
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001911 if (PyTuple_Size(args) == 1) {
1912 PyObject *o = PyTuple_GetItem(args, 0);
1913 if (PyFloat_Check(o)) {
1914 Py_INCREF(o);
1915 return o;
1916 }
1917 }
1918 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1919 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001920 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001921 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1922 return Tkinter_Error(self);
1923 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001924}
1925
1926static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001927Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001928{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001929 char *s;
1930 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001932 if (PyTuple_Size(args) == 1) {
1933 PyObject *o = PyTuple_GetItem(args, 0);
1934 if (PyInt_Check(o)) {
1935 Py_INCREF(o);
1936 return o;
1937 }
1938 }
1939 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1940 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001941 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001942 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1943 return Tkinter_Error(self);
1944 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001945}
1946
1947static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001948Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001949{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001950 char *s;
1951 PyObject *res = NULL;
1952 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001953
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001954 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1955 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001956
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001957 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001958 CHECK_TCL_APPARTMENT;
1959
1960 ENTER_TCL
1961 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1962 ENTER_OVERLAP
1963 if (retval == TCL_ERROR)
1964 res = Tkinter_Error(self);
1965 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001966 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001967 LEAVE_OVERLAP_TCL
1968 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001969}
1970
1971static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001972Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001973{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001974 char *s;
1975 PyObject *res = NULL;
1976 int retval;
1977 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001978
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001979 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1980 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001981
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001982 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001983 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001984
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001985 ENTER_TCL
1986 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1987 ENTER_OVERLAP
1988 if (retval == TCL_ERROR)
1989 res = Tkinter_Error(self);
1990 else
1991 res = Py_BuildValue("l", v);
1992 LEAVE_OVERLAP_TCL
1993 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001994}
1995
1996static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001997Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001998{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001999 char *s;
2000 PyObject *res = NULL;
2001 double v;
2002 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002003
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002004 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2005 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002006 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002007 CHECK_TCL_APPARTMENT;
2008 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2009 ENTER_TCL
2010 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2011 ENTER_OVERLAP
2012 PyFPE_END_PROTECT(retval)
2013 if (retval == TCL_ERROR)
2014 res = Tkinter_Error(self);
2015 else
2016 res = Py_BuildValue("d", v);
2017 LEAVE_OVERLAP_TCL
2018 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002019}
2020
2021static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002022Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002023{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002024 char *s;
2025 PyObject *res = NULL;
2026 int retval;
2027 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002028
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002029 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2030 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002031 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002032 CHECK_TCL_APPARTMENT;
2033 ENTER_TCL
2034 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2035 ENTER_OVERLAP
2036 if (retval == TCL_ERROR)
2037 res = Tkinter_Error(self);
2038 else
2039 res = Py_BuildValue("i", v);
2040 LEAVE_OVERLAP_TCL
2041 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002042}
2043
Barry Warsawfa701a81997-01-16 00:15:11 +00002044
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002045
Guido van Rossum18468821994-06-20 07:49:28 +00002046static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002047Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002048{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002049 char *list;
2050 int argc;
2051 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002052 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002053 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002054
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002055 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2056 return NULL;
2057 if (PyTclObject_Check(arg)) {
2058 int objc;
2059 Tcl_Obj **objv;
2060 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2061 ((PyTclObject*)arg)->value,
2062 &objc, &objv) == TCL_ERROR) {
2063 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002064 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002065 if (!(v = PyTuple_New(objc)))
2066 return NULL;
2067 for (i = 0; i < objc; i++) {
2068 PyObject *s = FromObj(self, objv[i]);
2069 if (!s || PyTuple_SetItem(v, i, s)) {
2070 Py_DECREF(v);
2071 return NULL;
2072 }
2073 }
2074 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002075 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002076 if (PyTuple_Check(arg)) {
2077 Py_INCREF(arg);
2078 return arg;
2079 }
2080
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002081 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2082 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002083
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002084 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002085 if (Tcl_SplitList(Tkapp_Interp(self), list,
2086 &argc, &argv) == TCL_ERROR) {
2087 PyMem_Free(list);
2088 return Tkinter_Error(self);
2089 }
Guido van Rossum18468821994-06-20 07:49:28 +00002090
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002091 if (!(v = PyTuple_New(argc)))
2092 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094 for (i = 0; i < argc; i++) {
2095 PyObject *s = PyString_FromString(argv[i]);
2096 if (!s || PyTuple_SetItem(v, i, s)) {
2097 Py_DECREF(v);
2098 v = NULL;
2099 goto finally;
2100 }
2101 }
Guido van Rossum18468821994-06-20 07:49:28 +00002102
Barry Warsawfa701a81997-01-16 00:15:11 +00002103 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002104 ckfree(FREECAST argv);
2105 PyMem_Free(list);
2106 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002107}
2108
2109static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002110Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002111{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002112 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002113 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002114
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002115 if (!PyArg_ParseTuple(args, "O:split", &arg))
2116 return NULL;
2117 if (PyTclObject_Check(arg)) {
2118 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2119 int objc;
2120 Tcl_Obj **objv;
2121 int i;
2122 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2123 &objc, &objv) == TCL_ERROR) {
2124 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002125 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002126 if (objc == 0)
2127 return PyString_FromString("");
2128 if (objc == 1)
2129 return FromObj(self, objv[0]);
2130 if (!(v = PyTuple_New(objc)))
2131 return NULL;
2132 for (i = 0; i < objc; i++) {
2133 PyObject *s = FromObj(self, objv[i]);
2134 if (!s || PyTuple_SetItem(v, i, s)) {
2135 Py_DECREF(v);
2136 return NULL;
2137 }
2138 }
2139 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002140 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002141 if (PyTuple_Check(arg))
2142 return SplitObj(arg);
2143
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002144 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2145 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002146 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002147 v = Split(list);
2148 PyMem_Free(list);
2149 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002150}
2151
2152static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002153Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002154{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002155 char *s = Merge(args);
2156 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002157
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002158 if (s) {
2159 res = PyString_FromString(s);
2160 ckfree(s);
2161 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002162
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002163 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002164}
2165
Barry Warsawfa701a81997-01-16 00:15:11 +00002166
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002167
Guido van Rossum18468821994-06-20 07:49:28 +00002168/** Tcl Command **/
2169
Guido van Rossum00d93061998-05-28 23:06:38 +00002170/* Client data struct */
2171typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002172 PyObject *self;
2173 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002174} PythonCmd_ClientData;
2175
2176static int
Fred Drake509d79a2000-07-08 04:04:38 +00002177PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002178{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002179 errorInCmd = 1;
2180 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2181 LEAVE_PYTHON
2182 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002183}
2184
Guido van Rossum18468821994-06-20 07:49:28 +00002185/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002186 * function or method.
2187 */
Guido van Rossum18468821994-06-20 07:49:28 +00002188static int
Fred Drake509d79a2000-07-08 04:04:38 +00002189PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002190{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002191 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2192 PyObject *func, *arg, *res;
2193 int i, rv;
2194 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002195
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002196 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002197
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002198 /* TBD: no error checking here since we know, via the
2199 * Tkapp_CreateCommand() that the client data is a two-tuple
2200 */
2201 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002202
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002203 /* Create argument list (argv1, ..., argvN) */
2204 if (!(arg = PyTuple_New(argc - 1)))
2205 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002206
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002207 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002208 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 if (!s || PyTuple_SetItem(arg, i, s)) {
2210 Py_DECREF(arg);
2211 return PythonCmd_Error(interp);
2212 }
2213 }
2214 res = PyEval_CallObject(func, arg);
2215 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002217 if (res == NULL)
2218 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002219
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002220 obj_res = AsObj(res);
2221 if (obj_res == NULL) {
2222 Py_DECREF(res);
2223 return PythonCmd_Error(interp);
2224 }
2225 else {
2226 Tcl_SetObjResult(interp, obj_res);
2227 rv = TCL_OK;
2228 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002229
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002230 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002231
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002232 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002233
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002234 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002235}
2236
2237static void
Fred Drake509d79a2000-07-08 04:04:38 +00002238PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002239{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002240 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002241
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002242 ENTER_PYTHON
2243 Py_XDECREF(data->self);
2244 Py_XDECREF(data->func);
2245 PyMem_DEL(data);
2246 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002247}
2248
Barry Warsawfa701a81997-01-16 00:15:11 +00002249
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002250
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002251
Guilherme Polo1972d162009-03-27 21:43:08 +00002252#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002253TCL_DECLARE_MUTEX(command_mutex)
2254
2255typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002256 Tcl_Event ev;
2257 Tcl_Interp* interp;
2258 char *name;
2259 int create;
2260 int *status;
2261 ClientData *data;
2262 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002263} CommandEvent;
2264
2265static int
2266Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002267{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002268 if (ev->create)
2269 *ev->status = Tcl_CreateCommand(
2270 ev->interp, ev->name, PythonCmd,
2271 ev->data, PythonCmdDelete) == NULL;
2272 else
2273 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2274 Tcl_MutexLock(&command_mutex);
2275 Tcl_ConditionNotify(ev->done);
2276 Tcl_MutexUnlock(&command_mutex);
2277 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002278}
Guilherme Polo1972d162009-03-27 21:43:08 +00002279#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002280
2281static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002282Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002283{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002284 TkappObject *self = (TkappObject*)selfptr;
2285 PythonCmd_ClientData *data;
2286 char *cmdName;
2287 PyObject *func;
2288 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002289
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002290 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2291 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002292 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002293 if (!PyCallable_Check(func)) {
2294 PyErr_SetString(PyExc_TypeError, "command not callable");
2295 return NULL;
2296 }
Guido van Rossum18468821994-06-20 07:49:28 +00002297
Martin v. Löwisa9656492003-03-30 08:44:58 +00002298#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002299 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2300 !WaitForMainloop(self))
2301 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002302#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002303
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002304 data = PyMem_NEW(PythonCmd_ClientData, 1);
2305 if (!data)
2306 return PyErr_NoMemory();
2307 Py_INCREF(self);
2308 Py_INCREF(func);
2309 data->self = selfptr;
2310 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002311
2312#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002313 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2314 Tcl_Condition cond = NULL;
2315 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2316 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2317 ev->interp = self->interp;
2318 ev->create = 1;
2319 ev->name = cmdName;
2320 ev->data = (ClientData)data;
2321 ev->status = &err;
2322 ev->done = &cond;
2323 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2324 Tcl_ConditionFinalize(&cond);
2325 }
2326 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002327#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002328 {
2329 ENTER_TCL
2330 err = Tcl_CreateCommand(
2331 Tkapp_Interp(self), cmdName, PythonCmd,
2332 (ClientData)data, PythonCmdDelete) == NULL;
2333 LEAVE_TCL
2334 }
2335 if (err) {
2336 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2337 PyMem_DEL(data);
2338 return NULL;
2339 }
Guido van Rossum18468821994-06-20 07:49:28 +00002340
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002341 Py_INCREF(Py_None);
2342 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002343}
2344
Barry Warsawfa701a81997-01-16 00:15:11 +00002345
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002346
Guido van Rossum18468821994-06-20 07:49:28 +00002347static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002348Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002349{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002350 TkappObject *self = (TkappObject*)selfptr;
2351 char *cmdName;
2352 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002353
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002354 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2355 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002356 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002357
2358#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002359 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2360 Tcl_Condition cond = NULL;
2361 CommandEvent *ev;
2362 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2363 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2364 ev->interp = self->interp;
2365 ev->create = 0;
2366 ev->name = cmdName;
2367 ev->status = &err;
2368 ev->done = &cond;
2369 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2370 &command_mutex);
2371 Tcl_ConditionFinalize(&cond);
2372 }
2373 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002374#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002375 {
2376 ENTER_TCL
2377 err = Tcl_DeleteCommand(self->interp, cmdName);
2378 LEAVE_TCL
2379 }
2380 if (err == -1) {
2381 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2382 return NULL;
2383 }
2384 Py_INCREF(Py_None);
2385 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002386}
2387
Barry Warsawfa701a81997-01-16 00:15:11 +00002388
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002389
Guido van Rossum00d93061998-05-28 23:06:38 +00002390#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002391/** File Handler **/
2392
Guido van Rossum00d93061998-05-28 23:06:38 +00002393typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002394 PyObject *func;
2395 PyObject *file;
2396 int id;
2397 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002398} FileHandler_ClientData;
2399
2400static FileHandler_ClientData *HeadFHCD;
2401
2402static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002403NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002404{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002405 FileHandler_ClientData *p;
2406 p = PyMem_NEW(FileHandler_ClientData, 1);
2407 if (p != NULL) {
2408 Py_XINCREF(func);
2409 Py_XINCREF(file);
2410 p->func = func;
2411 p->file = file;
2412 p->id = id;
2413 p->next = HeadFHCD;
2414 HeadFHCD = p;
2415 }
2416 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002417}
2418
2419static void
Fred Drake509d79a2000-07-08 04:04:38 +00002420DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002421{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002422 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002423
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002424 pp = &HeadFHCD;
2425 while ((p = *pp) != NULL) {
2426 if (p->id == id) {
2427 *pp = p->next;
2428 Py_XDECREF(p->func);
2429 Py_XDECREF(p->file);
2430 PyMem_DEL(p);
2431 }
2432 else
2433 pp = &p->next;
2434 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002435}
2436
Guido van Rossuma597dde1995-01-10 20:56:29 +00002437static void
Fred Drake509d79a2000-07-08 04:04:38 +00002438FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002439{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002440 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2441 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002442
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002443 ENTER_PYTHON
2444 func = data->func;
2445 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002446
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002447 arg = Py_BuildValue("(Oi)", file, (long) mask);
2448 res = PyEval_CallObject(func, arg);
2449 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002450
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002451 if (res == NULL) {
2452 errorInCmd = 1;
2453 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2454 }
2455 Py_XDECREF(res);
2456 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002457}
2458
Guido van Rossum18468821994-06-20 07:49:28 +00002459static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002460Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2461 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002462{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002463 FileHandler_ClientData *data;
2464 PyObject *file, *func;
2465 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002466
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002467 if (!self && Py_Py3kWarningFlag) {
2468 if (PyErr_Warn(PyExc_DeprecationWarning,
2469 "_tkinter.createfilehandler is gone in 3.x") < 0)
2470 return NULL;
2471 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002472
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002473 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2474 &file, &mask, &func))
2475 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002476
Martin v. Löwisa9656492003-03-30 08:44:58 +00002477#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002478 if (!self && !tcl_lock) {
2479 /* We don't have the Tcl lock since Tcl is threaded. */
2480 PyErr_SetString(PyExc_RuntimeError,
2481 "_tkinter.createfilehandler not supported "
2482 "for threaded Tcl");
2483 return NULL;
2484 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002485#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002486
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002487 if (self) {
2488 CHECK_TCL_APPARTMENT;
2489 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002491 tfile = PyObject_AsFileDescriptor(file);
2492 if (tfile < 0)
2493 return NULL;
2494 if (!PyCallable_Check(func)) {
2495 PyErr_SetString(PyExc_TypeError, "bad argument list");
2496 return NULL;
2497 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002498
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002499 data = NewFHCD(func, file, tfile);
2500 if (data == NULL)
2501 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002502
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002503 /* Ought to check for null Tcl_File object... */
2504 ENTER_TCL
2505 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2506 LEAVE_TCL
2507 Py_INCREF(Py_None);
2508 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002509}
2510
2511static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002512Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002513{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002514 PyObject *file;
2515 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002516
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002517 if (!self && Py_Py3kWarningFlag) {
2518 if (PyErr_Warn(PyExc_DeprecationWarning,
2519 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2520 return NULL;
2521 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002522
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2524 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002525
Martin v. Löwisa9656492003-03-30 08:44:58 +00002526#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002527 if (!self && !tcl_lock) {
2528 /* We don't have the Tcl lock since Tcl is threaded. */
2529 PyErr_SetString(PyExc_RuntimeError,
2530 "_tkinter.deletefilehandler not supported "
2531 "for threaded Tcl");
2532 return NULL;
2533 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002534#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002535
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002536 if (self) {
2537 CHECK_TCL_APPARTMENT;
2538 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002539
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002540 tfile = PyObject_AsFileDescriptor(file);
2541 if (tfile < 0)
2542 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002543
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002544 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002545
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002546 /* Ought to check for null Tcl_File object... */
2547 ENTER_TCL
2548 Tcl_DeleteFileHandler(tfile);
2549 LEAVE_TCL
2550 Py_INCREF(Py_None);
2551 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002552}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002553#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002554
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002555
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002556/**** Tktt Object (timer token) ****/
2557
Jeremy Hylton938ace62002-07-17 16:30:39 +00002558static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002559
Guido van Rossum00d93061998-05-28 23:06:38 +00002560typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002561 PyObject_HEAD
2562 Tcl_TimerToken token;
2563 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002564} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002565
2566static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002567Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002568{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002569 TkttObject *v = (TkttObject *)self;
2570 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002571
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002572 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2573 return NULL;
2574 if (v->token != NULL) {
2575 Tcl_DeleteTimerHandler(v->token);
2576 v->token = NULL;
2577 }
2578 if (func != NULL) {
2579 v->func = NULL;
2580 Py_DECREF(func);
2581 Py_DECREF(v); /* See Tktt_New() */
2582 }
2583 Py_INCREF(Py_None);
2584 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002585}
2586
2587static PyMethodDef Tktt_methods[] =
2588{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002589 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2590 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002591};
2592
2593static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002594Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002596 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002597
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002598 v = PyObject_New(TkttObject, &Tktt_Type);
2599 if (v == NULL)
2600 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002601
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002602 Py_INCREF(func);
2603 v->token = NULL;
2604 v->func = func;
2605
2606 /* Extra reference, deleted when called or when handler is deleted */
2607 Py_INCREF(v);
2608 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002609}
2610
2611static void
Fred Drake509d79a2000-07-08 04:04:38 +00002612Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002613{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002614 TkttObject *v = (TkttObject *)self;
2615 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002616
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002617 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002618
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002619 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002620}
2621
Guido van Rossum597ac201998-05-12 14:36:19 +00002622static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002623Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002624{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002625 TkttObject *v = (TkttObject *)self;
2626 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002627
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002628 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2629 v->func == NULL ? ", handler deleted" : "");
2630 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002631}
2632
2633static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002634Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002635{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002636 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002637}
2638
2639static PyTypeObject Tktt_Type =
2640{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002641 PyVarObject_HEAD_INIT(NULL, 0)
2642 "tktimertoken", /*tp_name */
2643 sizeof(TkttObject), /*tp_basicsize */
2644 0, /*tp_itemsize */
2645 Tktt_Dealloc, /*tp_dealloc */
2646 0, /*tp_print */
2647 Tktt_GetAttr, /*tp_getattr */
2648 0, /*tp_setattr */
2649 0, /*tp_compare */
2650 Tktt_Repr, /*tp_repr */
2651 0, /*tp_as_number */
2652 0, /*tp_as_sequence */
2653 0, /*tp_as_mapping */
2654 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002655};
2656
Barry Warsawfa701a81997-01-16 00:15:11 +00002657
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002658
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002659/** Timer Handler **/
2660
2661static void
Fred Drake509d79a2000-07-08 04:04:38 +00002662TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002663{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002664 TkttObject *v = (TkttObject *)clientData;
2665 PyObject *func = v->func;
2666 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002667
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002668 if (func == NULL)
2669 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002670
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002671 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002672
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002673 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002674
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002675 res = PyEval_CallObject(func, NULL);
2676 Py_DECREF(func);
2677 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002678
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002679 if (res == NULL) {
2680 errorInCmd = 1;
2681 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2682 }
2683 else
2684 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002685
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002686 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002687}
2688
2689static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002690Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002691{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002692 int milliseconds;
2693 PyObject *func;
2694 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002695
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002696 if (!self && Py_Py3kWarningFlag) {
2697 if (PyErr_Warn(PyExc_DeprecationWarning,
2698 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2699 return NULL;
2700 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002701
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002702 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2703 &milliseconds, &func))
2704 return NULL;
2705 if (!PyCallable_Check(func)) {
2706 PyErr_SetString(PyExc_TypeError, "bad argument list");
2707 return NULL;
2708 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002709
Martin v. Löwisa9656492003-03-30 08:44:58 +00002710#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002711 if (!self && !tcl_lock) {
2712 /* We don't have the Tcl lock since Tcl is threaded. */
2713 PyErr_SetString(PyExc_RuntimeError,
2714 "_tkinter.createtimerhandler not supported "
2715 "for threaded Tcl");
2716 return NULL;
2717 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002718#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002719
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002720 if (self) {
2721 CHECK_TCL_APPARTMENT;
2722 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002723
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002724 v = Tktt_New(func);
2725 if (v) {
2726 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2727 (ClientData)v);
2728 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002729
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002730 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002731}
2732
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002733
Guido van Rossum18468821994-06-20 07:49:28 +00002734/** Event Loop **/
2735
Guido van Rossum18468821994-06-20 07:49:28 +00002736static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002737Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002738{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002739 int threshold = 0;
2740 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002741#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002742 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002743#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002744
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002745 if (!self && Py_Py3kWarningFlag) {
2746 if (PyErr_Warn(PyExc_DeprecationWarning,
2747 "_tkinter.mainloop is gone in 3.x") < 0)
2748 return NULL;
2749 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002750
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002751 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2752 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002753
Martin v. Löwisa9656492003-03-30 08:44:58 +00002754#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002755 if (!self && !tcl_lock) {
2756 /* We don't have the Tcl lock since Tcl is threaded. */
2757 PyErr_SetString(PyExc_RuntimeError,
2758 "_tkinter.mainloop not supported "
2759 "for threaded Tcl");
2760 return NULL;
2761 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002762#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002763
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002764 if (self) {
2765 CHECK_TCL_APPARTMENT;
2766 self->dispatching = 1;
2767 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002768
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002769 quitMainLoop = 0;
2770 while (Tk_GetNumMainWindows() > threshold &&
2771 !quitMainLoop &&
2772 !errorInCmd)
2773 {
2774 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002775
2776#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002777 if (self && self->threaded) {
2778 /* Allow other Python threads to run. */
2779 ENTER_TCL
2780 result = Tcl_DoOneEvent(0);
2781 LEAVE_TCL
2782 }
2783 else {
2784 Py_BEGIN_ALLOW_THREADS
2785 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2786 tcl_tstate = tstate;
2787 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2788 tcl_tstate = NULL;
2789 if(tcl_lock)PyThread_release_lock(tcl_lock);
2790 if (result == 0)
2791 Sleep(Tkinter_busywaitinterval);
2792 Py_END_ALLOW_THREADS
2793 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002794#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002795 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002796#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002797
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002798 if (PyErr_CheckSignals() != 0) {
2799 if (self)
2800 self->dispatching = 0;
2801 return NULL;
2802 }
2803 if (result < 0)
2804 break;
2805 }
2806 if (self)
2807 self->dispatching = 0;
2808 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002809
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002810 if (errorInCmd) {
2811 errorInCmd = 0;
2812 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2813 excInCmd = valInCmd = trbInCmd = NULL;
2814 return NULL;
2815 }
2816 Py_INCREF(Py_None);
2817 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002818}
2819
2820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002821Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002822{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002823 int flags = 0;
2824 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002825
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002826 if (!self && Py_Py3kWarningFlag) {
2827 if (PyErr_Warn(PyExc_DeprecationWarning,
2828 "_tkinter.dooneevent is gone in 3.x") < 0)
2829 return NULL;
2830 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002831
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002832 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2833 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002834
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002835 ENTER_TCL
2836 rv = Tcl_DoOneEvent(flags);
2837 LEAVE_TCL
2838 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002839}
2840
2841static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002842Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002843{
2844
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002845 if (!self && Py_Py3kWarningFlag) {
2846 if (PyErr_Warn(PyExc_DeprecationWarning,
2847 "_tkinter.quit is gone in 3.x") < 0)
2848 return NULL;
2849 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002850
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002851 if (!PyArg_ParseTuple(args, ":quit"))
2852 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002853
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002854 quitMainLoop = 1;
2855 Py_INCREF(Py_None);
2856 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002857}
2858
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002859static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002860Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002861{
2862
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002863 if (!PyArg_ParseTuple(args, ":interpaddr"))
2864 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002865
Victor Stinner930c3c92013-09-05 00:26:15 +02002866 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002867}
2868
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002869static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002870Tkapp_TkInit(PyObject *self, PyObject *args)
2871{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002872 Tcl_Interp *interp = Tkapp_Interp(self);
2873 const char * _tk_exists = NULL;
2874 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002875
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002876#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002877 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2878 * first call failed.
2879 * To avoid the deadlock, we just refuse the second call through
2880 * a static variable.
2881 */
2882 if (tk_load_failed) {
2883 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2884 return NULL;
2885 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002886#endif
2887
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002888 /* We want to guard against calling Tk_Init() multiple times */
2889 CHECK_TCL_APPARTMENT;
2890 ENTER_TCL
2891 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2892 ENTER_OVERLAP
2893 if (err == TCL_ERROR) {
2894 /* This sets an exception, but we cannot return right
2895 away because we need to exit the overlap first. */
2896 Tkinter_Error(self);
2897 } else {
2898 _tk_exists = Tkapp_Result(self);
2899 }
2900 LEAVE_OVERLAP_TCL
2901 if (err == TCL_ERROR) {
2902 return NULL;
2903 }
2904 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2905 if (Tk_Init(interp) == TCL_ERROR) {
2906 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002907#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002908 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002909#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002910 return NULL;
2911 }
2912 }
2913 Py_INCREF(Py_None);
2914 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002915}
Barry Warsawfa701a81997-01-16 00:15:11 +00002916
Martin v. Löwisffad6332002-11-26 09:28:05 +00002917static PyObject *
2918Tkapp_WantObjects(PyObject *self, PyObject *args)
2919{
2920
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002921 int wantobjects = -1;
2922 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2923 return NULL;
2924 if (wantobjects == -1)
2925 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2926 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002927
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002928 Py_INCREF(Py_None);
2929 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002930}
2931
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002932static PyObject *
2933Tkapp_WillDispatch(PyObject *self, PyObject *args)
2934{
2935
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002936 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002937
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002938 Py_INCREF(Py_None);
2939 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002940}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002941
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002942
Guido van Rossum18468821994-06-20 07:49:28 +00002943/**** Tkapp Method List ****/
2944
2945static PyMethodDef Tkapp_methods[] =
2946{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002947 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2948 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2949 {"call", Tkapp_Call, METH_VARARGS},
2950 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2951 {"eval", Tkapp_Eval, METH_VARARGS},
2952 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2953 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2954 {"record", Tkapp_Record, METH_VARARGS},
2955 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2956 {"setvar", Tkapp_SetVar, METH_VARARGS},
2957 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2958 {"getvar", Tkapp_GetVar, METH_VARARGS},
2959 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2960 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2961 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2962 {"getint", Tkapp_GetInt, METH_VARARGS},
2963 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2964 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2965 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2966 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2967 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2968 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2969 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2970 {"split", Tkapp_Split, METH_VARARGS},
2971 {"merge", Tkapp_Merge, METH_VARARGS},
2972 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2973 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002974#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002975 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2976 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002977#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002978 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2979 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2980 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2981 {"quit", Tkapp_Quit, METH_VARARGS},
2982 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2983 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2984 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002985};
2986
Barry Warsawfa701a81997-01-16 00:15:11 +00002987
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002988
Guido van Rossum18468821994-06-20 07:49:28 +00002989/**** Tkapp Type Methods ****/
2990
2991static void
Fred Drake509d79a2000-07-08 04:04:38 +00002992Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002993{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002994 /*CHECK_TCL_APPARTMENT;*/
2995 ENTER_TCL
2996 Tcl_DeleteInterp(Tkapp_Interp(self));
2997 LEAVE_TCL
2998 PyObject_Del(self);
2999 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003000}
3001
3002static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003003Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003004{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003005 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003006}
3007
3008static PyTypeObject Tkapp_Type =
3009{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003010 PyVarObject_HEAD_INIT(NULL, 0)
3011 "tkapp", /*tp_name */
3012 sizeof(TkappObject), /*tp_basicsize */
3013 0, /*tp_itemsize */
3014 Tkapp_Dealloc, /*tp_dealloc */
3015 0, /*tp_print */
3016 Tkapp_GetAttr, /*tp_getattr */
3017 0, /*tp_setattr */
3018 0, /*tp_compare */
3019 0, /*tp_repr */
3020 0, /*tp_as_number */
3021 0, /*tp_as_sequence */
3022 0, /*tp_as_mapping */
3023 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003024};
3025
Barry Warsawfa701a81997-01-16 00:15:11 +00003026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003027
Guido van Rossum18468821994-06-20 07:49:28 +00003028/**** Tkinter Module ****/
3029
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003030typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003031 PyObject* tuple;
3032 int size; /* current size */
3033 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003034} FlattenContext;
3035
3036static int
3037_bump(FlattenContext* context, int size)
3038{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003039 /* expand tuple to hold (at least) size new items.
3040 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003041
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003042 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003043
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003044 if (maxsize < context->size + size)
3045 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003046
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003047 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003048
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003049 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003050}
3051
3052static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003053_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003054{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003055 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003056
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003057 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003058
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003059 if (depth > 1000) {
3060 PyErr_SetString(PyExc_ValueError,
3061 "nesting too deep in _flatten");
3062 return 0;
3063 } else if (PyList_Check(item)) {
3064 size = PyList_GET_SIZE(item);
3065 /* preallocate (assume no nesting) */
3066 if (context->size + size > context->maxsize &&
3067 !_bump(context, size))
3068 return 0;
3069 /* copy items to output tuple */
3070 for (i = 0; i < size; i++) {
3071 PyObject *o = PyList_GET_ITEM(item, i);
3072 if (PyList_Check(o) || PyTuple_Check(o)) {
3073 if (!_flatten1(context, o, depth + 1))
3074 return 0;
3075 } else if (o != Py_None) {
3076 if (context->size + 1 > context->maxsize &&
3077 !_bump(context, 1))
3078 return 0;
3079 Py_INCREF(o);
3080 PyTuple_SET_ITEM(context->tuple,
3081 context->size++, o);
3082 }
3083 }
3084 } else if (PyTuple_Check(item)) {
3085 /* same, for tuples */
3086 size = PyTuple_GET_SIZE(item);
3087 if (context->size + size > context->maxsize &&
3088 !_bump(context, size))
3089 return 0;
3090 for (i = 0; i < size; i++) {
3091 PyObject *o = PyTuple_GET_ITEM(item, i);
3092 if (PyList_Check(o) || PyTuple_Check(o)) {
3093 if (!_flatten1(context, o, depth + 1))
3094 return 0;
3095 } else if (o != Py_None) {
3096 if (context->size + 1 > context->maxsize &&
3097 !_bump(context, 1))
3098 return 0;
3099 Py_INCREF(o);
3100 PyTuple_SET_ITEM(context->tuple,
3101 context->size++, o);
3102 }
3103 }
3104 } else {
3105 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3106 return 0;
3107 }
3108 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003109}
3110
3111static PyObject *
3112Tkinter_Flatten(PyObject* self, PyObject* args)
3113{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003114 FlattenContext context;
3115 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003116
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003117 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3118 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003119
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003120 context.maxsize = PySequence_Size(item);
3121 if (context.maxsize < 0)
3122 return NULL;
3123 if (context.maxsize == 0)
3124 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003125
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003126 context.tuple = PyTuple_New(context.maxsize);
3127 if (!context.tuple)
3128 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003129
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003130 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003131
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003132 if (!_flatten1(&context, item,0))
3133 return NULL;
3134
3135 if (_PyTuple_Resize(&context.tuple, context.size))
3136 return NULL;
3137
3138 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003139}
3140
Guido van Rossum18468821994-06-20 07:49:28 +00003141static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003142Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003143{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003144 char *screenName = NULL;
3145 char *baseName = NULL;
3146 char *className = NULL;
3147 int interactive = 0;
3148 int wantobjects = 0;
3149 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3150 int sync = 0; /* pass -sync to wish */
3151 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003152
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003153 baseName = strrchr(Py_GetProgramName(), '/');
3154 if (baseName != NULL)
3155 baseName++;
3156 else
3157 baseName = Py_GetProgramName();
3158 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003159
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003160 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3161 &screenName, &baseName, &className,
3162 &interactive, &wantobjects, &wantTk,
3163 &sync, &use))
3164 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003165 CHECK_STRING_LENGTH(screenName);
3166 CHECK_STRING_LENGTH(baseName);
3167 CHECK_STRING_LENGTH(className);
3168 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003169
3170 return (PyObject *) Tkapp_New(screenName, baseName, className,
3171 interactive, wantobjects, wantTk,
3172 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003173}
3174
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003175static PyObject *
3176Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3177{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003178 int new_val;
3179 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3180 return NULL;
3181 if (new_val < 0) {
3182 PyErr_SetString(PyExc_ValueError,
3183 "busywaitinterval must be >= 0");
3184 return NULL;
3185 }
3186 Tkinter_busywaitinterval = new_val;
3187 Py_INCREF(Py_None);
3188 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003189}
3190
3191static char setbusywaitinterval_doc[] =
3192"setbusywaitinterval(n) -> None\n\
3193\n\
3194Set the busy-wait interval in milliseconds between successive\n\
3195calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3196It should be set to a divisor of the maximum time between\n\
3197frames in an animation.";
3198
3199static PyObject *
3200Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3201{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003202 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003203}
3204
3205static char getbusywaitinterval_doc[] =
3206"getbusywaitinterval() -> int\n\
3207\n\
3208Return the current busy-wait interval between successive\n\
3209calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3210
Guido van Rossum18468821994-06-20 07:49:28 +00003211static PyMethodDef moduleMethods[] =
3212{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003213 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3214 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003215#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003216 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3217 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003218#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003219 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3220 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3221 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3222 {"quit", Tkapp_Quit, METH_VARARGS},
3223 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3224 setbusywaitinterval_doc},
3225 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3226 METH_NOARGS, getbusywaitinterval_doc},
3227 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003228};
3229
Guido van Rossum7bf15641998-05-22 18:28:17 +00003230#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003231
3232static int stdin_ready = 0;
3233
Guido van Rossumad4db171998-06-13 13:56:28 +00003234#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003235static void
Fred Drake509d79a2000-07-08 04:04:38 +00003236MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003237{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003238 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003239}
Guido van Rossumad4db171998-06-13 13:56:28 +00003240#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003241
Martin v. Löwisa9656492003-03-30 08:44:58 +00003242#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003243static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003244#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003245
Guido van Rossum18468821994-06-20 07:49:28 +00003246static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003247EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003248{
Guido van Rossumad4db171998-06-13 13:56:28 +00003249#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003250 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003251#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003252#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003253 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003254#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003255 stdin_ready = 0;
3256 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003257#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003258 tfile = fileno(stdin);
3259 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003260#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003261 while (!errorInCmd && !stdin_ready) {
3262 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003263#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 if (_kbhit()) {
3265 stdin_ready = 1;
3266 break;
3267 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003268#endif
3269#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003270 Py_BEGIN_ALLOW_THREADS
3271 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3272 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003273
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003274 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003275
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003276 tcl_tstate = NULL;
3277 if(tcl_lock)PyThread_release_lock(tcl_lock);
3278 if (result == 0)
3279 Sleep(Tkinter_busywaitinterval);
3280 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003281#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003282 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003283#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003284
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003285 if (result < 0)
3286 break;
3287 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003288#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003289 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003290#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003291 if (errorInCmd) {
3292 errorInCmd = 0;
3293 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3294 excInCmd = valInCmd = trbInCmd = NULL;
3295 PyErr_Print();
3296 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003297#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003298 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003299#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003300 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003301}
Guido van Rossum18468821994-06-20 07:49:28 +00003302
Guido van Rossum00d93061998-05-28 23:06:38 +00003303#endif
3304
Guido van Rossum7bf15641998-05-22 18:28:17 +00003305static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003306EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003307{
Guido van Rossum00d93061998-05-28 23:06:38 +00003308#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003309 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003310#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003311 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003312#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003313 PyOS_InputHook = EventHook;
3314 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003315#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003316}
3317
3318static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003319DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003320{
Guido van Rossum00d93061998-05-28 23:06:38 +00003321#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003322 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3323 PyOS_InputHook = NULL;
3324 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003325#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003326}
3327
Barry Warsawfa701a81997-01-16 00:15:11 +00003328
3329/* all errors will be checked in one fell swoop in init_tkinter() */
3330static void
Fred Drake509d79a2000-07-08 04:04:38 +00003331ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003332{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 PyObject *v = PyInt_FromLong(val);
3334 if (v) {
3335 PyDict_SetItemString(d, name, v);
3336 Py_DECREF(v);
3337 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003338}
3339static void
Fred Drake509d79a2000-07-08 04:04:38 +00003340ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003341{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003342 PyObject *v = PyString_FromString(val);
3343 if (v) {
3344 PyDict_SetItemString(d, name, v);
3345 Py_DECREF(v);
3346 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003347}
3348
3349
Mark Hammond62b1ab12002-07-23 06:31:15 +00003350PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003351init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003352{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003353 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003354
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003355 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003356
3357#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003358 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003359#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003360
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003361 m = Py_InitModule("_tkinter", moduleMethods);
3362 if (m == NULL)
3363 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003364
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003365 d = PyModule_GetDict(m);
3366 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3367 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003368
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003369 ins_long(d, "READABLE", TCL_READABLE);
3370 ins_long(d, "WRITABLE", TCL_WRITABLE);
3371 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3372 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3373 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3374 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3375 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3376 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3377 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3378 ins_string(d, "TK_VERSION", TK_VERSION);
3379 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003381 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003383 Py_TYPE(&Tktt_Type) = &PyType_Type;
3384 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003385
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003386 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3387 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003388
3389#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003390 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3391 * start waking up. Note that Tcl_FindExecutable will do this, this
3392 * code must be above it! The original warning from
3393 * tkMacOSXAppInit.c is copied below.
3394 *
3395 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3396 * Tcl interpreter for now. It probably should work to do this
3397 * in the other order, but for now it doesn't seem to.
3398 *
3399 */
3400 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003401#endif
3402
3403
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003404 /* This helps the dynamic loader; in Unicode aware Tcl versions
3405 it also helps Tcl find its encodings. */
3406 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003407
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003408 if (PyErr_Occurred())
3409 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003410
Guido van Rossum43ff8681998-07-14 18:02:13 +00003411#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003412 /* This was not a good idea; through <Destroy> bindings,
3413 Tcl_Finalize() may invoke Python code but at that point the
3414 interpreter and thread state have already been destroyed! */
3415 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003416#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003417
Guido van Rossum18468821994-06-20 07:49:28 +00003418}