blob: aed42ac3e4ba7a0588ed1f5ea035a82f302f875b [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
Martin v. Löwis71e25a02002-10-01 18:08:06 +000050/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55#define USE_COMPAT_CONST
56
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000057/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60#define TCL_THREADS
61
Jack Jansencb852442001-12-09 23:15:56 +000062#ifdef TK_FRAMEWORK
63#include <Tcl/tcl.h>
64#include <Tk/tk.h>
65#else
Guido van Rossum18468821994-06-20 07:49:28 +000066#include <tcl.h>
67#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000068#endif
Guido van Rossum18468821994-06-20 07:49:28 +000069
Guilherme Polo5d64c332009-04-05 02:11:19 +000070#include "tkinter.h"
71
Jason Tishlerbbe89612002-12-31 20:30:46 +000072/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000073#ifndef CONST84_RETURN
74#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000075#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000076#define CONST
77#endif
78
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000079#if TK_VERSION_HEX < 0x08030102
80#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000081#endif
82
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000083/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000086 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000088 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
90*/
91#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000092#error "unsupported Tcl configuration"
93#endif
94
Jack Janseneddc1442003-11-20 01:44:59 +000095#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000096#define HAVE_CREATEFILEHANDLER
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099#ifdef HAVE_CREATEFILEHANDLER
100
Neal Norwitzd948a432006-01-08 01:08:55 +0000101/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103#ifndef TCL_UNIX_FD
104# ifdef TCL_WIN_SOCKET
105# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106# else
107# define TCL_UNIX_FD 1
108# endif
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
115
Guido van Rossum7bf15641998-05-22 18:28:17 +0000116#ifdef MS_WINDOWS
117#define FHANDLETYPE TCL_WIN_SOCKET
118#else
119#define FHANDLETYPE TCL_UNIX_FD
120#endif
121
Guido van Rossum00d93061998-05-28 23:06:38 +0000122/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
124
125#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#define WAIT_FOR_STDIN
127#endif
128
Guido van Rossum00d93061998-05-28 23:06:38 +0000129#endif /* HAVE_CREATEFILEHANDLER */
130
Guido van Rossumad4db171998-06-13 13:56:28 +0000131#ifdef MS_WINDOWS
132#include <conio.h>
133#define WAIT_FOR_STDIN
134#endif
135
Guido van Rossum00d93061998-05-28 23:06:38 +0000136#ifdef WITH_THREAD
137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000138/* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
143
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
147
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000152 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000153 released and the lock for Tcl has been acquired.
154
Guido van Rossum5e977831998-06-15 14:03:52 +0000155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
161
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000170
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
173
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
182
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
186
Guido van Rossum00d93061998-05-28 23:06:38 +0000187*/
188
Guido van Rossum65d5b571998-12-21 19:32:43 +0000189static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000190
191#ifdef TCL_THREADS
192static Tcl_ThreadDataKey state_key;
193typedef PyThreadState *ThreadSpecificData;
194#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000196static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000197#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
199#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000205
Guido van Rossum62320c91998-06-15 04:36:09 +0000206#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000207 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000208
209#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000211
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000212#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
216#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000219
220#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
225 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000226
227#else
228
229#define ENTER_TCL
230#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000231#define ENTER_OVERLAP
232#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000233#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000234#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000235#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#endif
238
Guido van Rossum97867b21996-08-08 19:09:53 +0000239#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000240#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000241#endif
242
Guido van Rossum18468821994-06-20 07:49:28 +0000243/**** Tkapp Object Declaration ****/
244
Jeremy Hylton938ace62002-07-17 16:30:39 +0000245static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000246
Guido van Rossum00d93061998-05-28 23:06:38 +0000247typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000263} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Christian Heimese93237d2007-12-19 02:37:44 +0000265#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000266#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000267#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Guido van Rossum35d43371997-08-02 00:09:09 +0000269#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000270(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Error Handling ****/
275
276static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000277static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000278static int errorInCmd = 0;
279static PyObject *excInCmd;
280static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000281static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000282
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000283#ifdef TKINTER_PROTECT_LOADTK
284static int tk_load_failed;
285#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000286
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000287
Guido van Rossum18468821994-06-20 07:49:28 +0000288static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000289Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000290{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000293}
294
Barry Warsawfa701a81997-01-16 00:15:11 +0000295
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000296
Guido van Rossum18468821994-06-20 07:49:28 +0000297/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000298
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000299static int Tkinter_busywaitinterval = 20;
300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000302#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000303
Guido van Rossum00d93061998-05-28 23:06:38 +0000304/* Millisecond sleep() for Unix platforms. */
305
306static void
Fred Drake509d79a2000-07-08 04:04:38 +0000307Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000308{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
311 t.tv_sec = milli/1000;
312 t.tv_usec = (milli%1000) * 1000;
313 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000314}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000315#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000316
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000317/* Wait up to 1s for the mainloop to come up. */
318
319static int
320WaitForMainloop(TkappObject* self)
321{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
329 }
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000334}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000335#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000336
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000337
Guido van Rossum18468821994-06-20 07:49:28 +0000338static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000339AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000340{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341 if (PyString_Check(value))
342 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000343#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000344 else if (PyUnicode_Check(value)) {
345 PyObject *v = PyUnicode_AsUTF8String(value);
346 if (v == NULL)
347 return NULL;
348 if (PyList_Append(tmp, v) != 0) {
349 Py_DECREF(v);
350 return NULL;
351 }
352 Py_DECREF(v);
353 return PyString_AsString(v);
354 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000355#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 else {
357 PyObject *v = PyObject_Str(value);
358 if (v == NULL)
359 return NULL;
360 if (PyList_Append(tmp, v) != 0) {
361 Py_DECREF(v);
362 return NULL;
363 }
364 Py_DECREF(v);
365 return PyString_AsString(v);
366 }
Guido van Rossum18468821994-06-20 07:49:28 +0000367}
368
Barry Warsawfa701a81997-01-16 00:15:11 +0000369
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000370
Guido van Rossum18468821994-06-20 07:49:28 +0000371#define ARGSZ 64
372
373static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000374Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000375{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000376 PyObject *tmp = NULL;
377 char *argvStore[ARGSZ];
378 char **argv = NULL;
379 int fvStore[ARGSZ];
380 int *fv = NULL;
381 int argc = 0, fvc = 0, i;
382 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000383
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000384 if (!(tmp = PyList_New(0)))
385 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000386
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000387 argv = argvStore;
388 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000389
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000390 if (args == NULL)
391 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000392
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000393 else if (!PyTuple_Check(args)) {
394 argc = 1;
395 fv[0] = 0;
396 if (!(argv[0] = AsString(args, tmp)))
397 goto finally;
398 }
399 else {
400 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000401
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000402 if (argc > ARGSZ) {
403 argv = (char **)ckalloc(argc * sizeof(char *));
404 fv = (int *)ckalloc(argc * sizeof(int));
405 if (argv == NULL || fv == NULL) {
406 PyErr_NoMemory();
407 goto finally;
408 }
409 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000410
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000411 for (i = 0; i < argc; i++) {
412 PyObject *v = PyTuple_GetItem(args, i);
413 if (PyTuple_Check(v)) {
414 fv[i] = 1;
415 if (!(argv[i] = Merge(v)))
416 goto finally;
417 fvc++;
418 }
419 else if (v == Py_None) {
420 argc = i;
421 break;
422 }
423 else {
424 fv[i] = 0;
425 if (!(argv[i] = AsString(v, tmp)))
426 goto finally;
427 fvc++;
428 }
429 }
430 }
431 res = Tcl_Merge(argc, argv);
432 if (res == NULL)
433 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000434
Barry Warsawfa701a81997-01-16 00:15:11 +0000435 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000436 for (i = 0; i < fvc; i++)
437 if (fv[i]) {
438 ckfree(argv[i]);
439 }
440 if (argv != argvStore)
441 ckfree(FREECAST argv);
442 if (fv != fvStore)
443 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000444
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000445 Py_DECREF(tmp);
446 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000447}
448
Barry Warsawfa701a81997-01-16 00:15:11 +0000449
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000450
Guido van Rossum18468821994-06-20 07:49:28 +0000451static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000452Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 int argc;
455 char **argv;
456 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458 if (list == NULL) {
459 Py_INCREF(Py_None);
460 return Py_None;
461 }
Guido van Rossum18468821994-06-20 07:49:28 +0000462
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000463 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
464 /* Not a list.
465 * Could be a quoted string containing funnies, e.g. {"}.
466 * Return the string itself.
467 */
468 return PyString_FromString(list);
469 }
Guido van Rossum18468821994-06-20 07:49:28 +0000470
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 if (argc == 0)
472 v = PyString_FromString("");
473 else if (argc == 1)
474 v = PyString_FromString(argv[0]);
475 else if ((v = PyTuple_New(argc)) != NULL) {
476 int i;
477 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 for (i = 0; i < argc; i++) {
480 if ((w = Split(argv[i])) == NULL) {
481 Py_DECREF(v);
482 v = NULL;
483 break;
484 }
485 PyTuple_SetItem(v, i, w);
486 }
487 }
488 Tcl_Free(FREECAST argv);
489 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000490}
491
Martin v. Löwisffad6332002-11-26 09:28:05 +0000492/* In some cases, Tcl will still return strings that are supposed to be
493 lists. SplitObj walks through a nested tuple, finding string objects that
494 need to be split. */
495
Martin v. Löwis111c1802008-06-13 07:47:47 +0000496static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000497SplitObj(PyObject *arg)
498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000499 if (PyTuple_Check(arg)) {
500 int i, size;
501 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000502
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000503 size = PyTuple_Size(arg);
504 result = NULL;
505 /* Recursively invoke SplitObj for all tuple items.
506 If this does not return a new object, no action is
507 needed. */
508 for(i = 0; i < size; i++) {
509 elem = PyTuple_GetItem(arg, i);
510 newelem = SplitObj(elem);
511 if (!newelem) {
512 Py_XDECREF(result);
513 return NULL;
514 }
515 if (!result) {
516 int k;
517 if (newelem == elem) {
518 Py_DECREF(newelem);
519 continue;
520 }
521 result = PyTuple_New(size);
522 if (!result)
523 return NULL;
524 for(k = 0; k < i; k++) {
525 elem = PyTuple_GetItem(arg, k);
526 Py_INCREF(elem);
527 PyTuple_SetItem(result, k, elem);
528 }
529 }
530 PyTuple_SetItem(result, i, newelem);
531 }
532 if (result)
533 return result;
534 /* Fall through, returning arg. */
535 }
536 else if (PyString_Check(arg)) {
537 int argc;
538 char **argv;
539 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000540
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000541 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
542 Py_INCREF(arg);
543 return arg;
544 }
545 Tcl_Free(FREECAST argv);
546 if (argc > 1)
547 return Split(PyString_AsString(arg));
548 /* Fall through, returning arg. */
549 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300550 else if (PyUnicode_Check(arg)) {
551 int argc;
552 char **argv;
553 char *list;
554 PyObject *s = PyUnicode_AsUTF8String(arg);
555
556 if (s == NULL) {
557 Py_INCREF(arg);
558 return arg;
559 }
560 list = PyString_AsString(s);
561
562 if (list == NULL ||
563 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
564 Py_DECREF(s);
565 Py_INCREF(arg);
566 return arg;
567 }
568 Tcl_Free(FREECAST argv);
569 if (argc > 1) {
570 PyObject *v = Split(list);
571 Py_DECREF(s);
572 return v;
573 }
574 Py_DECREF(s);
575 /* Fall through, returning arg. */
576 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000577 Py_INCREF(arg);
578 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000579}
Barry Warsawfa701a81997-01-16 00:15:11 +0000580
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000581
Guido van Rossum18468821994-06-20 07:49:28 +0000582/**** Tkapp Object ****/
583
584#ifndef WITH_APPINIT
585int
Fred Drake509d79a2000-07-08 04:04:38 +0000586Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000587{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000588 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000589
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000590 if (Tcl_Init(interp) == TCL_ERROR) {
591 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
592 return TCL_ERROR;
593 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000594
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000595 _tkinter_skip_tk_init = Tcl_GetVar(interp,
596 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
597 if (_tkinter_skip_tk_init != NULL &&
598 strcmp(_tkinter_skip_tk_init, "1") == 0) {
599 return TCL_OK;
600 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000601
602#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000603 if (tk_load_failed) {
604 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
605 return TCL_ERROR;
606 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000607#endif
608
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000609 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000610#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000612#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000613 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
614 return TCL_ERROR;
615 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000616
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000617 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000618}
619#endif /* !WITH_APPINIT */
620
Guido van Rossum18468821994-06-20 07:49:28 +0000621
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000622
Barry Warsawfa701a81997-01-16 00:15:11 +0000623
624/* Initialize the Tk application; see the `main' function in
625 * `tkMain.c'.
626 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000627
Thomas Wouters58d05102000-07-24 14:43:35 +0000628static void EnableEventHook(void); /* Forward */
629static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000630
Barry Warsawfa701a81997-01-16 00:15:11 +0000631static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000632Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000633 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000634{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000635 TkappObject *v;
636 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000637
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000638 v = PyObject_New(TkappObject, &Tkapp_Type);
639 if (v == NULL)
640 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000641
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000642 v->interp = Tcl_CreateInterp();
643 v->wantobjects = wantobjects;
644 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
645 TCL_GLOBAL_ONLY) != NULL;
646 v->thread_id = Tcl_GetCurrentThread();
647 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000648
649#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000650 if (v->threaded) {
651 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
652 Py_DECREF(v);
653 return 0;
654 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000655#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000656#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000657 if (v->threaded && tcl_lock) {
658 /* If Tcl is threaded, we don't need the lock. */
659 PyThread_free_lock(tcl_lock);
660 tcl_lock = NULL;
661 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000662#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000663
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000664 v->BooleanType = Tcl_GetObjType("boolean");
665 v->ByteArrayType = Tcl_GetObjType("bytearray");
666 v->DoubleType = Tcl_GetObjType("double");
667 v->IntType = Tcl_GetObjType("int");
668 v->ListType = Tcl_GetObjType("list");
669 v->ProcBodyType = Tcl_GetObjType("procbody");
670 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000671
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000672 /* Delete the 'exit' command, which can screw things up */
673 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000674
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000675 if (screenName != NULL)
676 Tcl_SetVar2(v->interp, "env", "DISPLAY",
677 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000678
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000679 if (interactive)
680 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
681 else
682 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000683
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000684 /* This is used to get the application class for Tk 4.1 and up */
685 argv0 = (char*)ckalloc(strlen(className) + 1);
686 if (!argv0) {
687 PyErr_NoMemory();
688 Py_DECREF(v);
689 return NULL;
690 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000691
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200693 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
694 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000695 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
696 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000697
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000698 if (! wantTk) {
699 Tcl_SetVar(v->interp,
700 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
701 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000702#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000703 else if (tk_load_failed) {
704 Tcl_SetVar(v->interp,
705 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
706 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000707#endif
David Aschere2b4b322004-02-18 05:59:53 +0000708
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000709 /* some initial arguments need to be in argv */
710 if (sync || use) {
711 char *args;
712 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000713
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000714 if (sync)
715 len += sizeof "-sync";
716 if (use)
717 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000718
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000719 args = (char*)ckalloc(len);
720 if (!args) {
721 PyErr_NoMemory();
722 Py_DECREF(v);
723 return NULL;
724 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000725
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000726 args[0] = '\0';
727 if (sync)
728 strcat(args, "-sync");
729 if (use) {
730 if (sync)
731 strcat(args, " ");
732 strcat(args, "-use ");
733 strcat(args, use);
734 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000735
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000736 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
737 ckfree(args);
738 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000739
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000740 if (Tcl_AppInit(v->interp) != TCL_OK) {
741 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000742#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000743 if (wantTk) {
744 const char *_tkinter_tk_failed;
745 _tkinter_tk_failed = Tcl_GetVar(v->interp,
746 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000747
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000748 if ( _tkinter_tk_failed != NULL &&
749 strcmp(_tkinter_tk_failed, "1") == 0) {
750 tk_load_failed = 1;
751 }
752 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000753#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000754 Py_DECREF((PyObject *)v);
755 return (TkappObject *)result;
756 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000757
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000758 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000759
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000760 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000761}
762
Barry Warsawfa701a81997-01-16 00:15:11 +0000763
Guilherme Polo1972d162009-03-27 21:43:08 +0000764#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000765static void
766Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000768{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000769 Py_BEGIN_ALLOW_THREADS;
770 Tcl_MutexLock(mutex);
771 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
772 Tcl_ThreadAlert(self->thread_id);
773 Tcl_ConditionWait(cond, mutex, NULL);
774 Tcl_MutexUnlock(mutex);
775 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000776}
Guilherme Polo1972d162009-03-27 21:43:08 +0000777#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000778
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000779
Guido van Rossum18468821994-06-20 07:49:28 +0000780/** Tcl Eval **/
781
Martin v. Löwisffad6332002-11-26 09:28:05 +0000782typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000783 PyObject_HEAD
784 Tcl_Obj *value;
785 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000786} PyTclObject;
787
788staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000789#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000790
791static PyObject *
792newPyTclObject(Tcl_Obj *arg)
793{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000794 PyTclObject *self;
795 self = PyObject_New(PyTclObject, &PyTclObject_Type);
796 if (self == NULL)
797 return NULL;
798 Tcl_IncrRefCount(arg);
799 self->value = arg;
800 self->string = NULL;
801 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000802}
803
804static void
805PyTclObject_dealloc(PyTclObject *self)
806{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000807 Tcl_DecrRefCount(self->value);
808 Py_XDECREF(self->string);
809 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000810}
811
812static PyObject *
813PyTclObject_str(PyTclObject *self)
814{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 if (self->string && PyString_Check(self->string)) {
816 Py_INCREF(self->string);
817 return self->string;
818 }
819 /* XXX Could cache value if it is an ASCII string. */
820 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000821}
822
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000823static char*
824PyTclObject_TclString(PyObject *self)
825{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000826 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000827}
828
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000829/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000831"the string representation of this object, either as string or Unicode");
832
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000833static PyObject *
834PyTclObject_string(PyTclObject *self, void *ignored)
835{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000836 char *s;
837 int i, len;
838 if (!self->string) {
839 s = Tcl_GetStringFromObj(self->value, &len);
840 for (i = 0; i < len; i++)
841 if (s[i] & 0x80)
842 break;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000843#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000844 if (i == len)
845 /* It is an ASCII string. */
846 self->string = PyString_FromStringAndSize(s, len);
847 else {
848 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
849 if (!self->string) {
850 PyErr_Clear();
851 self->string = PyString_FromStringAndSize(s, len);
852 }
853 }
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000854#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000855 self->string = PyString_FromStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000856#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000857 if (!self->string)
858 return NULL;
859 }
860 Py_INCREF(self->string);
861 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000862}
863
864#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000865PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
866
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000867static PyObject *
868PyTclObject_unicode(PyTclObject *self, void *ignored)
869{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000870 char *s;
871 int len;
872 if (self->string && PyUnicode_Check(self->string)) {
873 Py_INCREF(self->string);
874 return self->string;
875 }
876 /* XXX Could chache result if it is non-ASCII. */
877 s = Tcl_GetStringFromObj(self->value, &len);
878 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000879}
880#endif
881
Martin v. Löwisffad6332002-11-26 09:28:05 +0000882static PyObject *
883PyTclObject_repr(PyTclObject *self)
884{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000885 char buf[50];
886 PyOS_snprintf(buf, 50, "<%s object at %p>",
887 self->value->typePtr->name, self->value);
888 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000889}
890
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000891static int
892PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
893{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000894 int res;
895 res = strcmp(Tcl_GetString(self->value),
896 Tcl_GetString(other->value));
897 if (res < 0) return -1;
898 if (res > 0) return 1;
899 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000900}
901
Martin v. Löwis39195712003-01-04 00:33:13 +0000902PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
903
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904static PyObject*
905get_typename(PyTclObject* obj, void* ignored)
906{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000907 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000908}
909
Martin v. Löwis39195712003-01-04 00:33:13 +0000910
Martin v. Löwisffad6332002-11-26 09:28:05 +0000911static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000912 {"typename", (getter)get_typename, NULL, get_typename__doc__},
913 {"string", (getter)PyTclObject_string, NULL,
914 PyTclObject_string__doc__},
915 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916};
917
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000918static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000919#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000920 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
921 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000922#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000923 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000924};
925
Martin v. Löwisffad6332002-11-26 09:28:05 +0000926statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000927 PyObject_HEAD_INIT(NULL)
928 0, /*ob_size*/
929 "_tkinter.Tcl_Obj", /*tp_name*/
930 sizeof(PyTclObject), /*tp_basicsize*/
931 0, /*tp_itemsize*/
932 /* methods */
933 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
934 0, /*tp_print*/
935 0, /*tp_getattr*/
936 0, /*tp_setattr*/
937 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
938 (reprfunc)PyTclObject_repr, /*tp_repr*/
939 0, /*tp_as_number*/
940 0, /*tp_as_sequence*/
941 0, /*tp_as_mapping*/
942 0, /*tp_hash*/
943 0, /*tp_call*/
944 (reprfunc)PyTclObject_str, /*tp_str*/
945 PyObject_GenericGetAttr,/*tp_getattro*/
946 0, /*tp_setattro*/
947 0, /*tp_as_buffer*/
948 Py_TPFLAGS_DEFAULT, /*tp_flags*/
949 0, /*tp_doc*/
950 0, /*tp_traverse*/
951 0, /*tp_clear*/
952 0, /*tp_richcompare*/
953 0, /*tp_weaklistoffset*/
954 0, /*tp_iter*/
955 0, /*tp_iternext*/
956 PyTclObject_methods, /*tp_methods*/
957 0, /*tp_members*/
958 PyTclObject_getsetlist, /*tp_getset*/
959 0, /*tp_base*/
960 0, /*tp_dict*/
961 0, /*tp_descr_get*/
962 0, /*tp_descr_set*/
963 0, /*tp_dictoffset*/
964 0, /*tp_init*/
965 0, /*tp_alloc*/
966 0, /*tp_new*/
967 0, /*tp_free*/
968 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000969};
970
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000971static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000972AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000973{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000974 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000975
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000976 if (PyString_Check(value))
977 return Tcl_NewStringObj(PyString_AS_STRING(value),
978 PyString_GET_SIZE(value));
979 else if (PyBool_Check(value))
980 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
981 else if (PyInt_Check(value))
982 return Tcl_NewLongObj(PyInt_AS_LONG(value));
983 else if (PyFloat_Check(value))
984 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
985 else if (PyTuple_Check(value)) {
986 Tcl_Obj **argv = (Tcl_Obj**)
987 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
988 int i;
989 if(!argv)
990 return 0;
991 for(i=0;i<PyTuple_Size(value);i++)
992 argv[i] = AsObj(PyTuple_GetItem(value,i));
993 result = Tcl_NewListObj(PyTuple_Size(value), argv);
994 ckfree(FREECAST argv);
995 return result;
996 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000997#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000998 else if (PyUnicode_Check(value)) {
999 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1000 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1001 /* This #ifdef assumes that Tcl uses UCS-2.
1002 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001003#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001004 Tcl_UniChar *outbuf = NULL;
1005 Py_ssize_t i;
1006 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
1007 if (allocsize >= size)
1008 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
1009 /* Else overflow occurred, and we take the next exit */
1010 if (!outbuf) {
1011 PyErr_NoMemory();
1012 return NULL;
1013 }
1014 for (i = 0; i < size; i++) {
1015 if (inbuf[i] >= 0x10000) {
1016 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001017 PyErr_Format(Tkinter_TclError,
1018 "character U+%x is above the range "
1019 "(U+0000-U+FFFF) allowed by Tcl",
1020 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001021 ckfree(FREECAST outbuf);
1022 return NULL;
1023 }
1024 outbuf[i] = inbuf[i];
1025 }
1026 result = Tcl_NewUnicodeObj(outbuf, size);
1027 ckfree(FREECAST outbuf);
1028 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001029#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001030 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001031#endif
1032
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001033 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001034#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001035 else if(PyTclObject_Check(value)) {
1036 Tcl_Obj *v = ((PyTclObject*)value)->value;
1037 Tcl_IncrRefCount(v);
1038 return v;
1039 }
1040 else {
1041 PyObject *v = PyObject_Str(value);
1042 if (!v)
1043 return 0;
1044 result = AsObj(v);
1045 Py_DECREF(v);
1046 return result;
1047 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001048}
1049
Martin v. Löwisffad6332002-11-26 09:28:05 +00001050static PyObject*
1051FromObj(PyObject* tkapp, Tcl_Obj *value)
1052{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001053 PyObject *result = NULL;
1054 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001055
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001056 if (value->typePtr == NULL) {
1057 /* If the result contains any bytes with the top bit set,
1058 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001059#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001060 int i;
1061 char *s = value->bytes;
1062 int len = value->length;
1063 for (i = 0; i < len; i++) {
1064 if (value->bytes[i] & 0x80)
1065 break;
1066 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001067
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001068 if (i == value->length)
1069 result = PyString_FromStringAndSize(s, len);
1070 else {
1071 /* Convert UTF-8 to Unicode string */
1072 result = PyUnicode_DecodeUTF8(s, len, "strict");
1073 if (result == NULL) {
1074 PyErr_Clear();
1075 result = PyString_FromStringAndSize(s, len);
1076 }
1077 }
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001078#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001079 result = PyString_FromStringAndSize(value->bytes, value->length);
Martin v. Löwise07e18d2002-12-04 19:54:36 +00001080#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001081 return result;
1082 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001083
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001084 if (value->typePtr == app->BooleanType) {
1085 result = value->internalRep.longValue ? Py_True : Py_False;
1086 Py_INCREF(result);
1087 return result;
1088 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001089
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001090 if (value->typePtr == app->ByteArrayType) {
1091 int size;
1092 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1093 return PyString_FromStringAndSize(data, size);
1094 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001095
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001096 if (value->typePtr == app->DoubleType) {
1097 return PyFloat_FromDouble(value->internalRep.doubleValue);
1098 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001099
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001100 if (value->typePtr == app->IntType) {
1101 return PyInt_FromLong(value->internalRep.longValue);
1102 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001103
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001104 if (value->typePtr == app->ListType) {
1105 int size;
1106 int i, status;
1107 PyObject *elem;
1108 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001109
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001110 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1111 if (status == TCL_ERROR)
1112 return Tkinter_Error(tkapp);
1113 result = PyTuple_New(size);
1114 if (!result)
1115 return NULL;
1116 for (i = 0; i < size; i++) {
1117 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1118 value, i, &tcl_elem);
1119 if (status == TCL_ERROR) {
1120 Py_DECREF(result);
1121 return Tkinter_Error(tkapp);
1122 }
1123 elem = FromObj(tkapp, tcl_elem);
1124 if (!elem) {
1125 Py_DECREF(result);
1126 return NULL;
1127 }
1128 PyTuple_SetItem(result, i, elem);
1129 }
1130 return result;
1131 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001132
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001133 if (value->typePtr == app->ProcBodyType) {
1134 /* fall through: return tcl object. */
1135 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001136
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001137 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001139#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001140 PyObject *result;
1141 int size;
1142 Tcl_UniChar *input;
1143 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001144
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001145 size = Tcl_GetCharLength(value);
1146 result = PyUnicode_FromUnicode(NULL, size);
1147 if (!result)
1148 return NULL;
1149 input = Tcl_GetUnicode(value);
1150 output = PyUnicode_AS_UNICODE(result);
1151 while (size--)
1152 *output++ = *input++;
1153 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001154#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001155 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1156 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001157#endif
1158#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 int size;
1160 char *c;
1161 c = Tcl_GetStringFromObj(value, &size);
1162 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001163#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001164 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001165
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001166 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001167}
1168
Guilherme Polo1972d162009-03-27 21:43:08 +00001169#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001170/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001171TCL_DECLARE_MUTEX(call_mutex)
1172
1173typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001174 Tcl_Event ev; /* Must be first */
1175 TkappObject *self;
1176 PyObject *args;
1177 int flags;
1178 PyObject **res;
1179 PyObject **exc_type, **exc_value, **exc_tb;
1180 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001181} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001182#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001183
1184void
1185Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001186{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001187 int i;
1188 for (i = 0; i < objc; i++)
1189 Tcl_DecrRefCount(objv[i]);
1190 if (objv != objStore)
1191 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192}
Guido van Rossum18468821994-06-20 07:49:28 +00001193
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194/* Convert Python objects to Tcl objects. This must happen in the
1195 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001196
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001197static Tcl_Obj**
1198Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1199{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001200 Tcl_Obj **objv = objStore;
1201 int objc = 0, i;
1202 if (args == NULL)
1203 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001205 else if (!PyTuple_Check(args)) {
1206 objv[0] = AsObj(args);
1207 if (objv[0] == 0)
1208 goto finally;
1209 objc = 1;
1210 Tcl_IncrRefCount(objv[0]);
1211 }
1212 else {
1213 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001214
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001215 if (objc > ARGSZ) {
1216 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1217 if (objv == NULL) {
1218 PyErr_NoMemory();
1219 objc = 0;
1220 goto finally;
1221 }
1222 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001224 for (i = 0; i < objc; i++) {
1225 PyObject *v = PyTuple_GetItem(args, i);
1226 if (v == Py_None) {
1227 objc = i;
1228 break;
1229 }
1230 objv[i] = AsObj(v);
1231 if (!objv[i]) {
1232 /* Reset objc, so it attempts to clear
1233 objects only up to i. */
1234 objc = i;
1235 goto finally;
1236 }
1237 Tcl_IncrRefCount(objv[i]);
1238 }
1239 }
1240 *pobjc = objc;
1241 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001242finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001243 Tkapp_CallDeallocArgs(objv, objStore, objc);
1244 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001245}
Guido van Rossum212643f1998-04-29 16:22:14 +00001246
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001247/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001248
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249static PyObject*
1250Tkapp_CallResult(TkappObject *self)
1251{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001252 PyObject *res = NULL;
1253 if(self->wantobjects) {
1254 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1255 /* Not sure whether the IncrRef is necessary, but something
1256 may overwrite the interpreter result while we are
1257 converting it. */
1258 Tcl_IncrRefCount(value);
1259 res = FromObj((PyObject*)self, value);
1260 Tcl_DecrRefCount(value);
1261 } else {
1262 const char *s = Tcl_GetStringResult(self->interp);
1263 const char *p = s;
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001264
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001265 /* If the result contains any bytes with the top bit set,
1266 it's UTF-8 and we should decode it to Unicode */
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001267#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001268 while (*p != '\0') {
1269 if (*p & 0x80)
1270 break;
1271 p++;
1272 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001273
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001274 if (*p == '\0')
1275 res = PyString_FromStringAndSize(s, (int)(p-s));
1276 else {
1277 /* Convert UTF-8 to Unicode string */
1278 p = strchr(p, '\0');
1279 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1280 if (res == NULL) {
1281 PyErr_Clear();
1282 res = PyString_FromStringAndSize(s, (int)(p-s));
1283 }
1284 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001285#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001286 p = strchr(p, '\0');
1287 res = PyString_FromStringAndSize(s, (int)(p-s));
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001288#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001289 }
1290 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001291}
Guido van Rossum632de272000-03-29 00:19:50 +00001292
Guilherme Polo1972d162009-03-27 21:43:08 +00001293#ifdef WITH_THREAD
1294
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001295/* Tkapp_CallProc is the event procedure that is executed in the context of
1296 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1297 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001298
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001299static int
1300Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1301{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 Tcl_Obj *objStore[ARGSZ];
1303 Tcl_Obj **objv;
1304 int objc;
1305 int i;
1306 ENTER_PYTHON
1307 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1308 if (!objv) {
1309 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1310 *(e->res) = NULL;
1311 }
1312 LEAVE_PYTHON
1313 if (!objv)
1314 goto done;
1315 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1316 ENTER_PYTHON
1317 if (i == TCL_ERROR) {
1318 *(e->res) = NULL;
1319 *(e->exc_type) = NULL;
1320 *(e->exc_tb) = NULL;
1321 *(e->exc_value) = PyObject_CallFunction(
1322 Tkinter_TclError, "s",
1323 Tcl_GetStringResult(e->self->interp));
1324 }
1325 else {
1326 *(e->res) = Tkapp_CallResult(e->self);
1327 }
1328 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001329
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001330 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001331done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001332 /* Wake up calling thread. */
1333 Tcl_MutexLock(&call_mutex);
1334 Tcl_ConditionNotify(e->done);
1335 Tcl_MutexUnlock(&call_mutex);
1336 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001337}
1338
Guilherme Polo1972d162009-03-27 21:43:08 +00001339#endif
1340
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001341/* This is the main entry point for calling a Tcl command.
1342 It supports three cases, with regard to threading:
1343 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1344 the context of the calling thread.
1345 2. Tcl is threaded, caller of the command is in the interpreter thread:
1346 Execute the command in the calling thread. Since the Tcl lock will
1347 not be used, we can merge that with case 1.
1348 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1349 the interpreter thread. Allocation of Tcl objects needs to occur in the
1350 interpreter thread, so we ship the PyObject* args to the target thread,
1351 and perform processing there. */
1352
1353static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001354Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001355{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001356 Tcl_Obj *objStore[ARGSZ];
1357 Tcl_Obj **objv = NULL;
1358 int objc, i;
1359 PyObject *res = NULL;
1360 TkappObject *self = (TkappObject*)selfptr;
1361 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001363 /* If args is a single tuple, replace with contents of tuple */
1364 if (1 == PyTuple_Size(args)){
1365 PyObject* item = PyTuple_GetItem(args, 0);
1366 if (PyTuple_Check(item))
1367 args = item;
1368 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001369#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001370 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1371 /* We cannot call the command directly. Instead, we must
1372 marshal the parameters to the interpreter thread. */
1373 Tkapp_CallEvent *ev;
1374 Tcl_Condition cond = NULL;
1375 PyObject *exc_type, *exc_value, *exc_tb;
1376 if (!WaitForMainloop(self))
1377 return NULL;
1378 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1379 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1380 ev->self = self;
1381 ev->args = args;
1382 ev->res = &res;
1383 ev->exc_type = &exc_type;
1384 ev->exc_value = &exc_value;
1385 ev->exc_tb = &exc_tb;
1386 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001387
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001388 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001390 if (res == NULL) {
1391 if (exc_type)
1392 PyErr_Restore(exc_type, exc_value, exc_tb);
1393 else
1394 PyErr_SetObject(Tkinter_TclError, exc_value);
1395 }
1396 Tcl_ConditionFinalize(&cond);
1397 }
1398 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001399#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001400 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001402 objv = Tkapp_CallArgs(args, objStore, &objc);
1403 if (!objv)
1404 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001405
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001406 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001407
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001408 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001410 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001411
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001412 if (i == TCL_ERROR)
1413 Tkinter_Error(selfptr);
1414 else
1415 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001416
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001417 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001418
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001419 Tkapp_CallDeallocArgs(objv, objStore, objc);
1420 }
1421 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001422}
1423
1424
1425static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001426Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001427{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001428 /* Could do the same here as for Tkapp_Call(), but this is not used
1429 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1430 way for the user to do what all its Global* variants do (save and
1431 reset the scope pointer, call the local version, restore the saved
1432 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001433
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001434 char *cmd;
1435 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001436
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001437 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001439 cmd = Merge(args);
1440 if (cmd) {
1441 int err;
1442 ENTER_TCL
1443 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1444 ENTER_OVERLAP
1445 if (err == TCL_ERROR)
1446 res = Tkinter_Error(self);
1447 else
1448 res = PyString_FromString(Tkapp_Result(self));
1449 LEAVE_OVERLAP_TCL
1450 ckfree(cmd);
1451 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001452
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001453 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001454}
1455
1456static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001457Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001458{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001459 char *script;
1460 PyObject *res = NULL;
1461 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001462
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001463 if (!PyArg_ParseTuple(args, "s:eval", &script))
1464 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001465
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001466 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001468 ENTER_TCL
1469 err = Tcl_Eval(Tkapp_Interp(self), script);
1470 ENTER_OVERLAP
1471 if (err == TCL_ERROR)
1472 res = Tkinter_Error(self);
1473 else
1474 res = PyString_FromString(Tkapp_Result(self));
1475 LEAVE_OVERLAP_TCL
1476 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001477}
1478
1479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001480Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001481{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 char *script;
1483 PyObject *res = NULL;
1484 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001486 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1487 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001489 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001491 ENTER_TCL
1492 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1493 ENTER_OVERLAP
1494 if (err == TCL_ERROR)
1495 res = Tkinter_Error(self);
1496 else
1497 res = PyString_FromString(Tkapp_Result(self));
1498 LEAVE_OVERLAP_TCL
1499 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001500}
1501
1502static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001503Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001504{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001505 char *fileName;
1506 PyObject *res = NULL;
1507 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001509 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1510 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001512 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001514 ENTER_TCL
1515 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1516 ENTER_OVERLAP
1517 if (err == TCL_ERROR)
1518 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001519
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001520 else
1521 res = PyString_FromString(Tkapp_Result(self));
1522 LEAVE_OVERLAP_TCL
1523 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001524}
1525
1526static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001527Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001528{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001529 char *script;
1530 PyObject *res = NULL;
1531 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001533 if (!PyArg_ParseTuple(args, "s", &script))
1534 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001535
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001536 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001538 ENTER_TCL
1539 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1540 ENTER_OVERLAP
1541 if (err == TCL_ERROR)
1542 res = Tkinter_Error(self);
1543 else
1544 res = PyString_FromString(Tkapp_Result(self));
1545 LEAVE_OVERLAP_TCL
1546 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001547}
1548
1549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001550Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001551{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001552 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001553
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001554 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1555 return NULL;
1556 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001557
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001558 ENTER_TCL
1559 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1560 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001561
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001562 Py_INCREF(Py_None);
1563 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001564}
1565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001567
Guido van Rossum18468821994-06-20 07:49:28 +00001568/** Tcl Variable **/
1569
Guilherme Polo1972d162009-03-27 21:43:08 +00001570typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1571
1572#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573TCL_DECLARE_MUTEX(var_mutex)
1574
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001576 Tcl_Event ev; /* must be first */
1577 PyObject *self;
1578 PyObject *args;
1579 int flags;
1580 EventFunc func;
1581 PyObject **res;
1582 PyObject **exc_type;
1583 PyObject **exc_val;
1584 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001585} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001586#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001588static int
1589varname_converter(PyObject *in, void *_out)
1590{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001591 char **out = (char**)_out;
1592 if (PyString_Check(in)) {
1593 *out = PyString_AsString(in);
1594 return 1;
1595 }
1596 if (PyTclObject_Check(in)) {
1597 *out = PyTclObject_TclString(in);
1598 return 1;
1599 }
1600 /* XXX: Should give diagnostics. */
1601 return 0;
1602}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001603
Guilherme Polo1972d162009-03-27 21:43:08 +00001604#ifdef WITH_THREAD
1605
Martin v. Löwis111c1802008-06-13 07:47:47 +00001606static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001607var_perform(VarEvent *ev)
1608{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001609 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1610 if (!*(ev->res)) {
1611 PyObject *exc, *val, *tb;
1612 PyErr_Fetch(&exc, &val, &tb);
1613 PyErr_NormalizeException(&exc, &val, &tb);
1614 *(ev->exc_type) = exc;
1615 *(ev->exc_val) = val;
1616 Py_DECREF(tb);
1617 }
1618
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001619}
1620
1621static int
1622var_proc(VarEvent* ev, int flags)
1623{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001624 ENTER_PYTHON
1625 var_perform(ev);
1626 Tcl_MutexLock(&var_mutex);
1627 Tcl_ConditionNotify(ev->cond);
1628 Tcl_MutexUnlock(&var_mutex);
1629 LEAVE_PYTHON
1630 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001631}
1632
Guilherme Polo1972d162009-03-27 21:43:08 +00001633#endif
1634
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001635static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001636var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001637{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001638#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001639 TkappObject *self = (TkappObject*)selfptr;
1640 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1641 TkappObject *self = (TkappObject*)selfptr;
1642 VarEvent *ev;
1643 PyObject *res, *exc_type, *exc_val;
1644 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001645
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001646 /* The current thread is not the interpreter thread. Marshal
1647 the call to the interpreter thread, then wait for
1648 completion. */
1649 if (!WaitForMainloop(self))
1650 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001651
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001652 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1653
1654 ev->self = selfptr;
1655 ev->args = args;
1656 ev->flags = flags;
1657 ev->func = func;
1658 ev->res = &res;
1659 ev->exc_type = &exc_type;
1660 ev->exc_val = &exc_val;
1661 ev->cond = &cond;
1662 ev->ev.proc = (Tcl_EventProc*)var_proc;
1663 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1664 Tcl_ConditionFinalize(&cond);
1665 if (!res) {
1666 PyErr_SetObject(exc_type, exc_val);
1667 Py_DECREF(exc_type);
1668 Py_DECREF(exc_val);
1669 return NULL;
1670 }
1671 return res;
1672 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001673#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001674 /* Tcl is not threaded, or this is the interpreter thread. */
1675 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001676}
1677
Guido van Rossum18468821994-06-20 07:49:28 +00001678static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001679SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001680{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001681 char *name1, *name2;
1682 PyObject *newValue;
1683 PyObject *res = NULL;
1684 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001685
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001686 if (PyArg_ParseTuple(args, "O&O:setvar",
1687 varname_converter, &name1, &newValue)) {
1688 /* XXX Acquire tcl lock??? */
1689 newval = AsObj(newValue);
1690 if (newval == NULL)
1691 return NULL;
1692 ENTER_TCL
1693 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1694 newval, flags);
1695 ENTER_OVERLAP
1696 if (!ok)
1697 Tkinter_Error(self);
1698 else {
1699 res = Py_None;
1700 Py_INCREF(res);
1701 }
1702 LEAVE_OVERLAP_TCL
1703 }
1704 else {
1705 PyErr_Clear();
1706 if (PyArg_ParseTuple(args, "ssO:setvar",
1707 &name1, &name2, &newValue)) {
1708 /* XXX must hold tcl lock already??? */
1709 newval = AsObj(newValue);
1710 ENTER_TCL
1711 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1712 ENTER_OVERLAP
1713 if (!ok)
1714 Tkinter_Error(self);
1715 else {
1716 res = Py_None;
1717 Py_INCREF(res);
1718 }
1719 LEAVE_OVERLAP_TCL
1720 }
1721 else {
1722 return NULL;
1723 }
1724 }
1725 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001726}
1727
1728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001729Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001730{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001731 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001732}
1733
1734static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001735Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001736{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001737 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
Barry Warsawfa701a81997-01-16 00:15:11 +00001740
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001741
Guido van Rossum18468821994-06-20 07:49:28 +00001742static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001743GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001744{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001745 char *name1, *name2=NULL;
1746 PyObject *res = NULL;
1747 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001748
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001749 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1750 varname_converter, &name1, &name2))
1751 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001752
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001753 ENTER_TCL
1754 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1755 ENTER_OVERLAP
1756 if (tres == NULL) {
1757 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1758 } else {
1759 if (((TkappObject*)self)->wantobjects) {
1760 res = FromObj(self, tres);
1761 }
1762 else {
1763 res = PyString_FromString(Tcl_GetString(tres));
1764 }
1765 }
1766 LEAVE_OVERLAP_TCL
1767 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001773 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
1776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001779 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001780}
1781
Barry Warsawfa701a81997-01-16 00:15:11 +00001782
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001783
Guido van Rossum18468821994-06-20 07:49:28 +00001784static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001785UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001786{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001787 char *name1, *name2=NULL;
1788 int code;
1789 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001790
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1792 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001793
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001794 ENTER_TCL
1795 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1796 ENTER_OVERLAP
1797 if (code == TCL_ERROR)
1798 res = Tkinter_Error(self);
1799 else {
1800 Py_INCREF(Py_None);
1801 res = Py_None;
1802 }
1803 LEAVE_OVERLAP_TCL
1804 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001805}
1806
1807static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001808Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001809{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
1813static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001814Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001815{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001816 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001817}
1818
Barry Warsawfa701a81997-01-16 00:15:11 +00001819
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001820
Guido van Rossum18468821994-06-20 07:49:28 +00001821/** Tcl to Python **/
1822
1823static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001824Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001825{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001826 char *s;
1827 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001828
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001829 if (PyTuple_Size(args) == 1) {
1830 PyObject* o = PyTuple_GetItem(args, 0);
1831 if (PyInt_Check(o)) {
1832 Py_INCREF(o);
1833 return o;
1834 }
1835 }
1836 if (!PyArg_ParseTuple(args, "s:getint", &s))
1837 return NULL;
1838 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1839 return Tkinter_Error(self);
1840 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001841}
1842
1843static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001844Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001845{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001846 char *s;
1847 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001848
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001849 if (PyTuple_Size(args) == 1) {
1850 PyObject *o = PyTuple_GetItem(args, 0);
1851 if (PyFloat_Check(o)) {
1852 Py_INCREF(o);
1853 return o;
1854 }
1855 }
1856 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1857 return NULL;
1858 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1859 return Tkinter_Error(self);
1860 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001861}
1862
1863static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001864Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001865{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001866 char *s;
1867 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001868
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 if (PyTuple_Size(args) == 1) {
1870 PyObject *o = PyTuple_GetItem(args, 0);
1871 if (PyInt_Check(o)) {
1872 Py_INCREF(o);
1873 return o;
1874 }
1875 }
1876 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1877 return NULL;
1878 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1879 return Tkinter_Error(self);
1880 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001881}
1882
1883static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001884Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001885{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001886 char *s;
1887 PyObject *res = NULL;
1888 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001889
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001890 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1891 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001892
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001893 CHECK_TCL_APPARTMENT;
1894
1895 ENTER_TCL
1896 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1897 ENTER_OVERLAP
1898 if (retval == TCL_ERROR)
1899 res = Tkinter_Error(self);
1900 else
1901 res = Py_BuildValue("s", Tkapp_Result(self));
1902 LEAVE_OVERLAP_TCL
1903 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001904}
1905
1906static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001907Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001908{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001909 char *s;
1910 PyObject *res = NULL;
1911 int retval;
1912 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001913
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001914 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1915 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001916
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001917 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001918
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001919 ENTER_TCL
1920 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1921 ENTER_OVERLAP
1922 if (retval == TCL_ERROR)
1923 res = Tkinter_Error(self);
1924 else
1925 res = Py_BuildValue("l", v);
1926 LEAVE_OVERLAP_TCL
1927 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001928}
1929
1930static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001931Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001932{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001933 char *s;
1934 PyObject *res = NULL;
1935 double v;
1936 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001937
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001938 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1939 return NULL;
1940 CHECK_TCL_APPARTMENT;
1941 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1942 ENTER_TCL
1943 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1944 ENTER_OVERLAP
1945 PyFPE_END_PROTECT(retval)
1946 if (retval == TCL_ERROR)
1947 res = Tkinter_Error(self);
1948 else
1949 res = Py_BuildValue("d", v);
1950 LEAVE_OVERLAP_TCL
1951 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001957 char *s;
1958 PyObject *res = NULL;
1959 int retval;
1960 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001961
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001962 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1963 return NULL;
1964 CHECK_TCL_APPARTMENT;
1965 ENTER_TCL
1966 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1967 ENTER_OVERLAP
1968 if (retval == TCL_ERROR)
1969 res = Tkinter_Error(self);
1970 else
1971 res = Py_BuildValue("i", v);
1972 LEAVE_OVERLAP_TCL
1973 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001974}
1975
Barry Warsawfa701a81997-01-16 00:15:11 +00001976
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001977
Guido van Rossum18468821994-06-20 07:49:28 +00001978static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001979Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001980{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001981 char *list;
1982 int argc;
1983 char **argv;
1984 PyObject *v;
1985 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001986
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001987 if (PyTuple_Size(args) == 1) {
1988 v = PyTuple_GetItem(args, 0);
1989 if (PyTuple_Check(v)) {
1990 Py_INCREF(v);
1991 return v;
1992 }
1993 }
1994 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1995 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001996
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001997 if (Tcl_SplitList(Tkapp_Interp(self), list,
1998 &argc, &argv) == TCL_ERROR) {
1999 PyMem_Free(list);
2000 return Tkinter_Error(self);
2001 }
Guido van Rossum18468821994-06-20 07:49:28 +00002002
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002003 if (!(v = PyTuple_New(argc)))
2004 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002005
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002006 for (i = 0; i < argc; i++) {
2007 PyObject *s = PyString_FromString(argv[i]);
2008 if (!s || PyTuple_SetItem(v, i, s)) {
2009 Py_DECREF(v);
2010 v = NULL;
2011 goto finally;
2012 }
2013 }
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Barry Warsawfa701a81997-01-16 00:15:11 +00002015 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002016 ckfree(FREECAST argv);
2017 PyMem_Free(list);
2018 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002019}
2020
2021static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002022Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002023{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002024 PyObject *v;
2025 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002026
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002027 if (PyTuple_Size(args) == 1) {
2028 PyObject* o = PyTuple_GetItem(args, 0);
2029 if (PyTuple_Check(o)) {
2030 o = SplitObj(o);
2031 return o;
2032 }
2033 }
2034 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2035 return NULL;
2036 v = Split(list);
2037 PyMem_Free(list);
2038 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002039}
2040
2041static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002042Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002043{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002044 char *s = Merge(args);
2045 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002046
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002047 if (s) {
2048 res = PyString_FromString(s);
2049 ckfree(s);
2050 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002052 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Barry Warsawfa701a81997-01-16 00:15:11 +00002055
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002056
Guido van Rossum18468821994-06-20 07:49:28 +00002057/** Tcl Command **/
2058
Guido van Rossum00d93061998-05-28 23:06:38 +00002059/* Client data struct */
2060typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002061 PyObject *self;
2062 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002063} PythonCmd_ClientData;
2064
2065static int
Fred Drake509d79a2000-07-08 04:04:38 +00002066PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002067{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002068 errorInCmd = 1;
2069 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2070 LEAVE_PYTHON
2071 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002072}
2073
Guido van Rossum18468821994-06-20 07:49:28 +00002074/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002075 * function or method.
2076 */
Guido van Rossum18468821994-06-20 07:49:28 +00002077static int
Fred Drake509d79a2000-07-08 04:04:38 +00002078PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002079{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002080 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2081 PyObject *func, *arg, *res;
2082 int i, rv;
2083 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002084
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002085 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002086
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002087 /* TBD: no error checking here since we know, via the
2088 * Tkapp_CreateCommand() that the client data is a two-tuple
2089 */
2090 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 /* Create argument list (argv1, ..., argvN) */
2093 if (!(arg = PyTuple_New(argc - 1)))
2094 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002095
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002096 for (i = 0; i < (argc - 1); i++) {
2097 PyObject *s = PyString_FromString(argv[i + 1]);
2098 if (!s || PyTuple_SetItem(arg, i, s)) {
2099 Py_DECREF(arg);
2100 return PythonCmd_Error(interp);
2101 }
2102 }
2103 res = PyEval_CallObject(func, arg);
2104 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002105
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002106 if (res == NULL)
2107 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002109 obj_res = AsObj(res);
2110 if (obj_res == NULL) {
2111 Py_DECREF(res);
2112 return PythonCmd_Error(interp);
2113 }
2114 else {
2115 Tcl_SetObjResult(interp, obj_res);
2116 rv = TCL_OK;
2117 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002118
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002119 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002120
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002121 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002122
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002123 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002124}
2125
2126static void
Fred Drake509d79a2000-07-08 04:04:38 +00002127PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002128{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002129 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002130
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002131 ENTER_PYTHON
2132 Py_XDECREF(data->self);
2133 Py_XDECREF(data->func);
2134 PyMem_DEL(data);
2135 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002136}
2137
Barry Warsawfa701a81997-01-16 00:15:11 +00002138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002139
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002140
Guilherme Polo1972d162009-03-27 21:43:08 +00002141#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002142TCL_DECLARE_MUTEX(command_mutex)
2143
2144typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002145 Tcl_Event ev;
2146 Tcl_Interp* interp;
2147 char *name;
2148 int create;
2149 int *status;
2150 ClientData *data;
2151 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002152} CommandEvent;
2153
2154static int
2155Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002156{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002157 if (ev->create)
2158 *ev->status = Tcl_CreateCommand(
2159 ev->interp, ev->name, PythonCmd,
2160 ev->data, PythonCmdDelete) == NULL;
2161 else
2162 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2163 Tcl_MutexLock(&command_mutex);
2164 Tcl_ConditionNotify(ev->done);
2165 Tcl_MutexUnlock(&command_mutex);
2166 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002167}
Guilherme Polo1972d162009-03-27 21:43:08 +00002168#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002169
2170static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002171Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002172{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002173 TkappObject *self = (TkappObject*)selfptr;
2174 PythonCmd_ClientData *data;
2175 char *cmdName;
2176 PyObject *func;
2177 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002178
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002179 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2180 return NULL;
2181 if (!PyCallable_Check(func)) {
2182 PyErr_SetString(PyExc_TypeError, "command not callable");
2183 return NULL;
2184 }
Guido van Rossum18468821994-06-20 07:49:28 +00002185
Martin v. Löwisa9656492003-03-30 08:44:58 +00002186#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002187 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2188 !WaitForMainloop(self))
2189 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002190#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002191
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002192 data = PyMem_NEW(PythonCmd_ClientData, 1);
2193 if (!data)
2194 return PyErr_NoMemory();
2195 Py_INCREF(self);
2196 Py_INCREF(func);
2197 data->self = selfptr;
2198 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002199
2200#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002201 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2202 Tcl_Condition cond = NULL;
2203 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2204 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2205 ev->interp = self->interp;
2206 ev->create = 1;
2207 ev->name = cmdName;
2208 ev->data = (ClientData)data;
2209 ev->status = &err;
2210 ev->done = &cond;
2211 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2212 Tcl_ConditionFinalize(&cond);
2213 }
2214 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002215#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002216 {
2217 ENTER_TCL
2218 err = Tcl_CreateCommand(
2219 Tkapp_Interp(self), cmdName, PythonCmd,
2220 (ClientData)data, PythonCmdDelete) == NULL;
2221 LEAVE_TCL
2222 }
2223 if (err) {
2224 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2225 PyMem_DEL(data);
2226 return NULL;
2227 }
Guido van Rossum18468821994-06-20 07:49:28 +00002228
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002229 Py_INCREF(Py_None);
2230 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002231}
2232
Barry Warsawfa701a81997-01-16 00:15:11 +00002233
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002234
Guido van Rossum18468821994-06-20 07:49:28 +00002235static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002236Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002237{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002238 TkappObject *self = (TkappObject*)selfptr;
2239 char *cmdName;
2240 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002241
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002242 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2243 return NULL;
Guilherme Polo1972d162009-03-27 21:43:08 +00002244
2245#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002246 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2247 Tcl_Condition cond = NULL;
2248 CommandEvent *ev;
2249 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2250 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2251 ev->interp = self->interp;
2252 ev->create = 0;
2253 ev->name = cmdName;
2254 ev->status = &err;
2255 ev->done = &cond;
2256 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2257 &command_mutex);
2258 Tcl_ConditionFinalize(&cond);
2259 }
2260 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002261#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002262 {
2263 ENTER_TCL
2264 err = Tcl_DeleteCommand(self->interp, cmdName);
2265 LEAVE_TCL
2266 }
2267 if (err == -1) {
2268 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2269 return NULL;
2270 }
2271 Py_INCREF(Py_None);
2272 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002273}
2274
Barry Warsawfa701a81997-01-16 00:15:11 +00002275
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002276
Guido van Rossum00d93061998-05-28 23:06:38 +00002277#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002278/** File Handler **/
2279
Guido van Rossum00d93061998-05-28 23:06:38 +00002280typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002281 PyObject *func;
2282 PyObject *file;
2283 int id;
2284 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002285} FileHandler_ClientData;
2286
2287static FileHandler_ClientData *HeadFHCD;
2288
2289static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002290NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002291{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002292 FileHandler_ClientData *p;
2293 p = PyMem_NEW(FileHandler_ClientData, 1);
2294 if (p != NULL) {
2295 Py_XINCREF(func);
2296 Py_XINCREF(file);
2297 p->func = func;
2298 p->file = file;
2299 p->id = id;
2300 p->next = HeadFHCD;
2301 HeadFHCD = p;
2302 }
2303 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002304}
2305
2306static void
Fred Drake509d79a2000-07-08 04:04:38 +00002307DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002308{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002309 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002310
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002311 pp = &HeadFHCD;
2312 while ((p = *pp) != NULL) {
2313 if (p->id == id) {
2314 *pp = p->next;
2315 Py_XDECREF(p->func);
2316 Py_XDECREF(p->file);
2317 PyMem_DEL(p);
2318 }
2319 else
2320 pp = &p->next;
2321 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002322}
2323
Guido van Rossuma597dde1995-01-10 20:56:29 +00002324static void
Fred Drake509d79a2000-07-08 04:04:38 +00002325FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002326{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002327 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2328 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002330 ENTER_PYTHON
2331 func = data->func;
2332 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002333
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002334 arg = Py_BuildValue("(Oi)", file, (long) mask);
2335 res = PyEval_CallObject(func, arg);
2336 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002337
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002338 if (res == NULL) {
2339 errorInCmd = 1;
2340 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2341 }
2342 Py_XDECREF(res);
2343 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002344}
2345
Guido van Rossum18468821994-06-20 07:49:28 +00002346static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002347Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2348 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002349{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002350 FileHandler_ClientData *data;
2351 PyObject *file, *func;
2352 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002353
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002354 if (!self && Py_Py3kWarningFlag) {
2355 if (PyErr_Warn(PyExc_DeprecationWarning,
2356 "_tkinter.createfilehandler is gone in 3.x") < 0)
2357 return NULL;
2358 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002359
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002360 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2361 &file, &mask, &func))
2362 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002363
Martin v. Löwisa9656492003-03-30 08:44:58 +00002364#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002365 if (!self && !tcl_lock) {
2366 /* We don't have the Tcl lock since Tcl is threaded. */
2367 PyErr_SetString(PyExc_RuntimeError,
2368 "_tkinter.createfilehandler not supported "
2369 "for threaded Tcl");
2370 return NULL;
2371 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002372#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002373
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002374 if (self) {
2375 CHECK_TCL_APPARTMENT;
2376 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002377
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002378 tfile = PyObject_AsFileDescriptor(file);
2379 if (tfile < 0)
2380 return NULL;
2381 if (!PyCallable_Check(func)) {
2382 PyErr_SetString(PyExc_TypeError, "bad argument list");
2383 return NULL;
2384 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002385
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002386 data = NewFHCD(func, file, tfile);
2387 if (data == NULL)
2388 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002390 /* Ought to check for null Tcl_File object... */
2391 ENTER_TCL
2392 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2393 LEAVE_TCL
2394 Py_INCREF(Py_None);
2395 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002396}
2397
2398static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002399Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002400{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002401 PyObject *file;
2402 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002403
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002404 if (!self && Py_Py3kWarningFlag) {
2405 if (PyErr_Warn(PyExc_DeprecationWarning,
2406 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2407 return NULL;
2408 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002409
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002410 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2411 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002412
Martin v. Löwisa9656492003-03-30 08:44:58 +00002413#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002414 if (!self && !tcl_lock) {
2415 /* We don't have the Tcl lock since Tcl is threaded. */
2416 PyErr_SetString(PyExc_RuntimeError,
2417 "_tkinter.deletefilehandler not supported "
2418 "for threaded Tcl");
2419 return NULL;
2420 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002421#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002422
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002423 if (self) {
2424 CHECK_TCL_APPARTMENT;
2425 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002427 tfile = PyObject_AsFileDescriptor(file);
2428 if (tfile < 0)
2429 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002430
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002431 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002432
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002433 /* Ought to check for null Tcl_File object... */
2434 ENTER_TCL
2435 Tcl_DeleteFileHandler(tfile);
2436 LEAVE_TCL
2437 Py_INCREF(Py_None);
2438 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002439}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002440#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002443/**** Tktt Object (timer token) ****/
2444
Jeremy Hylton938ace62002-07-17 16:30:39 +00002445static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002446
Guido van Rossum00d93061998-05-28 23:06:38 +00002447typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002448 PyObject_HEAD
2449 Tcl_TimerToken token;
2450 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002451} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452
2453static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002454Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002455{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 TkttObject *v = (TkttObject *)self;
2457 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002458
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002459 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2460 return NULL;
2461 if (v->token != NULL) {
2462 Tcl_DeleteTimerHandler(v->token);
2463 v->token = NULL;
2464 }
2465 if (func != NULL) {
2466 v->func = NULL;
2467 Py_DECREF(func);
2468 Py_DECREF(v); /* See Tktt_New() */
2469 }
2470 Py_INCREF(Py_None);
2471 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472}
2473
2474static PyMethodDef Tktt_methods[] =
2475{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002476 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2477 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002478};
2479
2480static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002481Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002482{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002483 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002484
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002485 v = PyObject_New(TkttObject, &Tktt_Type);
2486 if (v == NULL)
2487 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002489 Py_INCREF(func);
2490 v->token = NULL;
2491 v->func = func;
2492
2493 /* Extra reference, deleted when called or when handler is deleted */
2494 Py_INCREF(v);
2495 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002496}
2497
2498static void
Fred Drake509d79a2000-07-08 04:04:38 +00002499Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002500{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002501 TkttObject *v = (TkttObject *)self;
2502 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002503
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002504 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002505
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002506 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002507}
2508
Guido van Rossum597ac201998-05-12 14:36:19 +00002509static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002510Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002511{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 TkttObject *v = (TkttObject *)self;
2513 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002514
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002515 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2516 v->func == NULL ? ", handler deleted" : "");
2517 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002518}
2519
2520static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002521Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002522{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002524}
2525
2526static PyTypeObject Tktt_Type =
2527{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002528 PyVarObject_HEAD_INIT(NULL, 0)
2529 "tktimertoken", /*tp_name */
2530 sizeof(TkttObject), /*tp_basicsize */
2531 0, /*tp_itemsize */
2532 Tktt_Dealloc, /*tp_dealloc */
2533 0, /*tp_print */
2534 Tktt_GetAttr, /*tp_getattr */
2535 0, /*tp_setattr */
2536 0, /*tp_compare */
2537 Tktt_Repr, /*tp_repr */
2538 0, /*tp_as_number */
2539 0, /*tp_as_sequence */
2540 0, /*tp_as_mapping */
2541 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002542};
2543
Barry Warsawfa701a81997-01-16 00:15:11 +00002544
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002545
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002546/** Timer Handler **/
2547
2548static void
Fred Drake509d79a2000-07-08 04:04:38 +00002549TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002550{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002551 TkttObject *v = (TkttObject *)clientData;
2552 PyObject *func = v->func;
2553 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002554
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002555 if (func == NULL)
2556 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002557
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002558 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002559
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002560 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002561
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002562 res = PyEval_CallObject(func, NULL);
2563 Py_DECREF(func);
2564 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002565
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002566 if (res == NULL) {
2567 errorInCmd = 1;
2568 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2569 }
2570 else
2571 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002572
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002573 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002574}
2575
2576static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002577Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002578{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002579 int milliseconds;
2580 PyObject *func;
2581 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002582
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002583 if (!self && Py_Py3kWarningFlag) {
2584 if (PyErr_Warn(PyExc_DeprecationWarning,
2585 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2586 return NULL;
2587 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002588
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002589 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2590 &milliseconds, &func))
2591 return NULL;
2592 if (!PyCallable_Check(func)) {
2593 PyErr_SetString(PyExc_TypeError, "bad argument list");
2594 return NULL;
2595 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002596
Martin v. Löwisa9656492003-03-30 08:44:58 +00002597#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002598 if (!self && !tcl_lock) {
2599 /* We don't have the Tcl lock since Tcl is threaded. */
2600 PyErr_SetString(PyExc_RuntimeError,
2601 "_tkinter.createtimerhandler not supported "
2602 "for threaded Tcl");
2603 return NULL;
2604 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002605#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002606
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002607 if (self) {
2608 CHECK_TCL_APPARTMENT;
2609 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002610
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002611 v = Tktt_New(func);
2612 if (v) {
2613 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2614 (ClientData)v);
2615 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002616
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002617 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002618}
2619
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002620
Guido van Rossum18468821994-06-20 07:49:28 +00002621/** Event Loop **/
2622
Guido van Rossum18468821994-06-20 07:49:28 +00002623static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002624Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002625{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002626 int threshold = 0;
2627 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002628#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002629 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002630#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002631
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002632 if (!self && Py_Py3kWarningFlag) {
2633 if (PyErr_Warn(PyExc_DeprecationWarning,
2634 "_tkinter.mainloop is gone in 3.x") < 0)
2635 return NULL;
2636 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002637
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002638 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2639 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002640
Martin v. Löwisa9656492003-03-30 08:44:58 +00002641#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002642 if (!self && !tcl_lock) {
2643 /* We don't have the Tcl lock since Tcl is threaded. */
2644 PyErr_SetString(PyExc_RuntimeError,
2645 "_tkinter.mainloop not supported "
2646 "for threaded Tcl");
2647 return NULL;
2648 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002649#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002650
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002651 if (self) {
2652 CHECK_TCL_APPARTMENT;
2653 self->dispatching = 1;
2654 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002655
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002656 quitMainLoop = 0;
2657 while (Tk_GetNumMainWindows() > threshold &&
2658 !quitMainLoop &&
2659 !errorInCmd)
2660 {
2661 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002662
2663#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002664 if (self && self->threaded) {
2665 /* Allow other Python threads to run. */
2666 ENTER_TCL
2667 result = Tcl_DoOneEvent(0);
2668 LEAVE_TCL
2669 }
2670 else {
2671 Py_BEGIN_ALLOW_THREADS
2672 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2673 tcl_tstate = tstate;
2674 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2675 tcl_tstate = NULL;
2676 if(tcl_lock)PyThread_release_lock(tcl_lock);
2677 if (result == 0)
2678 Sleep(Tkinter_busywaitinterval);
2679 Py_END_ALLOW_THREADS
2680 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002681#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002682 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002683#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002684
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002685 if (PyErr_CheckSignals() != 0) {
2686 if (self)
2687 self->dispatching = 0;
2688 return NULL;
2689 }
2690 if (result < 0)
2691 break;
2692 }
2693 if (self)
2694 self->dispatching = 0;
2695 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002696
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002697 if (errorInCmd) {
2698 errorInCmd = 0;
2699 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2700 excInCmd = valInCmd = trbInCmd = NULL;
2701 return NULL;
2702 }
2703 Py_INCREF(Py_None);
2704 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002705}
2706
2707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002708Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002709{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002710 int flags = 0;
2711 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002712
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002713 if (!self && Py_Py3kWarningFlag) {
2714 if (PyErr_Warn(PyExc_DeprecationWarning,
2715 "_tkinter.dooneevent is gone in 3.x") < 0)
2716 return NULL;
2717 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002718
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002719 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2720 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002721
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002722 ENTER_TCL
2723 rv = Tcl_DoOneEvent(flags);
2724 LEAVE_TCL
2725 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002726}
2727
2728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002729Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002730{
2731
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002732 if (!self && Py_Py3kWarningFlag) {
2733 if (PyErr_Warn(PyExc_DeprecationWarning,
2734 "_tkinter.quit is gone in 3.x") < 0)
2735 return NULL;
2736 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002737
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002738 if (!PyArg_ParseTuple(args, ":quit"))
2739 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002740
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002741 quitMainLoop = 1;
2742 Py_INCREF(Py_None);
2743 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002744}
2745
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002746static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002747Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002748{
2749
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002750 if (!PyArg_ParseTuple(args, ":interpaddr"))
2751 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002752
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002753 return PyInt_FromLong((long)Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002754}
2755
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002756static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002757Tkapp_TkInit(PyObject *self, PyObject *args)
2758{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002759 Tcl_Interp *interp = Tkapp_Interp(self);
2760 const char * _tk_exists = NULL;
2761 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002762
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002763#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002764 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2765 * first call failed.
2766 * To avoid the deadlock, we just refuse the second call through
2767 * a static variable.
2768 */
2769 if (tk_load_failed) {
2770 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2771 return NULL;
2772 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002773#endif
2774
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002775 /* We want to guard against calling Tk_Init() multiple times */
2776 CHECK_TCL_APPARTMENT;
2777 ENTER_TCL
2778 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2779 ENTER_OVERLAP
2780 if (err == TCL_ERROR) {
2781 /* This sets an exception, but we cannot return right
2782 away because we need to exit the overlap first. */
2783 Tkinter_Error(self);
2784 } else {
2785 _tk_exists = Tkapp_Result(self);
2786 }
2787 LEAVE_OVERLAP_TCL
2788 if (err == TCL_ERROR) {
2789 return NULL;
2790 }
2791 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2792 if (Tk_Init(interp) == TCL_ERROR) {
2793 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002794#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002795 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002796#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002797 return NULL;
2798 }
2799 }
2800 Py_INCREF(Py_None);
2801 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002802}
Barry Warsawfa701a81997-01-16 00:15:11 +00002803
Martin v. Löwisffad6332002-11-26 09:28:05 +00002804static PyObject *
2805Tkapp_WantObjects(PyObject *self, PyObject *args)
2806{
2807
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002808 int wantobjects = -1;
2809 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2810 return NULL;
2811 if (wantobjects == -1)
2812 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2813 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002814
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002815 Py_INCREF(Py_None);
2816 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002817}
2818
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002819static PyObject *
2820Tkapp_WillDispatch(PyObject *self, PyObject *args)
2821{
2822
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002823 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002824
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002825 Py_INCREF(Py_None);
2826 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002827}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002828
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002829
Guido van Rossum18468821994-06-20 07:49:28 +00002830/**** Tkapp Method List ****/
2831
2832static PyMethodDef Tkapp_methods[] =
2833{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002834 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2835 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2836 {"call", Tkapp_Call, METH_VARARGS},
2837 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2838 {"eval", Tkapp_Eval, METH_VARARGS},
2839 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2840 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2841 {"record", Tkapp_Record, METH_VARARGS},
2842 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2843 {"setvar", Tkapp_SetVar, METH_VARARGS},
2844 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2845 {"getvar", Tkapp_GetVar, METH_VARARGS},
2846 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2847 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2848 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2849 {"getint", Tkapp_GetInt, METH_VARARGS},
2850 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2851 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2852 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2853 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2854 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2855 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2856 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2857 {"split", Tkapp_Split, METH_VARARGS},
2858 {"merge", Tkapp_Merge, METH_VARARGS},
2859 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2860 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002861#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002862 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2863 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002864#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002865 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2866 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2867 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2868 {"quit", Tkapp_Quit, METH_VARARGS},
2869 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2870 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2871 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002872};
2873
Barry Warsawfa701a81997-01-16 00:15:11 +00002874
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002875
Guido van Rossum18468821994-06-20 07:49:28 +00002876/**** Tkapp Type Methods ****/
2877
2878static void
Fred Drake509d79a2000-07-08 04:04:38 +00002879Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002880{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002881 /*CHECK_TCL_APPARTMENT;*/
2882 ENTER_TCL
2883 Tcl_DeleteInterp(Tkapp_Interp(self));
2884 LEAVE_TCL
2885 PyObject_Del(self);
2886 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002887}
2888
2889static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002890Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00002891{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002892 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00002893}
2894
2895static PyTypeObject Tkapp_Type =
2896{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002897 PyVarObject_HEAD_INIT(NULL, 0)
2898 "tkapp", /*tp_name */
2899 sizeof(TkappObject), /*tp_basicsize */
2900 0, /*tp_itemsize */
2901 Tkapp_Dealloc, /*tp_dealloc */
2902 0, /*tp_print */
2903 Tkapp_GetAttr, /*tp_getattr */
2904 0, /*tp_setattr */
2905 0, /*tp_compare */
2906 0, /*tp_repr */
2907 0, /*tp_as_number */
2908 0, /*tp_as_sequence */
2909 0, /*tp_as_mapping */
2910 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00002911};
2912
Barry Warsawfa701a81997-01-16 00:15:11 +00002913
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002914
Guido van Rossum18468821994-06-20 07:49:28 +00002915/**** Tkinter Module ****/
2916
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002917typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002918 PyObject* tuple;
2919 int size; /* current size */
2920 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002921} FlattenContext;
2922
2923static int
2924_bump(FlattenContext* context, int size)
2925{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926 /* expand tuple to hold (at least) size new items.
2927 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002928
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002929 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002930
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002931 if (maxsize < context->size + size)
2932 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002933
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002934 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002935
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002936 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002937}
2938
2939static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002940_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002941{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002942 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002943
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002944 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002945
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002946 if (depth > 1000) {
2947 PyErr_SetString(PyExc_ValueError,
2948 "nesting too deep in _flatten");
2949 return 0;
2950 } else if (PyList_Check(item)) {
2951 size = PyList_GET_SIZE(item);
2952 /* preallocate (assume no nesting) */
2953 if (context->size + size > context->maxsize &&
2954 !_bump(context, size))
2955 return 0;
2956 /* copy items to output tuple */
2957 for (i = 0; i < size; i++) {
2958 PyObject *o = PyList_GET_ITEM(item, i);
2959 if (PyList_Check(o) || PyTuple_Check(o)) {
2960 if (!_flatten1(context, o, depth + 1))
2961 return 0;
2962 } else if (o != Py_None) {
2963 if (context->size + 1 > context->maxsize &&
2964 !_bump(context, 1))
2965 return 0;
2966 Py_INCREF(o);
2967 PyTuple_SET_ITEM(context->tuple,
2968 context->size++, o);
2969 }
2970 }
2971 } else if (PyTuple_Check(item)) {
2972 /* same, for tuples */
2973 size = PyTuple_GET_SIZE(item);
2974 if (context->size + size > context->maxsize &&
2975 !_bump(context, size))
2976 return 0;
2977 for (i = 0; i < size; i++) {
2978 PyObject *o = PyTuple_GET_ITEM(item, i);
2979 if (PyList_Check(o) || PyTuple_Check(o)) {
2980 if (!_flatten1(context, o, depth + 1))
2981 return 0;
2982 } else if (o != Py_None) {
2983 if (context->size + 1 > context->maxsize &&
2984 !_bump(context, 1))
2985 return 0;
2986 Py_INCREF(o);
2987 PyTuple_SET_ITEM(context->tuple,
2988 context->size++, o);
2989 }
2990 }
2991 } else {
2992 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2993 return 0;
2994 }
2995 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002996}
2997
2998static PyObject *
2999Tkinter_Flatten(PyObject* self, PyObject* args)
3000{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003001 FlattenContext context;
3002 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003003
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003004 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3005 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003006
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003007 context.maxsize = PySequence_Size(item);
3008 if (context.maxsize < 0)
3009 return NULL;
3010 if (context.maxsize == 0)
3011 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003012
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003013 context.tuple = PyTuple_New(context.maxsize);
3014 if (!context.tuple)
3015 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003016
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003017 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003018
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003019 if (!_flatten1(&context, item,0))
3020 return NULL;
3021
3022 if (_PyTuple_Resize(&context.tuple, context.size))
3023 return NULL;
3024
3025 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003026}
3027
Guido van Rossum18468821994-06-20 07:49:28 +00003028static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003029Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003030{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003031 char *screenName = NULL;
3032 char *baseName = NULL;
3033 char *className = NULL;
3034 int interactive = 0;
3035 int wantobjects = 0;
3036 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3037 int sync = 0; /* pass -sync to wish */
3038 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003040 baseName = strrchr(Py_GetProgramName(), '/');
3041 if (baseName != NULL)
3042 baseName++;
3043 else
3044 baseName = Py_GetProgramName();
3045 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003046
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003047 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3048 &screenName, &baseName, &className,
3049 &interactive, &wantobjects, &wantTk,
3050 &sync, &use))
3051 return NULL;
3052
3053 return (PyObject *) Tkapp_New(screenName, baseName, className,
3054 interactive, wantobjects, wantTk,
3055 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003056}
3057
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003058static PyObject *
3059Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3060{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003061 int new_val;
3062 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3063 return NULL;
3064 if (new_val < 0) {
3065 PyErr_SetString(PyExc_ValueError,
3066 "busywaitinterval must be >= 0");
3067 return NULL;
3068 }
3069 Tkinter_busywaitinterval = new_val;
3070 Py_INCREF(Py_None);
3071 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003072}
3073
3074static char setbusywaitinterval_doc[] =
3075"setbusywaitinterval(n) -> None\n\
3076\n\
3077Set the busy-wait interval in milliseconds between successive\n\
3078calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3079It should be set to a divisor of the maximum time between\n\
3080frames in an animation.";
3081
3082static PyObject *
3083Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3084{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003085 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003086}
3087
3088static char getbusywaitinterval_doc[] =
3089"getbusywaitinterval() -> int\n\
3090\n\
3091Return the current busy-wait interval between successive\n\
3092calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3093
Guido van Rossum18468821994-06-20 07:49:28 +00003094static PyMethodDef moduleMethods[] =
3095{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003096 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3097 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003098#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003099 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3100 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003101#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003102 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3103 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3104 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3105 {"quit", Tkapp_Quit, METH_VARARGS},
3106 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3107 setbusywaitinterval_doc},
3108 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3109 METH_NOARGS, getbusywaitinterval_doc},
3110 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003111};
3112
Guido van Rossum7bf15641998-05-22 18:28:17 +00003113#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003114
3115static int stdin_ready = 0;
3116
Guido van Rossumad4db171998-06-13 13:56:28 +00003117#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003118static void
Fred Drake509d79a2000-07-08 04:04:38 +00003119MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003120{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003121 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003122}
Guido van Rossumad4db171998-06-13 13:56:28 +00003123#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003124
Martin v. Löwisa9656492003-03-30 08:44:58 +00003125#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003126static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003127#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003128
Guido van Rossum18468821994-06-20 07:49:28 +00003129static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003130EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003131{
Guido van Rossumad4db171998-06-13 13:56:28 +00003132#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003133 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003134#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003135#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003136 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003137#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003138 stdin_ready = 0;
3139 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003140#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003141 tfile = fileno(stdin);
3142 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003143#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003144 while (!errorInCmd && !stdin_ready) {
3145 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003146#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003147 if (_kbhit()) {
3148 stdin_ready = 1;
3149 break;
3150 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003151#endif
3152#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003153 Py_BEGIN_ALLOW_THREADS
3154 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3155 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003156
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003157 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003158
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003159 tcl_tstate = NULL;
3160 if(tcl_lock)PyThread_release_lock(tcl_lock);
3161 if (result == 0)
3162 Sleep(Tkinter_busywaitinterval);
3163 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003164#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003165 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003166#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003167
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003168 if (result < 0)
3169 break;
3170 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003171#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003172 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003173#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003174 if (errorInCmd) {
3175 errorInCmd = 0;
3176 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3177 excInCmd = valInCmd = trbInCmd = NULL;
3178 PyErr_Print();
3179 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003180#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003181 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003182#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003183 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003184}
Guido van Rossum18468821994-06-20 07:49:28 +00003185
Guido van Rossum00d93061998-05-28 23:06:38 +00003186#endif
3187
Guido van Rossum7bf15641998-05-22 18:28:17 +00003188static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003189EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003190{
Guido van Rossum00d93061998-05-28 23:06:38 +00003191#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003192 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003193#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003194 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003195#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003196 PyOS_InputHook = EventHook;
3197 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003198#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003199}
3200
3201static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003202DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003203{
Guido van Rossum00d93061998-05-28 23:06:38 +00003204#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003205 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3206 PyOS_InputHook = NULL;
3207 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003208#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003209}
3210
Barry Warsawfa701a81997-01-16 00:15:11 +00003211
3212/* all errors will be checked in one fell swoop in init_tkinter() */
3213static void
Fred Drake509d79a2000-07-08 04:04:38 +00003214ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003215{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003216 PyObject *v = PyInt_FromLong(val);
3217 if (v) {
3218 PyDict_SetItemString(d, name, v);
3219 Py_DECREF(v);
3220 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003221}
3222static void
Fred Drake509d79a2000-07-08 04:04:38 +00003223ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003224{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003225 PyObject *v = PyString_FromString(val);
3226 if (v) {
3227 PyDict_SetItemString(d, name, v);
3228 Py_DECREF(v);
3229 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003230}
3231
3232
Mark Hammond62b1ab12002-07-23 06:31:15 +00003233PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003234init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003235{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003236 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003237
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003238 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003239
3240#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003241 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003242#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003243
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003244 m = Py_InitModule("_tkinter", moduleMethods);
3245 if (m == NULL)
3246 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003247
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003248 d = PyModule_GetDict(m);
3249 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3250 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003251
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003252 ins_long(d, "READABLE", TCL_READABLE);
3253 ins_long(d, "WRITABLE", TCL_WRITABLE);
3254 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3255 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3256 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3257 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3258 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3259 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3260 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3261 ins_string(d, "TK_VERSION", TK_VERSION);
3262 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003265
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003266 Py_TYPE(&Tktt_Type) = &PyType_Type;
3267 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003268
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003269 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3270 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003271
3272#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003273 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3274 * start waking up. Note that Tcl_FindExecutable will do this, this
3275 * code must be above it! The original warning from
3276 * tkMacOSXAppInit.c is copied below.
3277 *
3278 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3279 * Tcl interpreter for now. It probably should work to do this
3280 * in the other order, but for now it doesn't seem to.
3281 *
3282 */
3283 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003284#endif
3285
3286
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003287 /* This helps the dynamic loader; in Unicode aware Tcl versions
3288 it also helps Tcl find its encodings. */
3289 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003290
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003291 if (PyErr_Occurred())
3292 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003293
Guido van Rossum43ff8681998-07-14 18:02:13 +00003294#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003295 /* This was not a good idea; through <Destroy> bindings,
3296 Tcl_Finalize() may invoke Python code but at that point the
3297 interpreter and thread state have already been destroyed! */
3298 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003299#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003300
Guido van Rossum18468821994-06-20 07:49:28 +00003301}