blob: e31afae152d704a313d10261393d823bcc82c4af [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 Pitrouf95a1b32010-05-09 15:52:27 +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
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
Serhiy Storchaka35840562015-02-16 20:54:03 +020037 ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030038
Martin v. Löwis71e25a02002-10-01 18:08:06 +000039/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
40 making _tkinter correct for this API means to break earlier
41 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
42 earlier versions. Once Tcl releases before 8.4 don't need to be supported
43 anymore, this should go. */
44#define USE_COMPAT_CONST
45
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000046/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
47 it always; if Tcl is not threaded, the thread functions in
48 Tcl are empty. */
49#define TCL_THREADS
50
Jack Jansencb852442001-12-09 23:15:56 +000051#ifdef TK_FRAMEWORK
52#include <Tcl/tcl.h>
53#include <Tk/tk.h>
54#else
Guido van Rossum18468821994-06-20 07:49:28 +000055#include <tcl.h>
56#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000057#endif
Guido van Rossum18468821994-06-20 07:49:28 +000058
Guilherme Polo2d87e422009-04-10 22:19:09 +000059#include "tkinter.h"
60
Jason Tishlerbbe89612002-12-31 20:30:46 +000061/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000062#ifndef CONST84_RETURN
63#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000064#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000065#define CONST
66#endif
67
Guilherme Polo66917722009-02-09 22:35:27 +000068#if TK_VERSION_HEX < 0x08030102
69#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Serhiy Storchakaea134da2015-04-02 18:46:50 +030072#if TK_VERSION_HEX >= 0x08050000
73#define HAVE_LIBTOMMAMTH
74#include <tclTomMath.h>
75#endif
76
Jack Janseneddc1442003-11-20 01:44:59 +000077#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000078#define HAVE_CREATEFILEHANDLER
79#endif
80
Guido van Rossum00d93061998-05-28 23:06:38 +000081#ifdef HAVE_CREATEFILEHANDLER
82
Neal Norwitzd948a432006-01-08 01:08:55 +000083/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
84 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
85#ifndef TCL_UNIX_FD
86# ifdef TCL_WIN_SOCKET
87# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
88# else
89# define TCL_UNIX_FD 1
90# endif
91#endif
92
Guido van Rossum00d93061998-05-28 23:06:38 +000093/* Tcl_CreateFileHandler() changed several times; these macros deal with the
94 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
95 Unix, only because Jack added it back); when available on Windows, it only
96 applies to sockets. */
97
Guido van Rossum7bf15641998-05-22 18:28:17 +000098#ifdef MS_WINDOWS
99#define FHANDLETYPE TCL_WIN_SOCKET
100#else
101#define FHANDLETYPE TCL_UNIX_FD
102#endif
103
Guido van Rossum00d93061998-05-28 23:06:38 +0000104/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
105 which uses this to handle Tcl events while the user is typing commands. */
106
107#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000108#define WAIT_FOR_STDIN
109#endif
110
Guido van Rossum00d93061998-05-28 23:06:38 +0000111#endif /* HAVE_CREATEFILEHANDLER */
112
Guido van Rossumad4db171998-06-13 13:56:28 +0000113#ifdef MS_WINDOWS
114#include <conio.h>
115#define WAIT_FOR_STDIN
116#endif
117
Guido van Rossum00d93061998-05-28 23:06:38 +0000118#ifdef WITH_THREAD
119
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000120/* The threading situation is complicated. Tcl is not thread-safe, except
121 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000122
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300123 So we need to use a lock around all uses of Tcl. Previously, the
124 Python interpreter lock was used for this. However, this causes
125 problems when other Python threads need to run while Tcl is blocked
126 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000127
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300128 To solve this problem, a separate lock for Tcl is introduced.
129 Holding it is incompatible with holding Python's interpreter lock.
130 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000131
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300132 ENTER_TCL and LEAVE_TCL are brackets, just like
133 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
134 used whenever a call into Tcl is made that could call an event
135 handler, or otherwise affect the state of a Tcl interpreter. These
136 assume that the surrounding code has the Python interpreter lock;
137 inside the brackets, the Python interpreter lock has been released
138 and the lock for Tcl has been acquired.
139
140 Sometimes, it is necessary to have both the Python lock and the Tcl
141 lock. (For example, when transferring data from the Tcl
142 interpreter result to a Python string object.) This can be done by
143 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
144 reacquires the Python lock (and restores the thread state) but
145 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
146 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000147
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000148 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300149 handlers when the handler needs to use Python. Such event handlers
150 are entered while the lock for Tcl is held; the event handler
151 presumably needs to use Python. ENTER_PYTHON releases the lock for
152 Tcl and acquires the Python interpreter lock, restoring the
153 appropriate thread state, and LEAVE_PYTHON releases the Python
154 interpreter lock and re-acquires the lock for Tcl. It is okay for
155 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
156 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000157
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300158 These locks expand to several statements and brackets; they should
159 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000160
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300161 If Tcl is threaded, this approach won't work anymore. The Tcl
162 interpreter is only valid in the thread that created it, and all Tk
163 activity must happen in this thread, also. That means that the
164 mainloop must be invoked in the thread that created the
165 interpreter. Invoking commands from other threads is possible;
166 _tkinter will queue an event for the interpreter thread, which will
167 then execute the command and pass back the result. If the main
168 thread is not in the mainloop, and invoking commands causes an
169 exception; if the main loop is running but not processing events,
170 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000171
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300172 In addition, for a threaded Tcl, a single global tcl_tstate won't
173 be sufficient anymore, since multiple Tcl interpreters may
174 simultaneously dispatch in different threads. So we use the Tcl TLS
175 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000176
Guido van Rossum00d93061998-05-28 23:06:38 +0000177*/
178
Guido van Rossum65d5b571998-12-21 19:32:43 +0000179static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000180
181#ifdef TCL_THREADS
182static Tcl_ThreadDataKey state_key;
183typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300184#define tcl_tstate \
185 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000186#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000187static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000188#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000189
190#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
192 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000193
194#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300195 tcl_tstate = NULL; \
196 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000197
Guido van Rossum62320c91998-06-15 04:36:09 +0000198#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000200
201#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000203
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000204#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300206 if(tcl_lock) \
207 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000208
209#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 { PyThreadState *tstate = PyEval_SaveThread(); \
211 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212
213#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000214 if (((TkappObject *)self)->threaded && \
215 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300216 PyErr_SetString(PyExc_RuntimeError, \
217 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000218 return 0; \
219 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000220
221#else
222
223#define ENTER_TCL
224#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000225#define ENTER_OVERLAP
226#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000227#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000228#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000229#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000230
231#endif
232
Guido van Rossum97867b21996-08-08 19:09:53 +0000233#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000234#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000235#endif
236
Guido van Rossum18468821994-06-20 07:49:28 +0000237/**** Tkapp Object Declaration ****/
238
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300239static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000240
Guido van Rossum00d93061998-05-28 23:06:38 +0000241typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 PyObject_HEAD
243 Tcl_Interp *interp;
244 int wantobjects;
245 int threaded; /* True if tcl_platform[threaded] */
246 Tcl_ThreadId thread_id;
247 int dispatching;
248 /* We cannot include tclInt.h, as this is internal.
249 So we cache interesting types here. */
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300250 const Tcl_ObjType *OldBooleanType;
251 const Tcl_ObjType *BooleanType;
252 const Tcl_ObjType *ByteArrayType;
253 const Tcl_ObjType *DoubleType;
254 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300255 const Tcl_ObjType *WideIntType;
256 const Tcl_ObjType *BignumType;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300257 const Tcl_ObjType *ListType;
258 const Tcl_ObjType *ProcBodyType;
259 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000260} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000261
Guido van Rossum18468821994-06-20 07:49:28 +0000262#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000263#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000264
Guido van Rossum35d43371997-08-02 00:09:09 +0000265#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000266(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000267
Barry Warsawfa701a81997-01-16 00:15:11 +0000268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000269
Guido van Rossum18468821994-06-20 07:49:28 +0000270/**** Error Handling ****/
271
272static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000273static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000274static int errorInCmd = 0;
275static PyObject *excInCmd;
276static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000277static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000278
Guilherme Polob681df42009-02-09 22:33:59 +0000279#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000280static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000281#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000283
Guido van Rossum18468821994-06-20 07:49:28 +0000284static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000285Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000286{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
288 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000289}
290
Barry Warsawfa701a81997-01-16 00:15:11 +0000291
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000292
Guido van Rossum18468821994-06-20 07:49:28 +0000293/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000294
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000295static int Tkinter_busywaitinterval = 20;
296
Guido van Rossum00d93061998-05-28 23:06:38 +0000297#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000298#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000299
Guido van Rossum00d93061998-05-28 23:06:38 +0000300/* Millisecond sleep() for Unix platforms. */
301
302static void
Fred Drake509d79a2000-07-08 04:04:38 +0000303Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000304{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 /* XXX Too bad if you don't have select(). */
306 struct timeval t;
307 t.tv_sec = milli/1000;
308 t.tv_usec = (milli%1000) * 1000;
309 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000310}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000311#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000312
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000313/* Wait up to 1s for the mainloop to come up. */
314
315static int
316WaitForMainloop(TkappObject* self)
317{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 int i;
319 for (i = 0; i < 10; i++) {
320 if (self->dispatching)
321 return 1;
322 Py_BEGIN_ALLOW_THREADS
323 Sleep(100);
324 Py_END_ALLOW_THREADS
325 }
326 if (self->dispatching)
327 return 1;
328 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
329 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000330}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000331#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000332
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334
Guido van Rossum18468821994-06-20 07:49:28 +0000335#define ARGSZ 64
336
Barry Warsawfa701a81997-01-16 00:15:11 +0000337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338
Guido van Rossum18468821994-06-20 07:49:28 +0000339static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200340unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
341{
342 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
343 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
344 /* Tcl encodes null character as \xc0\x80 */
345 if (memchr(s, '\xc0', size)) {
346 char *buf, *q;
347 const char *e = s + size;
348 PyErr_Clear();
349 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300350 if (buf == NULL) {
351 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200352 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300353 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200354 while (s != e) {
355 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
356 *q++ = '\0';
357 s += 2;
358 }
359 else
360 *q++ = *s++;
361 }
362 s = buf;
363 size = q - s;
364 r = PyUnicode_DecodeUTF8(s, size, NULL);
365 PyMem_Free(buf);
366 }
367 }
368 return r;
369}
370
371static PyObject *
372unicodeFromTclString(const char *s)
373{
374 return unicodeFromTclStringAndSize(s, strlen(s));
375}
376
377static PyObject *
378unicodeFromTclObj(Tcl_Obj *value)
379{
380 int len;
381 char *s = Tcl_GetStringFromObj(value, &len);
382 return unicodeFromTclStringAndSize(s, len);
383}
384
385
386static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000387Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000388{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000389 int argc;
390 char **argv;
391 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000392
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000393 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300394 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 }
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000397 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
398 /* Not a list.
399 * Could be a quoted string containing funnies, e.g. {"}.
400 * Return the string itself.
401 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200402 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 }
Guido van Rossum18468821994-06-20 07:49:28 +0000404
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 if (argc == 0)
406 v = PyUnicode_FromString("");
407 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200408 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 else if ((v = PyTuple_New(argc)) != NULL) {
410 int i;
411 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 for (i = 0; i < argc; i++) {
414 if ((w = Split(argv[i])) == NULL) {
415 Py_DECREF(v);
416 v = NULL;
417 break;
418 }
419 PyTuple_SetItem(v, i, w);
420 }
421 }
422 Tcl_Free(FREECAST argv);
423 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000424}
425
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300426/* In some cases, Tcl will still return strings that are supposed to
427 be lists. SplitObj walks through a nested tuple, finding string
428 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000429
Martin v. Löwis59683e82008-06-13 07:50:45 +0000430static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000431SplitObj(PyObject *arg)
432{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 if (PyTuple_Check(arg)) {
434 int i, size;
435 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000436
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000437 size = PyTuple_Size(arg);
438 result = NULL;
439 /* Recursively invoke SplitObj for all tuple items.
440 If this does not return a new object, no action is
441 needed. */
442 for(i = 0; i < size; i++) {
443 elem = PyTuple_GetItem(arg, i);
444 newelem = SplitObj(elem);
445 if (!newelem) {
446 Py_XDECREF(result);
447 return NULL;
448 }
449 if (!result) {
450 int k;
451 if (newelem == elem) {
452 Py_DECREF(newelem);
453 continue;
454 }
455 result = PyTuple_New(size);
456 if (!result)
457 return NULL;
458 for(k = 0; k < i; k++) {
459 elem = PyTuple_GetItem(arg, k);
460 Py_INCREF(elem);
461 PyTuple_SetItem(result, k, elem);
462 }
463 }
464 PyTuple_SetItem(result, i, newelem);
465 }
466 if (result)
467 return result;
468 /* Fall through, returning arg. */
469 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300470 else if (PyUnicode_Check(arg)) {
471 int argc;
472 char **argv;
473 char *list = PyUnicode_AsUTF8(arg);
474
475 if (list == NULL ||
476 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
477 Py_INCREF(arg);
478 return arg;
479 }
480 Tcl_Free(FREECAST argv);
481 if (argc > 1)
482 return Split(list);
483 /* Fall through, returning arg. */
484 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 else if (PyBytes_Check(arg)) {
486 int argc;
487 char **argv;
488 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
491 Py_INCREF(arg);
492 return arg;
493 }
494 Tcl_Free(FREECAST argv);
495 if (argc > 1)
496 return Split(PyBytes_AsString(arg));
497 /* Fall through, returning arg. */
498 }
499 Py_INCREF(arg);
500 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000501}
Barry Warsawfa701a81997-01-16 00:15:11 +0000502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000503
Guido van Rossum18468821994-06-20 07:49:28 +0000504/**** Tkapp Object ****/
505
506#ifndef WITH_APPINIT
507int
Fred Drake509d79a2000-07-08 04:04:38 +0000508Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000509{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000510 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000512 if (Tcl_Init(interp) == TCL_ERROR) {
513 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
514 return TCL_ERROR;
515 }
Guilherme Polob681df42009-02-09 22:33:59 +0000516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 _tkinter_skip_tk_init = Tcl_GetVar(interp,
518 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
519 if (_tkinter_skip_tk_init != NULL &&
520 strcmp(_tkinter_skip_tk_init, "1") == 0) {
521 return TCL_OK;
522 }
Guilherme Polob681df42009-02-09 22:33:59 +0000523
524#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 if (tk_load_failed) {
526 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
527 return TCL_ERROR;
528 }
Guilherme Polob681df42009-02-09 22:33:59 +0000529#endif
530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000532#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000534#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000535 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
536 return TCL_ERROR;
537 }
Guilherme Polob681df42009-02-09 22:33:59 +0000538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000540}
541#endif /* !WITH_APPINIT */
542
Guido van Rossum18468821994-06-20 07:49:28 +0000543
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544
Barry Warsawfa701a81997-01-16 00:15:11 +0000545
546/* Initialize the Tk application; see the `main' function in
547 * `tkMain.c'.
548 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000549
Thomas Wouters58d05102000-07-24 14:43:35 +0000550static void EnableEventHook(void); /* Forward */
551static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000552
Barry Warsawfa701a81997-01-16 00:15:11 +0000553static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000554Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000555 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000556{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 TkappObject *v;
558 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000559
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300560 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 if (v == NULL)
562 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200563 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000564
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000565 v->interp = Tcl_CreateInterp();
566 v->wantobjects = wantobjects;
567 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
568 TCL_GLOBAL_ONLY) != NULL;
569 v->thread_id = Tcl_GetCurrentThread();
570 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000571
572#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300574 PyErr_SetString(PyExc_RuntimeError,
575 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000576 Py_DECREF(v);
577 return 0;
578 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000579#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000580#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000581 if (v->threaded && tcl_lock) {
582 /* If Tcl is threaded, we don't need the lock. */
583 PyThread_free_lock(tcl_lock);
584 tcl_lock = NULL;
585 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000586#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000587
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300588 v->OldBooleanType = Tcl_GetObjType("boolean");
589 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000590 v->ByteArrayType = Tcl_GetObjType("bytearray");
591 v->DoubleType = Tcl_GetObjType("double");
592 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300593 v->WideIntType = Tcl_GetObjType("wideInt");
594 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000595 v->ListType = Tcl_GetObjType("list");
596 v->ProcBodyType = Tcl_GetObjType("procbody");
597 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000598
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000599 /* Delete the 'exit' command, which can screw things up */
600 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000602 if (screenName != NULL)
603 Tcl_SetVar2(v->interp, "env", "DISPLAY",
604 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000605
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 if (interactive)
607 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
608 else
609 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000611 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka07940882014-09-11 10:38:54 +0300612 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 if (!argv0) {
614 PyErr_NoMemory();
615 Py_DECREF(v);
616 return NULL;
617 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000619 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200620 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
621 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
623 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625 if (! wantTk) {
626 Tcl_SetVar(v->interp,
627 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
628 }
Guilherme Polob681df42009-02-09 22:33:59 +0000629#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 else if (tk_load_failed) {
631 Tcl_SetVar(v->interp,
632 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
633 }
Guilherme Polob681df42009-02-09 22:33:59 +0000634#endif
David Aschere2b4b322004-02-18 05:59:53 +0000635
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 /* some initial arguments need to be in argv */
637 if (sync || use) {
638 char *args;
639 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 if (sync)
642 len += sizeof "-sync";
643 if (use)
644 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000645
Serhiy Storchaka07940882014-09-11 10:38:54 +0300646 args = (char*)attemptckalloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 if (!args) {
648 PyErr_NoMemory();
649 Py_DECREF(v);
650 return NULL;
651 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 args[0] = '\0';
654 if (sync)
655 strcat(args, "-sync");
656 if (use) {
657 if (sync)
658 strcat(args, " ");
659 strcat(args, "-use ");
660 strcat(args, use);
661 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000662
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000663 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
664 ckfree(args);
665 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 if (Tcl_AppInit(v->interp) != TCL_OK) {
668 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000669#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 if (wantTk) {
671 const char *_tkinter_tk_failed;
672 _tkinter_tk_failed = Tcl_GetVar(v->interp,
673 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 if ( _tkinter_tk_failed != NULL &&
676 strcmp(_tkinter_tk_failed, "1") == 0) {
677 tk_load_failed = 1;
678 }
679 }
Guilherme Polob681df42009-02-09 22:33:59 +0000680#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 Py_DECREF((PyObject *)v);
682 return (TkappObject *)result;
683 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000685 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000688}
689
Barry Warsawfa701a81997-01-16 00:15:11 +0000690
Benjamin Peterson5879d412009-03-30 14:51:56 +0000691#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000692static void
693Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000695{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 Py_BEGIN_ALLOW_THREADS;
697 Tcl_MutexLock(mutex);
698 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
699 Tcl_ThreadAlert(self->thread_id);
700 Tcl_ConditionWait(cond, mutex, NULL);
701 Tcl_MutexUnlock(mutex);
702 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000703}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000704#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706
Guido van Rossum18468821994-06-20 07:49:28 +0000707/** Tcl Eval **/
708
Martin v. Löwisffad6332002-11-26 09:28:05 +0000709typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 PyObject_HEAD
711 Tcl_Obj *value;
712 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000713} PyTclObject;
714
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300715static PyObject *PyTclObject_Type;
716#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000717
718static PyObject *
719newPyTclObject(Tcl_Obj *arg)
720{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300722 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 if (self == NULL)
724 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200725 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 Tcl_IncrRefCount(arg);
727 self->value = arg;
728 self->string = NULL;
729 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000730}
731
732static void
733PyTclObject_dealloc(PyTclObject *self)
734{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200735 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 Tcl_DecrRefCount(self->value);
737 Py_XDECREF(self->string);
738 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200739 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000740}
741
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000742static char*
743PyTclObject_TclString(PyObject *self)
744{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000745 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000746}
747
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000748/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000749PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000750"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000751
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000752static PyObject *
753PyTclObject_string(PyTclObject *self, void *ignored)
754{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200756 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 if (!self->string)
758 return NULL;
759 }
760 Py_INCREF(self->string);
761 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000762}
763
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000764static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000765PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000766{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200767 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000768 Py_INCREF(self->string);
769 return self->string;
770 }
771 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200772 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000773}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000774
Martin v. Löwisffad6332002-11-26 09:28:05 +0000775static PyObject *
776PyTclObject_repr(PyTclObject *self)
777{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300778 PyObject *repr, *str = PyTclObject_str(self, NULL);
779 if (str == NULL)
780 return NULL;
781 repr = PyUnicode_FromFormat("<%s object: %R>",
782 self->value->typePtr->name, str);
783 Py_DECREF(str);
784 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000785}
786
Mark Dickinson211c6252009-02-01 10:28:51 +0000787#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
788
789static PyObject *
790PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000791{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 int result;
793 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000794
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000795 /* neither argument should be NULL, unless something's gone wrong */
796 if (self == NULL || other == NULL) {
797 PyErr_BadInternalCall();
798 return NULL;
799 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 /* both arguments should be instances of PyTclObject */
802 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
803 v = Py_NotImplemented;
804 goto finished;
805 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000806
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 if (self == other)
808 /* fast path when self and other are identical */
809 result = 0;
810 else
811 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
812 Tcl_GetString(((PyTclObject *)other)->value));
813 /* Convert return value to a Boolean */
814 switch (op) {
815 case Py_EQ:
816 v = TEST_COND(result == 0);
817 break;
818 case Py_NE:
819 v = TEST_COND(result != 0);
820 break;
821 case Py_LE:
822 v = TEST_COND(result <= 0);
823 break;
824 case Py_GE:
825 v = TEST_COND(result >= 0);
826 break;
827 case Py_LT:
828 v = TEST_COND(result < 0);
829 break;
830 case Py_GT:
831 v = TEST_COND(result > 0);
832 break;
833 default:
834 PyErr_BadArgument();
835 return NULL;
836 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000837 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000838 Py_INCREF(v);
839 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000840}
841
Martin v. Löwis39195712003-01-04 00:33:13 +0000842PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
843
Martin v. Löwisffad6332002-11-26 09:28:05 +0000844static PyObject*
845get_typename(PyTclObject* obj, void* ignored)
846{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200847 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848}
849
Martin v. Löwis39195712003-01-04 00:33:13 +0000850
Martin v. Löwisffad6332002-11-26 09:28:05 +0000851static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000852 {"typename", (getter)get_typename, NULL, get_typename__doc__},
853 {"string", (getter)PyTclObject_string, NULL,
854 PyTclObject_string__doc__},
855 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000856};
857
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300858static PyType_Slot PyTclObject_Type_slots[] = {
859 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
860 {Py_tp_repr, (reprfunc)PyTclObject_repr},
861 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200862 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300863 {Py_tp_richcompare, PyTclObject_richcompare},
864 {Py_tp_getset, PyTclObject_getsetlist},
865 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000866};
867
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300868static PyType_Spec PyTclObject_Type_spec = {
869 "_tkinter.Tcl_Obj",
870 sizeof(PyTclObject),
871 0,
872 Py_TPFLAGS_DEFAULT,
873 PyTclObject_Type_slots,
874};
875
876
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300877#if PY_SIZE_MAX > INT_MAX
878#define CHECK_STRING_LENGTH(s) do { \
879 if (s != NULL && strlen(s) >= INT_MAX) { \
880 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
881 return NULL; \
882 } } while(0)
883#else
884#define CHECK_STRING_LENGTH(s)
885#endif
886
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300887#ifdef HAVE_LIBTOMMAMTH
888static Tcl_Obj*
889asBignumObj(PyObject *value)
890{
891 Tcl_Obj *result;
892 int neg;
893 PyObject *hexstr;
894 char *hexchars;
895 mp_int bigValue;
896
897 neg = Py_SIZE(value) < 0;
898 hexstr = _PyLong_Format(value, 16);
899 if (hexstr == NULL)
900 return NULL;
901 hexchars = PyUnicode_AsUTF8(hexstr);
902 if (hexchars == NULL) {
903 Py_DECREF(hexstr);
904 return NULL;
905 }
906 hexchars += neg + 2; /* skip sign and "0x" */
907 mp_init(&bigValue);
908 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
909 mp_clear(&bigValue);
910 Py_DECREF(hexstr);
911 PyErr_NoMemory();
912 return NULL;
913 }
914 Py_DECREF(hexstr);
915 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
916 result = Tcl_NewBignumObj(&bigValue);
917 mp_clear(&bigValue);
918 if (result == NULL) {
919 PyErr_NoMemory();
920 return NULL;
921 }
922 return result;
923}
924#endif
925
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000926static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000927AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000928{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000930
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000931 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300932 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
933 PyBytes_GET_SIZE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300934
935 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300937
938 if (PyLong_CheckExact(value)) {
939 int overflow;
940 long longValue;
941#ifdef TCL_WIDE_INT_TYPE
942 Tcl_WideInt wideValue;
943#endif
944 longValue = PyLong_AsLongAndOverflow(value, &overflow);
945 if (!overflow) {
946 return Tcl_NewLongObj(longValue);
947 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000948 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300949 fall through to wideInt handling. */
950#ifdef TCL_WIDE_INT_TYPE
951 if (_PyLong_AsByteArray((PyLongObject *)value,
952 (unsigned char *)(void *)&wideValue,
953 sizeof(wideValue),
954 PY_LITTLE_ENDIAN,
955 /* signed */ 1) == 0) {
956 return Tcl_NewWideIntObj(wideValue);
957 }
958 PyErr_Clear();
959#endif
960 /* If there is an overflow in the wideInt conversion,
961 fall through to bignum handling. */
962#ifdef HAVE_LIBTOMMAMTH
963 return asBignumObj(value);
964#endif
965 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000966 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000967 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300968
969 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300971
972 if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300973 Tcl_Obj **argv;
974 Py_ssize_t size, i;
975
976 size = PyTuple_Size(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300977 if (size == 0)
978 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300979 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
980 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
981 return NULL;
982 }
Serhiy Storchaka07940882014-09-11 10:38:54 +0300983 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 if(!argv)
985 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300986 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000987 argv[i] = AsObj(PyTuple_GetItem(value,i));
988 result = Tcl_NewListObj(PyTuple_Size(value), argv);
989 ckfree(FREECAST argv);
990 return result;
991 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300992
993 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200994 void *inbuf;
995 Py_ssize_t size;
996 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 Tcl_UniChar *outbuf = NULL;
998 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200999 size_t allocsize;
1000
1001 if (PyUnicode_READY(value) == -1)
1002 return NULL;
1003
1004 inbuf = PyUnicode_DATA(value);
1005 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001006 if (size == 0)
1007 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001008 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1009 PyErr_SetString(PyExc_OverflowError, "string is too long");
1010 return NULL;
1011 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001012 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001013 if (kind == sizeof(Tcl_UniChar))
1014 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001015 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Serhiy Storchaka07940882014-09-11 10:38:54 +03001016 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001017 /* Else overflow occurred, and we take the next exit */
1018 if (!outbuf) {
1019 PyErr_NoMemory();
1020 return NULL;
1021 }
1022 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001023 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1024 /* We cannot test for sizeof(Tcl_UniChar) directly,
1025 so we test for UTF-8 size instead. */
1026#if TCL_UTF_MAX == 3
1027 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001028 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001029 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001030 "character U+%x is above the range "
1031 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001032 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001033 ckfree(FREECAST outbuf);
1034 return NULL;
1035 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001036#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001037 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001038 }
1039 result = Tcl_NewUnicodeObj(outbuf, size);
1040 ckfree(FREECAST outbuf);
1041 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001043
1044 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 Tcl_Obj *v = ((PyTclObject*)value)->value;
1046 Tcl_IncrRefCount(v);
1047 return v;
1048 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001049
1050 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 PyObject *v = PyObject_Str(value);
1052 if (!v)
1053 return 0;
1054 result = AsObj(v);
1055 Py_DECREF(v);
1056 return result;
1057 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001058}
1059
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001060static PyObject *
1061fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1062{
1063 int boolValue;
1064 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1065 return Tkinter_Error(tkapp);
1066 return PyBool_FromLong(boolValue);
1067}
1068
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001069#ifdef TCL_WIDE_INT_TYPE
1070static PyObject*
1071fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1072{
1073 Tcl_WideInt wideValue;
1074 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1075#ifdef HAVE_LONG_LONG
1076 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1077 return PyLong_FromLongLong(wideValue);
1078#endif
1079 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1080 sizeof(wideValue),
1081 PY_LITTLE_ENDIAN,
1082 /* signed */ 1);
1083 }
1084 return NULL;
1085}
1086#endif
1087
1088#ifdef HAVE_LIBTOMMAMTH
1089static PyObject*
1090fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1091{
1092 mp_int bigValue;
1093 unsigned long numBytes;
1094 unsigned char *bytes;
1095 PyObject *res;
1096
1097 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1098 return Tkinter_Error(tkapp);
1099 numBytes = mp_unsigned_bin_size(&bigValue);
1100 bytes = PyMem_Malloc(numBytes);
1101 if (bytes == NULL) {
1102 mp_clear(&bigValue);
1103 return PyErr_NoMemory();
1104 }
1105 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1106 &numBytes) != MP_OKAY) {
1107 mp_clear(&bigValue);
1108 PyMem_Free(bytes);
1109 return PyErr_NoMemory();
1110 }
1111 res = _PyLong_FromByteArray(bytes, numBytes,
1112 /* big-endian */ 0,
1113 /* unsigned */ 0);
1114 PyMem_Free(bytes);
1115 if (res != NULL && bigValue.sign == MP_NEG) {
1116 PyObject *res2 = PyNumber_Negative(res);
1117 Py_DECREF(res);
1118 res = res2;
1119 }
1120 mp_clear(&bigValue);
1121 return res;
1122}
1123#endif
1124
Martin v. Löwisffad6332002-11-26 09:28:05 +00001125static PyObject*
1126FromObj(PyObject* tkapp, Tcl_Obj *value)
1127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 PyObject *result = NULL;
1129 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001130 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001132 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001133 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001135
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001136 if (value->typePtr == app->BooleanType ||
1137 value->typePtr == app->OldBooleanType) {
1138 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 if (value->typePtr == app->ByteArrayType) {
1142 int size;
1143 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1144 return PyBytes_FromStringAndSize(data, size);
1145 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001146
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 if (value->typePtr == app->DoubleType) {
1148 return PyFloat_FromDouble(value->internalRep.doubleValue);
1149 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001152 long longValue;
1153 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1154 return PyLong_FromLong(longValue);
1155 /* If there is an error in the long conversion,
1156 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001159#ifdef TCL_WIDE_INT_TYPE
1160 if (value->typePtr == app->IntType ||
1161 value->typePtr == app->WideIntType) {
1162 result = fromWideIntObj(tkapp, value);
1163 if (result != NULL || PyErr_Occurred())
1164 return result;
1165 Tcl_ResetResult(interp);
1166 /* If there is an error in the wideInt conversion,
1167 fall through to bignum handling. */
1168 }
1169#endif
1170
1171#ifdef HAVE_LIBTOMMAMTH
1172 if (value->typePtr == app->IntType ||
1173 value->typePtr == app->WideIntType ||
1174 value->typePtr == app->BignumType) {
1175 return fromBignumObj(tkapp, value);
1176 }
1177#endif
1178
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 if (value->typePtr == app->ListType) {
1180 int size;
1181 int i, status;
1182 PyObject *elem;
1183 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001184
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001185 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001186 if (status == TCL_ERROR)
1187 return Tkinter_Error(tkapp);
1188 result = PyTuple_New(size);
1189 if (!result)
1190 return NULL;
1191 for (i = 0; i < size; i++) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001192 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 if (status == TCL_ERROR) {
1194 Py_DECREF(result);
1195 return Tkinter_Error(tkapp);
1196 }
1197 elem = FromObj(tkapp, tcl_elem);
1198 if (!elem) {
1199 Py_DECREF(result);
1200 return NULL;
1201 }
1202 PyTuple_SetItem(result, i, elem);
1203 }
1204 return result;
1205 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001207 if (value->typePtr == app->ProcBodyType) {
1208 /* fall through: return tcl object. */
1209 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001212 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001213 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001214 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001215 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001217#if TK_VERSION_HEX >= 0x08050000
1218 if (app->BooleanType == NULL &&
1219 strcmp(value->typePtr->name, "booleanString") == 0) {
1220 /* booleanString type is not registered in Tcl */
1221 app->BooleanType = value->typePtr;
1222 return fromBoolean(tkapp, value);
1223 }
1224#endif
1225
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001226#ifdef HAVE_LIBTOMMAMTH
1227 if (app->BignumType == NULL &&
1228 strcmp(value->typePtr->name, "bignum") == 0) {
1229 /* bignum type is not registered in Tcl */
1230 app->BignumType = value->typePtr;
1231 return fromBignumObj(tkapp, value);
1232 }
1233#endif
1234
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001235 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001236}
1237
Benjamin Peterson5879d412009-03-30 14:51:56 +00001238#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001239/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240TCL_DECLARE_MUTEX(call_mutex)
1241
1242typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001243 Tcl_Event ev; /* Must be first */
1244 TkappObject *self;
1245 PyObject *args;
1246 int flags;
1247 PyObject **res;
1248 PyObject **exc_type, **exc_value, **exc_tb;
1249 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001250} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001251#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252
1253void
1254Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001255{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001256 int i;
1257 for (i = 0; i < objc; i++)
1258 Tcl_DecrRefCount(objv[i]);
1259 if (objv != objStore)
1260 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261}
Guido van Rossum18468821994-06-20 07:49:28 +00001262
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001263/* Convert Python objects to Tcl objects. This must happen in the
1264 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001265
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001266static Tcl_Obj**
1267Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1268{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001269 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001270 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001271 if (args == NULL)
1272 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001273
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001274 else if (!PyTuple_Check(args)) {
1275 objv[0] = AsObj(args);
1276 if (objv[0] == 0)
1277 goto finally;
1278 objc = 1;
1279 Tcl_IncrRefCount(objv[0]);
1280 }
1281 else {
1282 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001285 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1286 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1287 return NULL;
1288 }
Serhiy Storchaka07940882014-09-11 10:38:54 +03001289 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001290 if (objv == NULL) {
1291 PyErr_NoMemory();
1292 objc = 0;
1293 goto finally;
1294 }
1295 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001297 for (i = 0; i < objc; i++) {
1298 PyObject *v = PyTuple_GetItem(args, i);
1299 if (v == Py_None) {
1300 objc = i;
1301 break;
1302 }
1303 objv[i] = AsObj(v);
1304 if (!objv[i]) {
1305 /* Reset objc, so it attempts to clear
1306 objects only up to i. */
1307 objc = i;
1308 goto finally;
1309 }
1310 Tcl_IncrRefCount(objv[i]);
1311 }
1312 }
1313 *pobjc = objc;
1314 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001315finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 Tkapp_CallDeallocArgs(objv, objStore, objc);
1317 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001318}
Guido van Rossum212643f1998-04-29 16:22:14 +00001319
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001321
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001322static PyObject*
1323Tkapp_CallResult(TkappObject *self)
1324{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001326 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 /* Not sure whether the IncrRef is necessary, but something
1329 may overwrite the interpreter result while we are
1330 converting it. */
1331 Tcl_IncrRefCount(value);
1332 res = FromObj((PyObject*)self, value);
1333 Tcl_DecrRefCount(value);
1334 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001335 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 }
1337 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338}
Guido van Rossum632de272000-03-29 00:19:50 +00001339
Benjamin Peterson5879d412009-03-30 14:51:56 +00001340#ifdef WITH_THREAD
1341
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342/* Tkapp_CallProc is the event procedure that is executed in the context of
1343 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1344 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001345
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001346static int
1347Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1348{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 Tcl_Obj *objStore[ARGSZ];
1350 Tcl_Obj **objv;
1351 int objc;
1352 int i;
1353 ENTER_PYTHON
1354 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1355 if (!objv) {
1356 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1357 *(e->res) = NULL;
1358 }
1359 LEAVE_PYTHON
1360 if (!objv)
1361 goto done;
1362 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1363 ENTER_PYTHON
1364 if (i == TCL_ERROR) {
1365 *(e->res) = NULL;
1366 *(e->exc_type) = NULL;
1367 *(e->exc_tb) = NULL;
1368 *(e->exc_value) = PyObject_CallFunction(
1369 Tkinter_TclError, "s",
1370 Tcl_GetStringResult(e->self->interp));
1371 }
1372 else {
1373 *(e->res) = Tkapp_CallResult(e->self);
1374 }
1375 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001378done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 /* Wake up calling thread. */
1380 Tcl_MutexLock(&call_mutex);
1381 Tcl_ConditionNotify(e->done);
1382 Tcl_MutexUnlock(&call_mutex);
1383 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001384}
1385
Benjamin Peterson5879d412009-03-30 14:51:56 +00001386#endif
1387
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001388/* This is the main entry point for calling a Tcl command.
1389 It supports three cases, with regard to threading:
1390 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1391 the context of the calling thread.
1392 2. Tcl is threaded, caller of the command is in the interpreter thread:
1393 Execute the command in the calling thread. Since the Tcl lock will
1394 not be used, we can merge that with case 1.
1395 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1396 the interpreter thread. Allocation of Tcl objects needs to occur in the
1397 interpreter thread, so we ship the PyObject* args to the target thread,
1398 and perform processing there. */
1399
1400static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001401Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001402{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001403 Tcl_Obj *objStore[ARGSZ];
1404 Tcl_Obj **objv = NULL;
1405 int objc, i;
1406 PyObject *res = NULL;
1407 TkappObject *self = (TkappObject*)selfptr;
1408 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001409
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001410 /* If args is a single tuple, replace with contents of tuple */
1411 if (1 == PyTuple_Size(args)){
1412 PyObject* item = PyTuple_GetItem(args, 0);
1413 if (PyTuple_Check(item))
1414 args = item;
1415 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001416#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001417 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1418 /* We cannot call the command directly. Instead, we must
1419 marshal the parameters to the interpreter thread. */
1420 Tkapp_CallEvent *ev;
1421 Tcl_Condition cond = NULL;
1422 PyObject *exc_type, *exc_value, *exc_tb;
1423 if (!WaitForMainloop(self))
1424 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001425 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1426 if (ev == NULL) {
1427 PyErr_NoMemory();
1428 return NULL;
1429 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001430 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1431 ev->self = self;
1432 ev->args = args;
1433 ev->res = &res;
1434 ev->exc_type = &exc_type;
1435 ev->exc_value = &exc_value;
1436 ev->exc_tb = &exc_tb;
1437 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001438
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001439 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 if (res == NULL) {
1442 if (exc_type)
1443 PyErr_Restore(exc_type, exc_value, exc_tb);
1444 else
1445 PyErr_SetObject(Tkinter_TclError, exc_value);
1446 }
1447 Tcl_ConditionFinalize(&cond);
1448 }
1449 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001450#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 objv = Tkapp_CallArgs(args, objStore, &objc);
1454 if (!objv)
1455 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001458
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001463 if (i == TCL_ERROR)
1464 Tkinter_Error(selfptr);
1465 else
1466 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001470 Tkapp_CallDeallocArgs(objv, objStore, objc);
1471 }
1472 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001473}
1474
1475
1476static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001477Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001478{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001479 char *script;
1480 PyObject *res = NULL;
1481 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 if (!PyArg_ParseTuple(args, "s:eval", &script))
1484 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001485
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001486 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001488
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001489 ENTER_TCL
1490 err = Tcl_Eval(Tkapp_Interp(self), script);
1491 ENTER_OVERLAP
1492 if (err == TCL_ERROR)
1493 res = Tkinter_Error(self);
1494 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001495 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496 LEAVE_OVERLAP_TCL
1497 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001498}
1499
1500static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001501Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001502{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001503 char *fileName;
1504 PyObject *res = NULL;
1505 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1508 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001509
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001510 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 ENTER_TCL
1514 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1515 ENTER_OVERLAP
1516 if (err == TCL_ERROR)
1517 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001518 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001519 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 LEAVE_OVERLAP_TCL
1521 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001522}
1523
1524static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001525Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001526{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001527 char *script;
1528 PyObject *res = NULL;
1529 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001530
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001531 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001532 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001533
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001534 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001535 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001537 ENTER_TCL
1538 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1539 ENTER_OVERLAP
1540 if (err == TCL_ERROR)
1541 res = Tkinter_Error(self);
1542 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001543 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001544 LEAVE_OVERLAP_TCL
1545 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001546}
1547
1548static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001549Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001550{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1554 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001555 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001557
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001558 ENTER_TCL
1559 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1560 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001561
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001562 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001563}
1564
Barry Warsawfa701a81997-01-16 00:15:11 +00001565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566
Guido van Rossum18468821994-06-20 07:49:28 +00001567/** Tcl Variable **/
1568
Benjamin Peterson5879d412009-03-30 14:51:56 +00001569typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1570
1571#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001572TCL_DECLARE_MUTEX(var_mutex)
1573
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001574typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001575 Tcl_Event ev; /* must be first */
1576 PyObject *self;
1577 PyObject *args;
1578 int flags;
1579 EventFunc func;
1580 PyObject **res;
1581 PyObject **exc_type;
1582 PyObject **exc_val;
1583 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001584} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001585#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001586
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001587static int
1588varname_converter(PyObject *in, void *_out)
1589{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001590 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001591 char **out = (char**)_out;
1592 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001593 if (PyBytes_Size(in) > INT_MAX) {
1594 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1595 return 0;
1596 }
1597 s = PyBytes_AsString(in);
1598 if (strlen(s) != PyBytes_Size(in)) {
1599 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1600 return 0;
1601 }
1602 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001603 return 1;
1604 }
1605 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001606 Py_ssize_t size;
1607 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001608 if (s == NULL) {
1609 return 0;
1610 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001611 if (size > INT_MAX) {
1612 PyErr_SetString(PyExc_OverflowError, "string is too long");
1613 return 0;
1614 }
1615 if (strlen(s) != size) {
1616 PyErr_SetString(PyExc_ValueError, "null character in string");
1617 return 0;
1618 }
1619 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001620 return 1;
1621 }
1622 if (PyTclObject_Check(in)) {
1623 *out = PyTclObject_TclString(in);
1624 return 1;
1625 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001626 PyErr_Format(PyExc_TypeError,
1627 "must be str, bytes or Tcl_Obj, not %.50s",
1628 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001629 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001630}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001631
Benjamin Peterson5879d412009-03-30 14:51:56 +00001632#ifdef WITH_THREAD
1633
Martin v. Löwis59683e82008-06-13 07:50:45 +00001634static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001635var_perform(VarEvent *ev)
1636{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1638 if (!*(ev->res)) {
1639 PyObject *exc, *val, *tb;
1640 PyErr_Fetch(&exc, &val, &tb);
1641 PyErr_NormalizeException(&exc, &val, &tb);
1642 *(ev->exc_type) = exc;
1643 *(ev->exc_val) = val;
1644 Py_DECREF(tb);
1645 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001646
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001647}
1648
1649static int
1650var_proc(VarEvent* ev, int flags)
1651{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001652 ENTER_PYTHON
1653 var_perform(ev);
1654 Tcl_MutexLock(&var_mutex);
1655 Tcl_ConditionNotify(ev->cond);
1656 Tcl_MutexUnlock(&var_mutex);
1657 LEAVE_PYTHON
1658 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001659}
1660
Benjamin Peterson5879d412009-03-30 14:51:56 +00001661#endif
1662
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001663static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001664var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001665{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001666#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001667 TkappObject *self = (TkappObject*)selfptr;
1668 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1669 TkappObject *self = (TkappObject*)selfptr;
1670 VarEvent *ev;
1671 PyObject *res, *exc_type, *exc_val;
1672 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674 /* The current thread is not the interpreter thread. Marshal
1675 the call to the interpreter thread, then wait for
1676 completion. */
1677 if (!WaitForMainloop(self))
1678 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001679
Serhiy Storchaka07940882014-09-11 10:38:54 +03001680 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1681 if (ev == NULL) {
1682 PyErr_NoMemory();
1683 return NULL;
1684 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001685 ev->self = selfptr;
1686 ev->args = args;
1687 ev->flags = flags;
1688 ev->func = func;
1689 ev->res = &res;
1690 ev->exc_type = &exc_type;
1691 ev->exc_val = &exc_val;
1692 ev->cond = &cond;
1693 ev->ev.proc = (Tcl_EventProc*)var_proc;
1694 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1695 Tcl_ConditionFinalize(&cond);
1696 if (!res) {
1697 PyErr_SetObject(exc_type, exc_val);
1698 Py_DECREF(exc_type);
1699 Py_DECREF(exc_val);
1700 return NULL;
1701 }
1702 return res;
1703 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001704#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001705 /* Tcl is not threaded, or this is the interpreter thread. */
1706 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001707}
1708
Guido van Rossum18468821994-06-20 07:49:28 +00001709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 char *name1, *name2;
1713 PyObject *newValue;
1714 PyObject *res = NULL;
1715 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001716
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001717 switch (PyTuple_GET_SIZE(args)) {
1718 case 2:
1719 if (!PyArg_ParseTuple(args, "O&O:setvar",
1720 varname_converter, &name1, &newValue))
1721 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001722 /* XXX Acquire tcl lock??? */
1723 newval = AsObj(newValue);
1724 if (newval == NULL)
1725 return NULL;
1726 ENTER_TCL
1727 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1728 newval, flags);
1729 ENTER_OVERLAP
1730 if (!ok)
1731 Tkinter_Error(self);
1732 else {
1733 res = Py_None;
1734 Py_INCREF(res);
1735 }
1736 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001737 break;
1738 case 3:
1739 if (!PyArg_ParseTuple(args, "ssO:setvar",
1740 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001741 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001742 CHECK_STRING_LENGTH(name1);
1743 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001744 /* XXX must hold tcl lock already??? */
1745 newval = AsObj(newValue);
1746 ENTER_TCL
1747 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1748 ENTER_OVERLAP
1749 if (!ok)
1750 Tkinter_Error(self);
1751 else {
1752 res = Py_None;
1753 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001754 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001755 LEAVE_OVERLAP_TCL
1756 break;
1757 default:
1758 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1759 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001760 }
1761 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001762}
1763
1764static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001765Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001766{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
Barry Warsawfa701a81997-01-16 00:15:11 +00001776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777
Guido van Rossum18468821994-06-20 07:49:28 +00001778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 char *name1, *name2=NULL;
1782 PyObject *res = NULL;
1783 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1786 varname_converter, &name1, &name2))
1787 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001788
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001789 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001790 ENTER_TCL
1791 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1792 ENTER_OVERLAP
1793 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001794 PyErr_SetString(Tkinter_TclError,
1795 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001796 } else {
1797 if (((TkappObject*)self)->wantobjects) {
1798 res = FromObj(self, tres);
1799 }
1800 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001801 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001802 }
1803 }
1804 LEAVE_OVERLAP_TCL
1805 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001806}
1807
1808static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001809Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001810{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001811 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001817 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
Barry Warsawfa701a81997-01-16 00:15:11 +00001820
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001821
Guido van Rossum18468821994-06-20 07:49:28 +00001822static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001823UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001824{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001825 char *name1, *name2=NULL;
1826 int code;
1827 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001828
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001829 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1830 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001831
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001832 CHECK_STRING_LENGTH(name1);
1833 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001834 ENTER_TCL
1835 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1836 ENTER_OVERLAP
1837 if (code == TCL_ERROR)
1838 res = Tkinter_Error(self);
1839 else {
1840 Py_INCREF(Py_None);
1841 res = Py_None;
1842 }
1843 LEAVE_OVERLAP_TCL
1844 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001845}
1846
1847static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001848Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001849{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001851}
1852
1853static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001854Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001855{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001856 return var_invoke(UnsetVar, self, args,
1857 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001858}
1859
Barry Warsawfa701a81997-01-16 00:15:11 +00001860
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001861
Guido van Rossum18468821994-06-20 07:49:28 +00001862/** Tcl to Python **/
1863
1864static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001865Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001866{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001867 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001868#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
1869 Tcl_Obj *value;
1870 PyObject *result;
1871#else
1872 int intValue;
1873#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001875 if (PyTuple_Size(args) == 1) {
1876 PyObject* o = PyTuple_GetItem(args, 0);
1877 if (PyLong_Check(o)) {
1878 Py_INCREF(o);
1879 return o;
1880 }
1881 }
1882 if (!PyArg_ParseTuple(args, "s:getint", &s))
1883 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001884 CHECK_STRING_LENGTH(s);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001885#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
1886 value = Tcl_NewStringObj(s, -1);
1887 if (value == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001888 return Tkinter_Error(self);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001889 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1890 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1891
1892 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1893 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1894 */
1895#ifdef HAVE_LIBTOMMAMTH
1896 result = fromBignumObj(self, value);
1897#else
1898 result = fromWideIntObj(self, value);
1899#endif
1900 Tcl_DecrRefCount(value);
1901 if (result != NULL || PyErr_Occurred())
1902 return result;
1903#else
1904 if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
1905 return PyLong_FromLong(intValue);
1906#endif
1907 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001908}
1909
1910static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001911Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001912{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913 char *s;
1914 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001916 if (PyTuple_Size(args) == 1) {
1917 PyObject *o = PyTuple_GetItem(args, 0);
1918 if (PyFloat_Check(o)) {
1919 Py_INCREF(o);
1920 return o;
1921 }
1922 }
1923 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1924 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001925 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001926 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1927 return Tkinter_Error(self);
1928 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001929}
1930
1931static PyObject *
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001932Tkapp_GetBoolean(PyObject *self, PyObject *arg)
Guido van Rossum18468821994-06-20 07:49:28 +00001933{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001934 char *s;
1935 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001936
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001937 if (PyLong_Check(arg)) { /* int or bool */
1938 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001939 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001940
1941 if (PyTclObject_Check(arg)) {
1942 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
1943 ((PyTclObject*)arg)->value,
1944 &v) == TCL_ERROR)
1945 return Tkinter_Error(self);
1946 return PyBool_FromLong(v);
1947 }
1948
1949 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001950 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001951 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001952 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1953 return Tkinter_Error(self);
1954 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001955}
1956
1957static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001958Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001959{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001960 char *s;
1961 PyObject *res = NULL;
1962 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001964 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1965 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001966
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001967 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001970 ENTER_TCL
1971 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1972 ENTER_OVERLAP
1973 if (retval == TCL_ERROR)
1974 res = Tkinter_Error(self);
1975 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001976 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 LEAVE_OVERLAP_TCL
1978 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001979}
1980
1981static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001982Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001983{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001984 char *s;
1985 PyObject *res = NULL;
1986 int retval;
1987 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001988
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1990 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001991
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001992 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001993 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001994
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001995 ENTER_TCL
1996 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1997 ENTER_OVERLAP
1998 if (retval == TCL_ERROR)
1999 res = Tkinter_Error(self);
2000 else
2001 res = Py_BuildValue("l", v);
2002 LEAVE_OVERLAP_TCL
2003 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002004}
2005
2006static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002007Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002008{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002009 char *s;
2010 PyObject *res = NULL;
2011 double v;
2012 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002013
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002014 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2015 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002016 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002017 CHECK_TCL_APPARTMENT;
2018 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2019 ENTER_TCL
2020 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2021 ENTER_OVERLAP
2022 PyFPE_END_PROTECT(retval)
2023 if (retval == TCL_ERROR)
2024 res = Tkinter_Error(self);
2025 else
2026 res = Py_BuildValue("d", v);
2027 LEAVE_OVERLAP_TCL
2028 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002029}
2030
2031static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002032Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002034 char *s;
2035 PyObject *res = NULL;
2036 int retval;
2037 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002038
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002039 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2040 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002041 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 CHECK_TCL_APPARTMENT;
2043 ENTER_TCL
2044 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2045 ENTER_OVERLAP
2046 if (retval == TCL_ERROR)
2047 res = Tkinter_Error(self);
2048 else
2049 res = Py_BuildValue("i", v);
2050 LEAVE_OVERLAP_TCL
2051 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002052}
2053
Barry Warsawfa701a81997-01-16 00:15:11 +00002054
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002055
Guido van Rossum18468821994-06-20 07:49:28 +00002056static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002057Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002058{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002059 char *list;
2060 int argc;
2061 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002062 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002064
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002065 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2066 return NULL;
2067 if (PyTclObject_Check(arg)) {
2068 int objc;
2069 Tcl_Obj **objv;
2070 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2071 ((PyTclObject*)arg)->value,
2072 &objc, &objv) == TCL_ERROR) {
2073 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002074 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002075 if (!(v = PyTuple_New(objc)))
2076 return NULL;
2077 for (i = 0; i < objc; i++) {
2078 PyObject *s = FromObj(self, objv[i]);
2079 if (!s || PyTuple_SetItem(v, i, s)) {
2080 Py_DECREF(v);
2081 return NULL;
2082 }
2083 }
2084 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002085 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002086 if (PyTuple_Check(arg)) {
2087 Py_INCREF(arg);
2088 return arg;
2089 }
2090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002091 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2092 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002093
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002094 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002095 if (Tcl_SplitList(Tkapp_Interp(self), list,
2096 &argc, &argv) == TCL_ERROR) {
2097 PyMem_Free(list);
2098 return Tkinter_Error(self);
2099 }
Guido van Rossum18468821994-06-20 07:49:28 +00002100
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002101 if (!(v = PyTuple_New(argc)))
2102 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002103
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002104 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002105 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002106 if (!s || PyTuple_SetItem(v, i, s)) {
2107 Py_DECREF(v);
2108 v = NULL;
2109 goto finally;
2110 }
2111 }
Guido van Rossum18468821994-06-20 07:49:28 +00002112
Barry Warsawfa701a81997-01-16 00:15:11 +00002113 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 ckfree(FREECAST argv);
2115 PyMem_Free(list);
2116 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
2119static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002120Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002121{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002122 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002123 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002124
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002125 if (!PyArg_ParseTuple(args, "O:split", &arg))
2126 return NULL;
2127 if (PyTclObject_Check(arg)) {
2128 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2129 int objc;
2130 Tcl_Obj **objv;
2131 int i;
2132 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2133 &objc, &objv) == TCL_ERROR) {
2134 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002135 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002136 if (objc == 0)
2137 return PyUnicode_FromString("");
2138 if (objc == 1)
2139 return FromObj(self, objv[0]);
2140 if (!(v = PyTuple_New(objc)))
2141 return NULL;
2142 for (i = 0; i < objc; i++) {
2143 PyObject *s = FromObj(self, objv[i]);
2144 if (!s || PyTuple_SetItem(v, i, s)) {
2145 Py_DECREF(v);
2146 return NULL;
2147 }
2148 }
2149 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002151 if (PyTuple_Check(arg))
2152 return SplitObj(arg);
2153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002154 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2155 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002156 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002157 v = Split(list);
2158 PyMem_Free(list);
2159 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002160}
2161
Barry Warsawfa701a81997-01-16 00:15:11 +00002162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163
Guido van Rossum18468821994-06-20 07:49:28 +00002164/** Tcl Command **/
2165
Guido van Rossum00d93061998-05-28 23:06:38 +00002166/* Client data struct */
2167typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002168 PyObject *self;
2169 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002170} PythonCmd_ClientData;
2171
2172static int
Fred Drake509d79a2000-07-08 04:04:38 +00002173PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002174{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002175 errorInCmd = 1;
2176 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2177 LEAVE_PYTHON
2178 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002179}
2180
Guido van Rossum18468821994-06-20 07:49:28 +00002181/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002182 * function or method.
2183 */
Guido van Rossum18468821994-06-20 07:49:28 +00002184static int
Fred Drake509d79a2000-07-08 04:04:38 +00002185PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002186{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002188 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002189 int i, rv;
2190 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002192 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002193
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002194 /* TBD: no error checking here since we know, via the
2195 * Tkapp_CreateCommand() that the client data is a two-tuple
2196 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002197 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 /* Create argument list (argv1, ..., argvN) */
2200 if (!(arg = PyTuple_New(argc - 1)))
2201 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002203 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002204 PyObject *s = unicodeFromTclString(argv[i + 1]);
2205 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002206 Py_DECREF(arg);
2207 return PythonCmd_Error(interp);
2208 }
2209 }
2210 res = PyEval_CallObject(func, arg);
2211 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002213 if (res == NULL)
2214 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002216 obj_res = AsObj(res);
2217 if (obj_res == NULL) {
2218 Py_DECREF(res);
2219 return PythonCmd_Error(interp);
2220 }
2221 else {
2222 Tcl_SetObjResult(interp, obj_res);
2223 rv = TCL_OK;
2224 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002227
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002228 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002231}
2232
2233static void
Fred Drake509d79a2000-07-08 04:04:38 +00002234PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002235{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002236 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 ENTER_PYTHON
2239 Py_XDECREF(data->self);
2240 Py_XDECREF(data->func);
2241 PyMem_DEL(data);
2242 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002243}
2244
Barry Warsawfa701a81997-01-16 00:15:11 +00002245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002246
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002247
Benjamin Peterson5879d412009-03-30 14:51:56 +00002248#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002249TCL_DECLARE_MUTEX(command_mutex)
2250
2251typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002252 Tcl_Event ev;
2253 Tcl_Interp* interp;
2254 char *name;
2255 int create;
2256 int *status;
2257 ClientData *data;
2258 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002259} CommandEvent;
2260
2261static int
2262Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002264 if (ev->create)
2265 *ev->status = Tcl_CreateCommand(
2266 ev->interp, ev->name, PythonCmd,
2267 ev->data, PythonCmdDelete) == NULL;
2268 else
2269 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2270 Tcl_MutexLock(&command_mutex);
2271 Tcl_ConditionNotify(ev->done);
2272 Tcl_MutexUnlock(&command_mutex);
2273 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002274}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002275#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002276
2277static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002278Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002279{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002280 TkappObject *self = (TkappObject*)selfptr;
2281 PythonCmd_ClientData *data;
2282 char *cmdName;
2283 PyObject *func;
2284 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002285
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002286 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2287 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002288 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002289 if (!PyCallable_Check(func)) {
2290 PyErr_SetString(PyExc_TypeError, "command not callable");
2291 return NULL;
2292 }
Guido van Rossum18468821994-06-20 07:49:28 +00002293
Martin v. Löwisa9656492003-03-30 08:44:58 +00002294#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002295 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2296 !WaitForMainloop(self))
2297 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002298#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002299
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002300 data = PyMem_NEW(PythonCmd_ClientData, 1);
2301 if (!data)
2302 return PyErr_NoMemory();
2303 Py_INCREF(self);
2304 Py_INCREF(func);
2305 data->self = selfptr;
2306 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002307#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002308 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2309 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002310 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2311 if (ev == NULL) {
2312 PyErr_NoMemory();
2313 PyMem_DEL(data);
2314 return NULL;
2315 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002316 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2317 ev->interp = self->interp;
2318 ev->create = 1;
2319 ev->name = cmdName;
2320 ev->data = (ClientData)data;
2321 ev->status = &err;
2322 ev->done = &cond;
2323 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2324 Tcl_ConditionFinalize(&cond);
2325 }
2326 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002327#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002328 {
2329 ENTER_TCL
2330 err = Tcl_CreateCommand(
2331 Tkapp_Interp(self), cmdName, PythonCmd,
2332 (ClientData)data, PythonCmdDelete) == NULL;
2333 LEAVE_TCL
2334 }
2335 if (err) {
2336 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2337 PyMem_DEL(data);
2338 return NULL;
2339 }
Guido van Rossum18468821994-06-20 07:49:28 +00002340
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002341 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002342}
2343
Barry Warsawfa701a81997-01-16 00:15:11 +00002344
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002345
Guido van Rossum18468821994-06-20 07:49:28 +00002346static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002347Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002348{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002349 TkappObject *self = (TkappObject*)selfptr;
2350 char *cmdName;
2351 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002353 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2354 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002355 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002356
2357#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002358 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2359 Tcl_Condition cond = NULL;
2360 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002361 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2362 if (ev == NULL) {
2363 PyErr_NoMemory();
2364 return NULL;
2365 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002366 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2367 ev->interp = self->interp;
2368 ev->create = 0;
2369 ev->name = cmdName;
2370 ev->status = &err;
2371 ev->done = &cond;
2372 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2373 &command_mutex);
2374 Tcl_ConditionFinalize(&cond);
2375 }
2376 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002377#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 {
2379 ENTER_TCL
2380 err = Tcl_DeleteCommand(self->interp, cmdName);
2381 LEAVE_TCL
2382 }
2383 if (err == -1) {
2384 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2385 return NULL;
2386 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002387 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002388}
2389
Barry Warsawfa701a81997-01-16 00:15:11 +00002390
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391
Guido van Rossum00d93061998-05-28 23:06:38 +00002392#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002393/** File Handler **/
2394
Guido van Rossum00d93061998-05-28 23:06:38 +00002395typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002396 PyObject *func;
2397 PyObject *file;
2398 int id;
2399 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002400} FileHandler_ClientData;
2401
2402static FileHandler_ClientData *HeadFHCD;
2403
2404static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002405NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002406{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002407 FileHandler_ClientData *p;
2408 p = PyMem_NEW(FileHandler_ClientData, 1);
2409 if (p != NULL) {
2410 Py_XINCREF(func);
2411 Py_XINCREF(file);
2412 p->func = func;
2413 p->file = file;
2414 p->id = id;
2415 p->next = HeadFHCD;
2416 HeadFHCD = p;
2417 }
2418 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002419}
2420
2421static void
Fred Drake509d79a2000-07-08 04:04:38 +00002422DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002423{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002426 pp = &HeadFHCD;
2427 while ((p = *pp) != NULL) {
2428 if (p->id == id) {
2429 *pp = p->next;
2430 Py_XDECREF(p->func);
2431 Py_XDECREF(p->file);
2432 PyMem_DEL(p);
2433 }
2434 else
2435 pp = &p->next;
2436 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002437}
2438
Guido van Rossuma597dde1995-01-10 20:56:29 +00002439static void
Fred Drake509d79a2000-07-08 04:04:38 +00002440FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002441{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002442 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2443 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 ENTER_PYTHON
2446 func = data->func;
2447 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 arg = Py_BuildValue("(Oi)", file, (long) mask);
2450 res = PyEval_CallObject(func, arg);
2451 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002452
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 if (res == NULL) {
2454 errorInCmd = 1;
2455 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2456 }
2457 Py_XDECREF(res);
2458 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002459}
2460
Guido van Rossum18468821994-06-20 07:49:28 +00002461static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002462Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2463 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002464{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002465 FileHandler_ClientData *data;
2466 PyObject *file, *func;
2467 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002469 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2470 &file, &mask, &func))
2471 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002473 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002475 tfile = PyObject_AsFileDescriptor(file);
2476 if (tfile < 0)
2477 return NULL;
2478 if (!PyCallable_Check(func)) {
2479 PyErr_SetString(PyExc_TypeError, "bad argument list");
2480 return NULL;
2481 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002483 data = NewFHCD(func, file, tfile);
2484 if (data == NULL)
2485 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002487 /* Ought to check for null Tcl_File object... */
2488 ENTER_TCL
2489 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2490 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002491 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002492}
2493
2494static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002495Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002496{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002497 PyObject *file;
2498 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002500 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2501 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002502
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002503 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002504
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002505 tfile = PyObject_AsFileDescriptor(file);
2506 if (tfile < 0)
2507 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 /* Ought to check for null Tcl_File object... */
2512 ENTER_TCL
2513 Tcl_DeleteFileHandler(tfile);
2514 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002515 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002516}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002517#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002518
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002519
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002520/**** Tktt Object (timer token) ****/
2521
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002522static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002523
Guido van Rossum00d93061998-05-28 23:06:38 +00002524typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 PyObject_HEAD
2526 Tcl_TimerToken token;
2527 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002528} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002529
2530static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002531Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002532{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002533 TkttObject *v = (TkttObject *)self;
2534 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002535
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002536 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2537 return NULL;
2538 if (v->token != NULL) {
2539 Tcl_DeleteTimerHandler(v->token);
2540 v->token = NULL;
2541 }
2542 if (func != NULL) {
2543 v->func = NULL;
2544 Py_DECREF(func);
2545 Py_DECREF(v); /* See Tktt_New() */
2546 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002547 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002548}
2549
2550static PyMethodDef Tktt_methods[] =
2551{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002552 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2553 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002554};
2555
2556static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002557Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002558{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002559 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002560
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002561 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 if (v == NULL)
2563 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002564 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 Py_INCREF(func);
2567 v->token = NULL;
2568 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002569
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 /* Extra reference, deleted when called or when handler is deleted */
2571 Py_INCREF(v);
2572 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002573}
2574
2575static void
Fred Drake509d79a2000-07-08 04:04:38 +00002576Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002577{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002578 TkttObject *v = (TkttObject *)self;
2579 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002580 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002582 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002585 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002586}
2587
Guido van Rossum597ac201998-05-12 14:36:19 +00002588static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002589Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002590{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002591 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002592 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2593 v,
2594 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595}
2596
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002597static PyType_Slot Tktt_Type_slots[] = {
2598 {Py_tp_dealloc, Tktt_Dealloc},
2599 {Py_tp_repr, Tktt_Repr},
2600 {Py_tp_methods, Tktt_methods},
2601 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002602};
2603
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002604static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002605 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002606 sizeof(TkttObject),
2607 0,
2608 Py_TPFLAGS_DEFAULT,
2609 Tktt_Type_slots,
2610};
Barry Warsawfa701a81997-01-16 00:15:11 +00002611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002612
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002613/** Timer Handler **/
2614
2615static void
Fred Drake509d79a2000-07-08 04:04:38 +00002616TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002617{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002618 TkttObject *v = (TkttObject *)clientData;
2619 PyObject *func = v->func;
2620 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 if (func == NULL)
2623 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002626
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002627 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002628
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002629 res = PyEval_CallObject(func, NULL);
2630 Py_DECREF(func);
2631 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002633 if (res == NULL) {
2634 errorInCmd = 1;
2635 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2636 }
2637 else
2638 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002641}
2642
2643static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002644Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002645{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002646 int milliseconds;
2647 PyObject *func;
2648 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002650 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2651 &milliseconds, &func))
2652 return NULL;
2653 if (!PyCallable_Check(func)) {
2654 PyErr_SetString(PyExc_TypeError, "bad argument list");
2655 return NULL;
2656 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002657
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002658 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 v = Tktt_New(func);
2661 if (v) {
2662 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2663 (ClientData)v);
2664 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002665
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002666 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002667}
2668
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002669
Guido van Rossum18468821994-06-20 07:49:28 +00002670/** Event Loop **/
2671
Guido van Rossum18468821994-06-20 07:49:28 +00002672static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002673Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002674{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002675 int threshold = 0;
2676 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002677#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002678 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002679#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002680
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002681 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2682 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002684 CHECK_TCL_APPARTMENT;
2685 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 quitMainLoop = 0;
2688 while (Tk_GetNumMainWindows() > threshold &&
2689 !quitMainLoop &&
2690 !errorInCmd)
2691 {
2692 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002693
2694#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002695 if (self->threaded) {
2696 /* Allow other Python threads to run. */
2697 ENTER_TCL
2698 result = Tcl_DoOneEvent(0);
2699 LEAVE_TCL
2700 }
2701 else {
2702 Py_BEGIN_ALLOW_THREADS
2703 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2704 tcl_tstate = tstate;
2705 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2706 tcl_tstate = NULL;
2707 if(tcl_lock)PyThread_release_lock(tcl_lock);
2708 if (result == 0)
2709 Sleep(Tkinter_busywaitinterval);
2710 Py_END_ALLOW_THREADS
2711 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002712#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002713 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002714#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002716 if (PyErr_CheckSignals() != 0) {
2717 self->dispatching = 0;
2718 return NULL;
2719 }
2720 if (result < 0)
2721 break;
2722 }
2723 self->dispatching = 0;
2724 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002726 if (errorInCmd) {
2727 errorInCmd = 0;
2728 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2729 excInCmd = valInCmd = trbInCmd = NULL;
2730 return NULL;
2731 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002732 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002733}
2734
2735static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002736Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002737{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002738 int flags = 0;
2739 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2742 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002743
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002744 ENTER_TCL
2745 rv = Tcl_DoOneEvent(flags);
2746 LEAVE_TCL
2747 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002748}
2749
2750static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002751Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002752{
2753
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002754 if (!PyArg_ParseTuple(args, ":quit"))
2755 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002756
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002757 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002758 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002759}
2760
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002761static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002762Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002763{
2764
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002765 if (!PyArg_ParseTuple(args, ":interpaddr"))
2766 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002767
Victor Stinnere1040e22013-09-05 00:22:24 +02002768 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002769}
2770
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002771static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002772Tkapp_TkInit(PyObject *self, PyObject *args)
2773{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 Tcl_Interp *interp = Tkapp_Interp(self);
2775 const char * _tk_exists = NULL;
2776 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002777
Guilherme Polob681df42009-02-09 22:33:59 +00002778#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002779 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2780 * first call failed.
2781 * To avoid the deadlock, we just refuse the second call through
2782 * a static variable.
2783 */
2784 if (tk_load_failed) {
2785 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2786 return NULL;
2787 }
Guilherme Polob681df42009-02-09 22:33:59 +00002788#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002789
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790 /* We want to guard against calling Tk_Init() multiple times */
2791 CHECK_TCL_APPARTMENT;
2792 ENTER_TCL
2793 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2794 ENTER_OVERLAP
2795 if (err == TCL_ERROR) {
2796 /* This sets an exception, but we cannot return right
2797 away because we need to exit the overlap first. */
2798 Tkinter_Error(self);
2799 } else {
2800 _tk_exists = Tkapp_Result(self);
2801 }
2802 LEAVE_OVERLAP_TCL
2803 if (err == TCL_ERROR) {
2804 return NULL;
2805 }
2806 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2807 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002808 PyErr_SetString(Tkinter_TclError,
2809 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002810#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002811 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002812#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002813 return NULL;
2814 }
2815 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002816 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002817}
Barry Warsawfa701a81997-01-16 00:15:11 +00002818
Martin v. Löwisffad6332002-11-26 09:28:05 +00002819static PyObject *
2820Tkapp_WantObjects(PyObject *self, PyObject *args)
2821{
2822
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 int wantobjects = -1;
2824 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2825 return NULL;
2826 if (wantobjects == -1)
2827 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2828 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002829
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002830 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002831}
2832
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002833static PyObject *
2834Tkapp_WillDispatch(PyObject *self, PyObject *args)
2835{
2836
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002837 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002838
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002839 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002840}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002841
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842
Guido van Rossum18468821994-06-20 07:49:28 +00002843/**** Tkapp Method List ****/
2844
2845static PyMethodDef Tkapp_methods[] =
2846{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002847 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2848 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2849 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002850 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2852 {"record", Tkapp_Record, METH_VARARGS},
2853 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2854 {"setvar", Tkapp_SetVar, METH_VARARGS},
2855 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2856 {"getvar", Tkapp_GetVar, METH_VARARGS},
2857 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2858 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2859 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2860 {"getint", Tkapp_GetInt, METH_VARARGS},
2861 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002862 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002863 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2864 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2865 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2866 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2867 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2868 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002869 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2870 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002871#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002872 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2873 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002874#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002875 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2876 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2877 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2878 {"quit", Tkapp_Quit, METH_VARARGS},
2879 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2880 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2881 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002882};
2883
Barry Warsawfa701a81997-01-16 00:15:11 +00002884
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002885
Guido van Rossum18468821994-06-20 07:49:28 +00002886/**** Tkapp Type Methods ****/
2887
2888static void
Fred Drake509d79a2000-07-08 04:04:38 +00002889Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002890{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002891 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002892 /*CHECK_TCL_APPARTMENT;*/
2893 ENTER_TCL
2894 Tcl_DeleteInterp(Tkapp_Interp(self));
2895 LEAVE_TCL
2896 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002897 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002899}
2900
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002901static PyType_Slot Tkapp_Type_slots[] = {
2902 {Py_tp_dealloc, Tkapp_Dealloc},
2903 {Py_tp_methods, Tkapp_methods},
2904 {0, 0}
2905};
2906
2907
2908static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002909 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002910 sizeof(TkappObject),
2911 0,
2912 Py_TPFLAGS_DEFAULT,
2913 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002914};
2915
Barry Warsawfa701a81997-01-16 00:15:11 +00002916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002917
Guido van Rossum18468821994-06-20 07:49:28 +00002918/**** Tkinter Module ****/
2919
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002920typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 PyObject* tuple;
2922 int size; /* current size */
2923 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002924} FlattenContext;
2925
2926static int
2927_bump(FlattenContext* context, int size)
2928{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002929 /* expand tuple to hold (at least) size new items.
2930 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002932 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002933
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002934 if (maxsize < context->size + size)
2935 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002940}
2941
2942static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002943_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002944{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002945 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002947 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002949 if (depth > 1000) {
2950 PyErr_SetString(PyExc_ValueError,
2951 "nesting too deep in _flatten");
2952 return 0;
2953 } else if (PyList_Check(item)) {
2954 size = PyList_GET_SIZE(item);
2955 /* preallocate (assume no nesting) */
2956 if (context->size + size > context->maxsize &&
2957 !_bump(context, size))
2958 return 0;
2959 /* copy items to output tuple */
2960 for (i = 0; i < size; i++) {
2961 PyObject *o = PyList_GET_ITEM(item, i);
2962 if (PyList_Check(o) || PyTuple_Check(o)) {
2963 if (!_flatten1(context, o, depth + 1))
2964 return 0;
2965 } else if (o != Py_None) {
2966 if (context->size + 1 > context->maxsize &&
2967 !_bump(context, 1))
2968 return 0;
2969 Py_INCREF(o);
2970 PyTuple_SET_ITEM(context->tuple,
2971 context->size++, o);
2972 }
2973 }
2974 } else if (PyTuple_Check(item)) {
2975 /* same, for tuples */
2976 size = PyTuple_GET_SIZE(item);
2977 if (context->size + size > context->maxsize &&
2978 !_bump(context, size))
2979 return 0;
2980 for (i = 0; i < size; i++) {
2981 PyObject *o = PyTuple_GET_ITEM(item, i);
2982 if (PyList_Check(o) || PyTuple_Check(o)) {
2983 if (!_flatten1(context, o, depth + 1))
2984 return 0;
2985 } else if (o != Py_None) {
2986 if (context->size + 1 > context->maxsize &&
2987 !_bump(context, 1))
2988 return 0;
2989 Py_INCREF(o);
2990 PyTuple_SET_ITEM(context->tuple,
2991 context->size++, o);
2992 }
2993 }
2994 } else {
2995 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2996 return 0;
2997 }
2998 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002999}
3000
3001static PyObject *
3002Tkinter_Flatten(PyObject* self, PyObject* args)
3003{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003004 FlattenContext context;
3005 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003007 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3008 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 context.maxsize = PySequence_Size(item);
3011 if (context.maxsize < 0)
3012 return NULL;
3013 if (context.maxsize == 0)
3014 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003016 context.tuple = PyTuple_New(context.maxsize);
3017 if (!context.tuple)
3018 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003019
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003020 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003021
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003022 if (!_flatten1(&context, item,0))
3023 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003025 if (_PyTuple_Resize(&context.tuple, context.size))
3026 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003028 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003029}
3030
Guido van Rossum18468821994-06-20 07:49:28 +00003031static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003032Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003034 char *screenName = NULL;
3035 char *baseName = NULL; /* XXX this is not used anymore;
3036 try getting rid of it. */
3037 char *className = NULL;
3038 int interactive = 0;
3039 int wantobjects = 0;
3040 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3041 int sync = 0; /* pass -sync to wish */
3042 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003043
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003045
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3047 &screenName, &baseName, &className,
3048 &interactive, &wantobjects, &wantTk,
3049 &sync, &use))
3050 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003051 CHECK_STRING_LENGTH(screenName);
3052 CHECK_STRING_LENGTH(baseName);
3053 CHECK_STRING_LENGTH(className);
3054 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003056 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003057 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003058 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003059}
3060
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003061static PyObject *
3062Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3063{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003064 int new_val;
3065 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3066 return NULL;
3067 if (new_val < 0) {
3068 PyErr_SetString(PyExc_ValueError,
3069 "busywaitinterval must be >= 0");
3070 return NULL;
3071 }
3072 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003073 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003074}
3075
3076static char setbusywaitinterval_doc[] =
3077"setbusywaitinterval(n) -> None\n\
3078\n\
3079Set the busy-wait interval in milliseconds between successive\n\
3080calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3081It should be set to a divisor of the maximum time between\n\
3082frames in an animation.";
3083
3084static PyObject *
3085Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3086{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003087 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003088}
3089
3090static char getbusywaitinterval_doc[] =
3091"getbusywaitinterval() -> int\n\
3092\n\
3093Return the current busy-wait interval between successive\n\
3094calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3095
Guido van Rossum18468821994-06-20 07:49:28 +00003096static PyMethodDef moduleMethods[] =
3097{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3099 {"create", Tkinter_Create, METH_VARARGS},
3100 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3101 setbusywaitinterval_doc},
3102 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3103 METH_NOARGS, getbusywaitinterval_doc},
3104 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003105};
3106
Guido van Rossum7bf15641998-05-22 18:28:17 +00003107#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003108
3109static int stdin_ready = 0;
3110
Guido van Rossumad4db171998-06-13 13:56:28 +00003111#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003112static void
Fred Drake509d79a2000-07-08 04:04:38 +00003113MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003115 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003116}
Guido van Rossumad4db171998-06-13 13:56:28 +00003117#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003118
Martin v. Löwisa9656492003-03-30 08:44:58 +00003119#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003120static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003121#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003122
Guido van Rossum18468821994-06-20 07:49:28 +00003123static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003124EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003125{
Guido van Rossumad4db171998-06-13 13:56:28 +00003126#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003127 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003128#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003129#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003130 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003131#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003132 stdin_ready = 0;
3133 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003134#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003135 tfile = fileno(stdin);
3136 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003137#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 while (!errorInCmd && !stdin_ready) {
3139 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003140#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003141 if (_kbhit()) {
3142 stdin_ready = 1;
3143 break;
3144 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003145#endif
3146#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003147 Py_BEGIN_ALLOW_THREADS
3148 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3149 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003152
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 tcl_tstate = NULL;
3154 if(tcl_lock)PyThread_release_lock(tcl_lock);
3155 if (result == 0)
3156 Sleep(Tkinter_busywaitinterval);
3157 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003158#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003159 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003160#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003161
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003162 if (result < 0)
3163 break;
3164 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003165#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003166 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003167#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003168 if (errorInCmd) {
3169 errorInCmd = 0;
3170 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3171 excInCmd = valInCmd = trbInCmd = NULL;
3172 PyErr_Print();
3173 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003174#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003175 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003176#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003177 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003178}
Guido van Rossum18468821994-06-20 07:49:28 +00003179
Guido van Rossum00d93061998-05-28 23:06:38 +00003180#endif
3181
Guido van Rossum7bf15641998-05-22 18:28:17 +00003182static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003183EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003184{
Guido van Rossum00d93061998-05-28 23:06:38 +00003185#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003186 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003187#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003188 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003189#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003190 PyOS_InputHook = EventHook;
3191 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003192#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003193}
3194
3195static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003196DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003197{
Guido van Rossum00d93061998-05-28 23:06:38 +00003198#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003199 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3200 PyOS_InputHook = NULL;
3201 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003202#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003203}
3204
Barry Warsawfa701a81997-01-16 00:15:11 +00003205
Martin v. Löwis1a214512008-06-11 05:26:20 +00003206static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003207 PyModuleDef_HEAD_INIT,
3208 "_tkinter",
3209 NULL,
3210 -1,
3211 moduleMethods,
3212 NULL,
3213 NULL,
3214 NULL,
3215 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003216};
3217
Mark Hammond62b1ab12002-07-23 06:31:15 +00003218PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003219PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003220{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003221 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003222
Guido van Rossum00d93061998-05-28 23:06:38 +00003223#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003224 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003225 if (tcl_lock == NULL)
3226 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003227#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003229 m = PyModule_Create(&_tkintermodule);
3230 if (m == NULL)
3231 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003232
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003233 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3234 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003235 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003236 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003237 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003238 Py_INCREF(o);
3239 if (PyModule_AddObject(m, "TclError", o)) {
3240 Py_DECREF(o);
3241 Py_DECREF(m);
3242 return NULL;
3243 }
3244 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003245
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003246 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3247 Py_DECREF(m);
3248 return NULL;
3249 }
3250 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3251 Py_DECREF(m);
3252 return NULL;
3253 }
3254 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3255 Py_DECREF(m);
3256 return NULL;
3257 }
3258 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3259 Py_DECREF(m);
3260 return NULL;
3261 }
3262 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3263 Py_DECREF(m);
3264 return NULL;
3265 }
3266 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3267 Py_DECREF(m);
3268 return NULL;
3269 }
3270 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3271 Py_DECREF(m);
3272 return NULL;
3273 }
3274 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3275 Py_DECREF(m);
3276 return NULL;
3277 }
3278 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3279 Py_DECREF(m);
3280 return NULL;
3281 }
3282 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3283 Py_DECREF(m);
3284 return NULL;
3285 }
3286 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3287 Py_DECREF(m);
3288 return NULL;
3289 }
3290
3291 o = PyType_FromSpec(&Tkapp_Type_spec);
3292 if (o == NULL) {
3293 Py_DECREF(m);
3294 return NULL;
3295 }
3296 if (PyModule_AddObject(m, "TkappType", o)) {
3297 Py_DECREF(o);
3298 Py_DECREF(m);
3299 return NULL;
3300 }
3301 Tkapp_Type = o;
3302
3303 o = PyType_FromSpec(&Tktt_Type_spec);
3304 if (o == NULL) {
3305 Py_DECREF(m);
3306 return NULL;
3307 }
3308 if (PyModule_AddObject(m, "TkttType", o)) {
3309 Py_DECREF(o);
3310 Py_DECREF(m);
3311 return NULL;
3312 }
3313 Tktt_Type = o;
3314
3315 o = PyType_FromSpec(&PyTclObject_Type_spec);
3316 if (o == NULL) {
3317 Py_DECREF(m);
3318 return NULL;
3319 }
3320 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3321 Py_DECREF(o);
3322 Py_DECREF(m);
3323 return NULL;
3324 }
3325 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003326
3327#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003328 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3329 * start waking up. Note that Tcl_FindExecutable will do this, this
3330 * code must be above it! The original warning from
3331 * tkMacOSXAppInit.c is copied below.
3332 *
3333 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3334 * Tcl interpreter for now. It probably should work to do this
3335 * in the other order, but for now it doesn't seem to.
3336 *
3337 */
3338 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003339#endif
3340
3341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003342 /* This helps the dynamic loader; in Unicode aware Tcl versions
3343 it also helps Tcl find its encodings. */
3344 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3345 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003346 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003347 if (cexe)
3348 Tcl_FindExecutable(PyBytes_AsString(cexe));
3349 Py_XDECREF(cexe);
3350 Py_DECREF(uexe);
3351 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003353 if (PyErr_Occurred()) {
3354 Py_DECREF(m);
3355 return NULL;
3356 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003357
Guido van Rossum43ff8681998-07-14 18:02:13 +00003358#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003359 /* This was not a good idea; through <Destroy> bindings,
3360 Tcl_Finalize() may invoke Python code but at that point the
3361 interpreter and thread state have already been destroyed! */
3362 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003363#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003364 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003365}