blob: 52025bb16f6a77f8fb9cb3dc347bdc74495ab3df [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
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030068#if TK_HEX_VERSION < 0x08030201
Guilherme Polo66917722009-02-09 22:35:27 +000069#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Serhiy Storchaka3af7a382015-04-22 10:53:08 +030072#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
73 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakaea134da2015-04-02 18:46:50 +030074#define HAVE_LIBTOMMAMTH
75#include <tclTomMath.h>
76#endif
77
Jack Janseneddc1442003-11-20 01:44:59 +000078#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000079#define HAVE_CREATEFILEHANDLER
80#endif
81
Guido van Rossum00d93061998-05-28 23:06:38 +000082#ifdef HAVE_CREATEFILEHANDLER
83
Neal Norwitzd948a432006-01-08 01:08:55 +000084/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
85 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
86#ifndef TCL_UNIX_FD
87# ifdef TCL_WIN_SOCKET
88# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
89# else
90# define TCL_UNIX_FD 1
91# endif
92#endif
93
Guido van Rossum00d93061998-05-28 23:06:38 +000094/* Tcl_CreateFileHandler() changed several times; these macros deal with the
95 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
96 Unix, only because Jack added it back); when available on Windows, it only
97 applies to sockets. */
98
Guido van Rossum7bf15641998-05-22 18:28:17 +000099#ifdef MS_WINDOWS
100#define FHANDLETYPE TCL_WIN_SOCKET
101#else
102#define FHANDLETYPE TCL_UNIX_FD
103#endif
104
Guido van Rossum00d93061998-05-28 23:06:38 +0000105/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
106 which uses this to handle Tcl events while the user is typing commands. */
107
108#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000109#define WAIT_FOR_STDIN
110#endif
111
Guido van Rossum00d93061998-05-28 23:06:38 +0000112#endif /* HAVE_CREATEFILEHANDLER */
113
Guido van Rossumad4db171998-06-13 13:56:28 +0000114#ifdef MS_WINDOWS
115#include <conio.h>
116#define WAIT_FOR_STDIN
117#endif
118
Guido van Rossum00d93061998-05-28 23:06:38 +0000119#ifdef WITH_THREAD
120
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000121/* The threading situation is complicated. Tcl is not thread-safe, except
122 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000123
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300124 So we need to use a lock around all uses of Tcl. Previously, the
125 Python interpreter lock was used for this. However, this causes
126 problems when other Python threads need to run while Tcl is blocked
127 waiting for events.
Guido van Rossum00d93061998-05-28 23:06:38 +0000128
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300129 To solve this problem, a separate lock for Tcl is introduced.
130 Holding it is incompatible with holding Python's interpreter lock.
131 The following four macros manipulate both locks together.
Guido van Rossum00d93061998-05-28 23:06:38 +0000132
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300133 ENTER_TCL and LEAVE_TCL are brackets, just like
134 Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
135 used whenever a call into Tcl is made that could call an event
136 handler, or otherwise affect the state of a Tcl interpreter. These
137 assume that the surrounding code has the Python interpreter lock;
138 inside the brackets, the Python interpreter lock has been released
139 and the lock for Tcl has been acquired.
140
141 Sometimes, it is necessary to have both the Python lock and the Tcl
142 lock. (For example, when transferring data from the Tcl
143 interpreter result to a Python string object.) This can be done by
144 using different macros to close the ENTER_TCL block: ENTER_OVERLAP
145 reacquires the Python lock (and restores the thread state) but
146 doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
147 lock.
Guido van Rossum5e977831998-06-15 14:03:52 +0000148
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000149 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300150 handlers when the handler needs to use Python. Such event handlers
151 are entered while the lock for Tcl is held; the event handler
152 presumably needs to use Python. ENTER_PYTHON releases the lock for
153 Tcl and acquires the Python interpreter lock, restoring the
154 appropriate thread state, and LEAVE_PYTHON releases the Python
155 interpreter lock and re-acquires the lock for Tcl. It is okay for
156 ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
157 ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000158
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300159 These locks expand to several statements and brackets; they should
160 not be used in branches of if statements and the like.
Guido van Rossum00d93061998-05-28 23:06:38 +0000161
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300162 If Tcl is threaded, this approach won't work anymore. The Tcl
163 interpreter is only valid in the thread that created it, and all Tk
164 activity must happen in this thread, also. That means that the
165 mainloop must be invoked in the thread that created the
166 interpreter. Invoking commands from other threads is possible;
167 _tkinter will queue an event for the interpreter thread, which will
168 then execute the command and pass back the result. If the main
169 thread is not in the mainloop, and invoking commands causes an
170 exception; if the main loop is running but not processing events,
171 the command invocation will block.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000172
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300173 In addition, for a threaded Tcl, a single global tcl_tstate won't
174 be sufficient anymore, since multiple Tcl interpreters may
175 simultaneously dispatch in different threads. So we use the Tcl TLS
176 API.
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000177
Guido van Rossum00d93061998-05-28 23:06:38 +0000178*/
179
Guido van Rossum65d5b571998-12-21 19:32:43 +0000180static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181
182#ifdef TCL_THREADS
183static Tcl_ThreadDataKey state_key;
184typedef PyThreadState *ThreadSpecificData;
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300185#define tcl_tstate \
186 (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000187#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000188static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000189#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000190
191#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
193 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000194
195#define LEAVE_TCL \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300196 tcl_tstate = NULL; \
197 if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000198
Guido van Rossum62320c91998-06-15 04:36:09 +0000199#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000201
202#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000203 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000204
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000205#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300207 if(tcl_lock) \
208 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
210#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000211 { PyThreadState *tstate = PyEval_SaveThread(); \
212 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000213
214#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 if (((TkappObject *)self)->threaded && \
216 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300217 PyErr_SetString(PyExc_RuntimeError, \
218 "Calling Tcl from different appartment"); \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000219 return 0; \
220 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000221
222#else
223
224#define ENTER_TCL
225#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000226#define ENTER_OVERLAP
227#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000228#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000229#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000230#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000231
232#endif
233
Guido van Rossum97867b21996-08-08 19:09:53 +0000234#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000235#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000236#endif
237
Guido van Rossum18468821994-06-20 07:49:28 +0000238/**** Tkapp Object Declaration ****/
239
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300240static PyObject *Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000241
Guido van Rossum00d93061998-05-28 23:06:38 +0000242typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 PyObject_HEAD
244 Tcl_Interp *interp;
245 int wantobjects;
246 int threaded; /* True if tcl_platform[threaded] */
247 Tcl_ThreadId thread_id;
248 int dispatching;
249 /* We cannot include tclInt.h, as this is internal.
250 So we cache interesting types here. */
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300251 const Tcl_ObjType *OldBooleanType;
252 const Tcl_ObjType *BooleanType;
253 const Tcl_ObjType *ByteArrayType;
254 const Tcl_ObjType *DoubleType;
255 const Tcl_ObjType *IntType;
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300256 const Tcl_ObjType *WideIntType;
257 const Tcl_ObjType *BignumType;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300258 const Tcl_ObjType *ListType;
259 const Tcl_ObjType *ProcBodyType;
260 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000261} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000262
Guido van Rossum18468821994-06-20 07:49:28 +0000263#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000264#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000265
Guido van Rossum35d43371997-08-02 00:09:09 +0000266#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000267(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Barry Warsawfa701a81997-01-16 00:15:11 +0000269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270
Guido van Rossum18468821994-06-20 07:49:28 +0000271/**** Error Handling ****/
272
273static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000274static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000275static int errorInCmd = 0;
276static PyObject *excInCmd;
277static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000278static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000279
Guilherme Polob681df42009-02-09 22:33:59 +0000280#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000281static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000282#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000283
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284
Guido van Rossum18468821994-06-20 07:49:28 +0000285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000286Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000287{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000290}
291
Barry Warsawfa701a81997-01-16 00:15:11 +0000292
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293
Guido van Rossum18468821994-06-20 07:49:28 +0000294/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000295
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000296static int Tkinter_busywaitinterval = 20;
297
Guido van Rossum00d93061998-05-28 23:06:38 +0000298#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000299#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000300
Guido van Rossum00d93061998-05-28 23:06:38 +0000301/* Millisecond sleep() for Unix platforms. */
302
303static void
Fred Drake509d79a2000-07-08 04:04:38 +0000304Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000305{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000311}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000312#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000313
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000314/* Wait up to 1s for the mainloop to come up. */
315
316static int
317WaitForMainloop(TkappObject* self)
318{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
326 }
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000331}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000332#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000335
Guido van Rossum18468821994-06-20 07:49:28 +0000336#define ARGSZ 64
337
Barry Warsawfa701a81997-01-16 00:15:11 +0000338
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339
Guido van Rossum18468821994-06-20 07:49:28 +0000340static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200341unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
342{
343 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
344 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
345 /* Tcl encodes null character as \xc0\x80 */
346 if (memchr(s, '\xc0', size)) {
347 char *buf, *q;
348 const char *e = s + size;
349 PyErr_Clear();
350 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300351 if (buf == NULL) {
352 PyErr_NoMemory();
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200353 return NULL;
Serhiy Storchakab1ebfdd2014-07-14 12:20:15 +0300354 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200355 while (s != e) {
356 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
357 *q++ = '\0';
358 s += 2;
359 }
360 else
361 *q++ = *s++;
362 }
363 s = buf;
364 size = q - s;
365 r = PyUnicode_DecodeUTF8(s, size, NULL);
366 PyMem_Free(buf);
367 }
368 }
369 return r;
370}
371
372static PyObject *
373unicodeFromTclString(const char *s)
374{
375 return unicodeFromTclStringAndSize(s, strlen(s));
376}
377
378static PyObject *
379unicodeFromTclObj(Tcl_Obj *value)
380{
381 int len;
382 char *s = Tcl_GetStringFromObj(value, &len);
383 return unicodeFromTclStringAndSize(s, len);
384}
385
386
387static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000388Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000389{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000390 int argc;
391 char **argv;
392 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000394 if (list == NULL) {
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +0300395 Py_RETURN_NONE;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 }
Guido van Rossum18468821994-06-20 07:49:28 +0000397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
399 /* Not a list.
400 * Could be a quoted string containing funnies, e.g. {"}.
401 * Return the string itself.
402 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200403 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 }
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 if (argc == 0)
407 v = PyUnicode_FromString("");
408 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200409 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000410 else if ((v = PyTuple_New(argc)) != NULL) {
411 int i;
412 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000413
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000414 for (i = 0; i < argc; i++) {
415 if ((w = Split(argv[i])) == NULL) {
416 Py_DECREF(v);
417 v = NULL;
418 break;
419 }
420 PyTuple_SetItem(v, i, w);
421 }
422 }
423 Tcl_Free(FREECAST argv);
424 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000425}
426
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300427/* In some cases, Tcl will still return strings that are supposed to
428 be lists. SplitObj walks through a nested tuple, finding string
429 objects that need to be split. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000430
Martin v. Löwis59683e82008-06-13 07:50:45 +0000431static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000432SplitObj(PyObject *arg)
433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 if (PyTuple_Check(arg)) {
435 int i, size;
436 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 size = PyTuple_Size(arg);
439 result = NULL;
440 /* Recursively invoke SplitObj for all tuple items.
441 If this does not return a new object, no action is
442 needed. */
443 for(i = 0; i < size; i++) {
444 elem = PyTuple_GetItem(arg, i);
445 newelem = SplitObj(elem);
446 if (!newelem) {
447 Py_XDECREF(result);
448 return NULL;
449 }
450 if (!result) {
451 int k;
452 if (newelem == elem) {
453 Py_DECREF(newelem);
454 continue;
455 }
456 result = PyTuple_New(size);
457 if (!result)
458 return NULL;
459 for(k = 0; k < i; k++) {
460 elem = PyTuple_GetItem(arg, k);
461 Py_INCREF(elem);
462 PyTuple_SetItem(result, k, elem);
463 }
464 }
465 PyTuple_SetItem(result, i, newelem);
466 }
467 if (result)
468 return result;
469 /* Fall through, returning arg. */
470 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300471 else if (PyUnicode_Check(arg)) {
472 int argc;
473 char **argv;
474 char *list = PyUnicode_AsUTF8(arg);
475
476 if (list == NULL ||
477 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
478 Py_INCREF(arg);
479 return arg;
480 }
481 Tcl_Free(FREECAST argv);
482 if (argc > 1)
483 return Split(list);
484 /* Fall through, returning arg. */
485 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 else if (PyBytes_Check(arg)) {
487 int argc;
488 char **argv;
489 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
492 Py_INCREF(arg);
493 return arg;
494 }
495 Tcl_Free(FREECAST argv);
496 if (argc > 1)
497 return Split(PyBytes_AsString(arg));
498 /* Fall through, returning arg. */
499 }
500 Py_INCREF(arg);
501 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000502}
Barry Warsawfa701a81997-01-16 00:15:11 +0000503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504
Guido van Rossum18468821994-06-20 07:49:28 +0000505/**** Tkapp Object ****/
506
507#ifndef WITH_APPINIT
508int
Fred Drake509d79a2000-07-08 04:04:38 +0000509Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000510{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 if (Tcl_Init(interp) == TCL_ERROR) {
514 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
515 return TCL_ERROR;
516 }
Guilherme Polob681df42009-02-09 22:33:59 +0000517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 _tkinter_skip_tk_init = Tcl_GetVar(interp,
519 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
520 if (_tkinter_skip_tk_init != NULL &&
521 strcmp(_tkinter_skip_tk_init, "1") == 0) {
522 return TCL_OK;
523 }
Guilherme Polob681df42009-02-09 22:33:59 +0000524
525#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 if (tk_load_failed) {
527 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
528 return TCL_ERROR;
529 }
Guilherme Polob681df42009-02-09 22:33:59 +0000530#endif
531
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000532 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000533#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000535#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
537 return TCL_ERROR;
538 }
Guilherme Polob681df42009-02-09 22:33:59 +0000539
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000541}
542#endif /* !WITH_APPINIT */
543
Guido van Rossum18468821994-06-20 07:49:28 +0000544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000545
Barry Warsawfa701a81997-01-16 00:15:11 +0000546
547/* Initialize the Tk application; see the `main' function in
548 * `tkMain.c'.
549 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000550
Thomas Wouters58d05102000-07-24 14:43:35 +0000551static void EnableEventHook(void); /* Forward */
552static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000553
Barry Warsawfa701a81997-01-16 00:15:11 +0000554static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000555Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000557{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000558 TkappObject *v;
559 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000560
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300561 v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 if (v == NULL)
563 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200564 Py_INCREF(Tkapp_Type);
Barry Warsawfa701a81997-01-16 00:15:11 +0000565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 v->interp = Tcl_CreateInterp();
567 v->wantobjects = wantobjects;
568 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
569 TCL_GLOBAL_ONLY) != NULL;
570 v->thread_id = Tcl_GetCurrentThread();
571 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000572
573#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 if (v->threaded) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +0300575 PyErr_SetString(PyExc_RuntimeError,
576 "Tcl is threaded but _tkinter is not");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 Py_DECREF(v);
578 return 0;
579 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000580#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000581#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000582 if (v->threaded && tcl_lock) {
583 /* If Tcl is threaded, we don't need the lock. */
584 PyThread_free_lock(tcl_lock);
585 tcl_lock = NULL;
586 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000587#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000588
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +0300589 v->OldBooleanType = Tcl_GetObjType("boolean");
590 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 v->ByteArrayType = Tcl_GetObjType("bytearray");
592 v->DoubleType = Tcl_GetObjType("double");
593 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300594 v->WideIntType = Tcl_GetObjType("wideInt");
595 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 v->ListType = Tcl_GetObjType("list");
597 v->ProcBodyType = Tcl_GetObjType("procbody");
598 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 /* Delete the 'exit' command, which can screw things up */
601 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 if (screenName != NULL)
604 Tcl_SetVar2(v->interp, "env", "DISPLAY",
605 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 if (interactive)
608 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
609 else
610 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka07940882014-09-11 10:38:54 +0300613 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 if (!argv0) {
615 PyErr_NoMemory();
616 Py_DECREF(v);
617 return NULL;
618 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200621 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
622 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000623 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
624 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000626 if (! wantTk) {
627 Tcl_SetVar(v->interp,
628 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
629 }
Guilherme Polob681df42009-02-09 22:33:59 +0000630#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000631 else if (tk_load_failed) {
632 Tcl_SetVar(v->interp,
633 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
634 }
Guilherme Polob681df42009-02-09 22:33:59 +0000635#endif
David Aschere2b4b322004-02-18 05:59:53 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 /* some initial arguments need to be in argv */
638 if (sync || use) {
639 char *args;
640 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 if (sync)
643 len += sizeof "-sync";
644 if (use)
645 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000646
Serhiy Storchaka07940882014-09-11 10:38:54 +0300647 args = (char*)attemptckalloc(len);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000648 if (!args) {
649 PyErr_NoMemory();
650 Py_DECREF(v);
651 return NULL;
652 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 args[0] = '\0';
655 if (sync)
656 strcat(args, "-sync");
657 if (use) {
658 if (sync)
659 strcat(args, " ");
660 strcat(args, "-use ");
661 strcat(args, use);
662 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000663
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
665 ckfree(args);
666 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000668 if (Tcl_AppInit(v->interp) != TCL_OK) {
669 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000670#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000671 if (wantTk) {
672 const char *_tkinter_tk_failed;
673 _tkinter_tk_failed = Tcl_GetVar(v->interp,
674 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000675
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000676 if ( _tkinter_tk_failed != NULL &&
677 strcmp(_tkinter_tk_failed, "1") == 0) {
678 tk_load_failed = 1;
679 }
680 }
Guilherme Polob681df42009-02-09 22:33:59 +0000681#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 Py_DECREF((PyObject *)v);
683 return (TkappObject *)result;
684 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000689}
690
Barry Warsawfa701a81997-01-16 00:15:11 +0000691
Benjamin Peterson5879d412009-03-30 14:51:56 +0000692#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000693static void
694Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000696{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000697 Py_BEGIN_ALLOW_THREADS;
698 Tcl_MutexLock(mutex);
699 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
700 Tcl_ThreadAlert(self->thread_id);
701 Tcl_ConditionWait(cond, mutex, NULL);
702 Tcl_MutexUnlock(mutex);
703 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000705#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000706
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707
Guido van Rossum18468821994-06-20 07:49:28 +0000708/** Tcl Eval **/
709
Martin v. Löwisffad6332002-11-26 09:28:05 +0000710typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000711 PyObject_HEAD
712 Tcl_Obj *value;
713 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000714} PyTclObject;
715
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300716static PyObject *PyTclObject_Type;
717#define PyTclObject_Check(v) ((v)->ob_type == (PyTypeObject *) PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000718
719static PyObject *
720newPyTclObject(Tcl_Obj *arg)
721{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 PyTclObject *self;
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300723 self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000724 if (self == NULL)
725 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +0200726 Py_INCREF(PyTclObject_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 Tcl_IncrRefCount(arg);
728 self->value = arg;
729 self->string = NULL;
730 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000731}
732
733static void
734PyTclObject_dealloc(PyTclObject *self)
735{
Antoine Pitrou584e8152013-08-11 00:22:30 +0200736 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737 Tcl_DecrRefCount(self->value);
738 Py_XDECREF(self->string);
739 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +0200740 Py_DECREF(tp);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000741}
742
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000743static char*
744PyTclObject_TclString(PyObject *self)
745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000747}
748
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000749/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000750PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000751"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000752
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000753static PyObject *
754PyTclObject_string(PyTclObject *self, void *ignored)
755{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000756 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200757 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 if (!self->string)
759 return NULL;
760 }
761 Py_INCREF(self->string);
762 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000763}
764
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000765static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000766PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000767{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200768 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000769 Py_INCREF(self->string);
770 return self->string;
771 }
772 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200773 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000774}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000775
Martin v. Löwisffad6332002-11-26 09:28:05 +0000776static PyObject *
777PyTclObject_repr(PyTclObject *self)
778{
Serhiy Storchaka463bd4b2013-09-23 22:49:02 +0300779 PyObject *repr, *str = PyTclObject_str(self, NULL);
780 if (str == NULL)
781 return NULL;
782 repr = PyUnicode_FromFormat("<%s object: %R>",
783 self->value->typePtr->name, str);
784 Py_DECREF(str);
785 return repr;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000786}
787
Mark Dickinson211c6252009-02-01 10:28:51 +0000788#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
789
790static PyObject *
791PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000792{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000793 int result;
794 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000795
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 /* neither argument should be NULL, unless something's gone wrong */
797 if (self == NULL || other == NULL) {
798 PyErr_BadInternalCall();
799 return NULL;
800 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 /* both arguments should be instances of PyTclObject */
803 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
804 v = Py_NotImplemented;
805 goto finished;
806 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 if (self == other)
809 /* fast path when self and other are identical */
810 result = 0;
811 else
812 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
813 Tcl_GetString(((PyTclObject *)other)->value));
814 /* Convert return value to a Boolean */
815 switch (op) {
816 case Py_EQ:
817 v = TEST_COND(result == 0);
818 break;
819 case Py_NE:
820 v = TEST_COND(result != 0);
821 break;
822 case Py_LE:
823 v = TEST_COND(result <= 0);
824 break;
825 case Py_GE:
826 v = TEST_COND(result >= 0);
827 break;
828 case Py_LT:
829 v = TEST_COND(result < 0);
830 break;
831 case Py_GT:
832 v = TEST_COND(result > 0);
833 break;
834 default:
835 PyErr_BadArgument();
836 return NULL;
837 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000838 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000839 Py_INCREF(v);
840 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000841}
842
Martin v. Löwis39195712003-01-04 00:33:13 +0000843PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
844
Martin v. Löwisffad6332002-11-26 09:28:05 +0000845static PyObject*
846get_typename(PyTclObject* obj, void* ignored)
847{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200848 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000849}
850
Martin v. Löwis39195712003-01-04 00:33:13 +0000851
Martin v. Löwisffad6332002-11-26 09:28:05 +0000852static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000853 {"typename", (getter)get_typename, NULL, get_typename__doc__},
854 {"string", (getter)PyTclObject_string, NULL,
855 PyTclObject_string__doc__},
856 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000857};
858
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300859static PyType_Slot PyTclObject_Type_slots[] = {
860 {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
861 {Py_tp_repr, (reprfunc)PyTclObject_repr},
862 {Py_tp_str, (reprfunc)PyTclObject_str},
Andrew Svetlovd2217a82012-10-30 22:49:16 +0200863 {Py_tp_getattro, PyObject_GenericGetAttr},
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300864 {Py_tp_richcompare, PyTclObject_richcompare},
865 {Py_tp_getset, PyTclObject_getsetlist},
866 {0, 0}
Martin v. Löwisffad6332002-11-26 09:28:05 +0000867};
868
Andrew Svetlov11dc6c32012-10-14 16:54:35 +0300869static PyType_Spec PyTclObject_Type_spec = {
870 "_tkinter.Tcl_Obj",
871 sizeof(PyTclObject),
872 0,
873 Py_TPFLAGS_DEFAULT,
874 PyTclObject_Type_slots,
875};
876
877
Serhiy Storchaka79851d72014-05-30 14:24:03 +0300878#if PY_SIZE_MAX > INT_MAX
879#define CHECK_STRING_LENGTH(s) do { \
880 if (s != NULL && strlen(s) >= INT_MAX) { \
881 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
882 return NULL; \
883 } } while(0)
884#else
885#define CHECK_STRING_LENGTH(s)
886#endif
887
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300888#ifdef HAVE_LIBTOMMAMTH
889static Tcl_Obj*
890asBignumObj(PyObject *value)
891{
892 Tcl_Obj *result;
893 int neg;
894 PyObject *hexstr;
895 char *hexchars;
896 mp_int bigValue;
897
898 neg = Py_SIZE(value) < 0;
899 hexstr = _PyLong_Format(value, 16);
900 if (hexstr == NULL)
901 return NULL;
902 hexchars = PyUnicode_AsUTF8(hexstr);
903 if (hexchars == NULL) {
904 Py_DECREF(hexstr);
905 return NULL;
906 }
907 hexchars += neg + 2; /* skip sign and "0x" */
908 mp_init(&bigValue);
909 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
910 mp_clear(&bigValue);
911 Py_DECREF(hexstr);
912 PyErr_NoMemory();
913 return NULL;
914 }
915 Py_DECREF(hexstr);
916 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
917 result = Tcl_NewBignumObj(&bigValue);
918 mp_clear(&bigValue);
919 if (result == NULL) {
920 PyErr_NoMemory();
921 return NULL;
922 }
923 return result;
924}
925#endif
926
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000927static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000928AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000929{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000930 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 if (PyBytes_Check(value))
Serhiy Storchaka74596a82014-07-30 18:33:13 +0300933 return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
934 PyBytes_GET_SIZE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300935
936 if (PyBool_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000937 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300938
939 if (PyLong_CheckExact(value)) {
940 int overflow;
941 long longValue;
942#ifdef TCL_WIDE_INT_TYPE
943 Tcl_WideInt wideValue;
944#endif
945 longValue = PyLong_AsLongAndOverflow(value, &overflow);
946 if (!overflow) {
947 return Tcl_NewLongObj(longValue);
948 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 /* If there is an overflow in the long conversion,
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300950 fall through to wideInt handling. */
951#ifdef TCL_WIDE_INT_TYPE
952 if (_PyLong_AsByteArray((PyLongObject *)value,
953 (unsigned char *)(void *)&wideValue,
954 sizeof(wideValue),
955 PY_LITTLE_ENDIAN,
956 /* signed */ 1) == 0) {
957 return Tcl_NewWideIntObj(wideValue);
958 }
959 PyErr_Clear();
960#endif
961 /* If there is an overflow in the wideInt conversion,
962 fall through to bignum handling. */
963#ifdef HAVE_LIBTOMMAMTH
964 return asBignumObj(value);
965#endif
966 /* If there is no wideInt or bignum support,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000967 fall through to default object handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300969
970 if (PyFloat_Check(value))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300972
973 if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300974 Tcl_Obj **argv;
975 Py_ssize_t size, i;
976
977 size = PyTuple_Size(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +0300978 if (size == 0)
979 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300980 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
981 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
982 return NULL;
983 }
Serhiy Storchaka07940882014-09-11 10:38:54 +0300984 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 if(!argv)
986 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300987 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000988 argv[i] = AsObj(PyTuple_GetItem(value,i));
989 result = Tcl_NewListObj(PyTuple_Size(value), argv);
990 ckfree(FREECAST argv);
991 return result;
992 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +0300993
994 if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200995 void *inbuf;
996 Py_ssize_t size;
997 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000998 Tcl_UniChar *outbuf = NULL;
999 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001000 size_t allocsize;
1001
1002 if (PyUnicode_READY(value) == -1)
1003 return NULL;
1004
1005 inbuf = PyUnicode_DATA(value);
1006 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchakaabf68ce2014-09-11 10:57:13 +03001007 if (size == 0)
1008 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001009 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1010 PyErr_SetString(PyExc_OverflowError, "string is too long");
1011 return NULL;
1012 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001013 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001014 if (kind == sizeof(Tcl_UniChar))
1015 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001016 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Serhiy Storchaka07940882014-09-11 10:38:54 +03001017 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 /* Else overflow occurred, and we take the next exit */
1019 if (!outbuf) {
1020 PyErr_NoMemory();
1021 return NULL;
1022 }
1023 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001024 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1025 /* We cannot test for sizeof(Tcl_UniChar) directly,
1026 so we test for UTF-8 size instead. */
1027#if TCL_UTF_MAX == 3
1028 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001029 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001030 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001031 "character U+%x is above the range "
1032 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001033 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 ckfree(FREECAST outbuf);
1035 return NULL;
1036 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001037#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001038 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001039 }
1040 result = Tcl_NewUnicodeObj(outbuf, size);
1041 ckfree(FREECAST outbuf);
1042 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001043 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001044
1045 if (PyTclObject_Check(value)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001046 Tcl_Obj *v = ((PyTclObject*)value)->value;
1047 Tcl_IncrRefCount(v);
1048 return v;
1049 }
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001050
1051 {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 PyObject *v = PyObject_Str(value);
1053 if (!v)
1054 return 0;
1055 result = AsObj(v);
1056 Py_DECREF(v);
1057 return result;
1058 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001059}
1060
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001061static PyObject *
1062fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1063{
1064 int boolValue;
1065 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1066 return Tkinter_Error(tkapp);
1067 return PyBool_FromLong(boolValue);
1068}
1069
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001070#ifdef TCL_WIDE_INT_TYPE
1071static PyObject*
1072fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1073{
1074 Tcl_WideInt wideValue;
1075 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1076#ifdef HAVE_LONG_LONG
1077 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1078 return PyLong_FromLongLong(wideValue);
1079#endif
1080 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1081 sizeof(wideValue),
1082 PY_LITTLE_ENDIAN,
1083 /* signed */ 1);
1084 }
1085 return NULL;
1086}
1087#endif
1088
1089#ifdef HAVE_LIBTOMMAMTH
1090static PyObject*
1091fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1092{
1093 mp_int bigValue;
1094 unsigned long numBytes;
1095 unsigned char *bytes;
1096 PyObject *res;
1097
1098 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1099 return Tkinter_Error(tkapp);
1100 numBytes = mp_unsigned_bin_size(&bigValue);
1101 bytes = PyMem_Malloc(numBytes);
1102 if (bytes == NULL) {
1103 mp_clear(&bigValue);
1104 return PyErr_NoMemory();
1105 }
1106 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1107 &numBytes) != MP_OKAY) {
1108 mp_clear(&bigValue);
1109 PyMem_Free(bytes);
1110 return PyErr_NoMemory();
1111 }
1112 res = _PyLong_FromByteArray(bytes, numBytes,
1113 /* big-endian */ 0,
1114 /* unsigned */ 0);
1115 PyMem_Free(bytes);
1116 if (res != NULL && bigValue.sign == MP_NEG) {
1117 PyObject *res2 = PyNumber_Negative(res);
1118 Py_DECREF(res);
1119 res = res2;
1120 }
1121 mp_clear(&bigValue);
1122 return res;
1123}
1124#endif
1125
Martin v. Löwisffad6332002-11-26 09:28:05 +00001126static PyObject*
1127FromObj(PyObject* tkapp, Tcl_Obj *value)
1128{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001129 PyObject *result = NULL;
1130 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001131 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001132
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001134 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001136
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001137 if (value->typePtr == app->BooleanType ||
1138 value->typePtr == app->OldBooleanType) {
1139 return fromBoolean(tkapp, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001140 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001141
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 if (value->typePtr == app->ByteArrayType) {
1143 int size;
1144 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1145 return PyBytes_FromStringAndSize(data, size);
1146 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 if (value->typePtr == app->DoubleType) {
1149 return PyFloat_FromDouble(value->internalRep.doubleValue);
1150 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 if (value->typePtr == app->IntType) {
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001153 long longValue;
1154 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1155 return PyLong_FromLong(longValue);
1156 /* If there is an error in the long conversion,
1157 fall through to wideInt handling. */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001158 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001159
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001160#ifdef TCL_WIDE_INT_TYPE
1161 if (value->typePtr == app->IntType ||
1162 value->typePtr == app->WideIntType) {
1163 result = fromWideIntObj(tkapp, value);
1164 if (result != NULL || PyErr_Occurred())
1165 return result;
1166 Tcl_ResetResult(interp);
1167 /* If there is an error in the wideInt conversion,
1168 fall through to bignum handling. */
1169 }
1170#endif
1171
1172#ifdef HAVE_LIBTOMMAMTH
1173 if (value->typePtr == app->IntType ||
1174 value->typePtr == app->WideIntType ||
1175 value->typePtr == app->BignumType) {
1176 return fromBignumObj(tkapp, value);
1177 }
1178#endif
1179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001180 if (value->typePtr == app->ListType) {
1181 int size;
1182 int i, status;
1183 PyObject *elem;
1184 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001185
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001186 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001187 if (status == TCL_ERROR)
1188 return Tkinter_Error(tkapp);
1189 result = PyTuple_New(size);
1190 if (!result)
1191 return NULL;
1192 for (i = 0; i < size; i++) {
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001193 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001194 if (status == TCL_ERROR) {
1195 Py_DECREF(result);
1196 return Tkinter_Error(tkapp);
1197 }
1198 elem = FromObj(tkapp, tcl_elem);
1199 if (!elem) {
1200 Py_DECREF(result);
1201 return NULL;
1202 }
1203 PyTuple_SetItem(result, i, elem);
1204 }
1205 return result;
1206 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001207
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 if (value->typePtr == app->ProcBodyType) {
1209 /* fall through: return tcl object. */
1210 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001212 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001213 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001214 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001215 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001217
Serhiy Storchaka3af7a382015-04-22 10:53:08 +03001218#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakaf7de3dd2015-04-02 10:35:57 +03001219 if (app->BooleanType == NULL &&
1220 strcmp(value->typePtr->name, "booleanString") == 0) {
1221 /* booleanString type is not registered in Tcl */
1222 app->BooleanType = value->typePtr;
1223 return fromBoolean(tkapp, value);
1224 }
1225#endif
1226
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001227#ifdef HAVE_LIBTOMMAMTH
1228 if (app->BignumType == NULL &&
1229 strcmp(value->typePtr->name, "bignum") == 0) {
1230 /* bignum type is not registered in Tcl */
1231 app->BignumType = value->typePtr;
1232 return fromBignumObj(tkapp, value);
1233 }
1234#endif
1235
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001237}
1238
Benjamin Peterson5879d412009-03-30 14:51:56 +00001239#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001241TCL_DECLARE_MUTEX(call_mutex)
1242
1243typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001244 Tcl_Event ev; /* Must be first */
1245 TkappObject *self;
1246 PyObject *args;
1247 int flags;
1248 PyObject **res;
1249 PyObject **exc_type, **exc_value, **exc_tb;
1250 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001251} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001252#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253
1254void
1255Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001256{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 int i;
1258 for (i = 0; i < objc; i++)
1259 Tcl_DecrRefCount(objv[i]);
1260 if (objv != objStore)
1261 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001262}
Guido van Rossum18468821994-06-20 07:49:28 +00001263
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001264/* Convert Python objects to Tcl objects. This must happen in the
1265 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001266
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001267static Tcl_Obj**
1268Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1269{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001270 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001271 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001272 if (args == NULL)
1273 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 else if (!PyTuple_Check(args)) {
1276 objv[0] = AsObj(args);
1277 if (objv[0] == 0)
1278 goto finally;
1279 objc = 1;
1280 Tcl_IncrRefCount(objv[0]);
1281 }
1282 else {
1283 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001284
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001286 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1287 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1288 return NULL;
1289 }
Serhiy Storchaka07940882014-09-11 10:38:54 +03001290 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001291 if (objv == NULL) {
1292 PyErr_NoMemory();
1293 objc = 0;
1294 goto finally;
1295 }
1296 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001298 for (i = 0; i < objc; i++) {
1299 PyObject *v = PyTuple_GetItem(args, i);
1300 if (v == Py_None) {
1301 objc = i;
1302 break;
1303 }
1304 objv[i] = AsObj(v);
1305 if (!objv[i]) {
1306 /* Reset objc, so it attempts to clear
1307 objects only up to i. */
1308 objc = i;
1309 goto finally;
1310 }
1311 Tcl_IncrRefCount(objv[i]);
1312 }
1313 }
1314 *pobjc = objc;
1315 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001316finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 Tkapp_CallDeallocArgs(objv, objStore, objc);
1318 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001319}
Guido van Rossum212643f1998-04-29 16:22:14 +00001320
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001321/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001322
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001323static PyObject*
1324Tkapp_CallResult(TkappObject *self)
1325{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001326 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001327 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001328 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 /* Not sure whether the IncrRef is necessary, but something
1330 may overwrite the interpreter result while we are
1331 converting it. */
1332 Tcl_IncrRefCount(value);
1333 res = FromObj((PyObject*)self, value);
1334 Tcl_DecrRefCount(value);
1335 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001336 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 }
1338 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001339}
Guido van Rossum632de272000-03-29 00:19:50 +00001340
Benjamin Peterson5879d412009-03-30 14:51:56 +00001341#ifdef WITH_THREAD
1342
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001343/* Tkapp_CallProc is the event procedure that is executed in the context of
1344 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1345 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001346
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001347static int
1348Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001350 Tcl_Obj *objStore[ARGSZ];
1351 Tcl_Obj **objv;
1352 int objc;
1353 int i;
1354 ENTER_PYTHON
1355 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1356 if (!objv) {
1357 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1358 *(e->res) = NULL;
1359 }
1360 LEAVE_PYTHON
1361 if (!objv)
1362 goto done;
1363 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1364 ENTER_PYTHON
1365 if (i == TCL_ERROR) {
1366 *(e->res) = NULL;
1367 *(e->exc_type) = NULL;
1368 *(e->exc_tb) = NULL;
1369 *(e->exc_value) = PyObject_CallFunction(
1370 Tkinter_TclError, "s",
1371 Tcl_GetStringResult(e->self->interp));
1372 }
1373 else {
1374 *(e->res) = Tkapp_CallResult(e->self);
1375 }
1376 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001378 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001379done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001380 /* Wake up calling thread. */
1381 Tcl_MutexLock(&call_mutex);
1382 Tcl_ConditionNotify(e->done);
1383 Tcl_MutexUnlock(&call_mutex);
1384 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001385}
1386
Benjamin Peterson5879d412009-03-30 14:51:56 +00001387#endif
1388
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001389/* This is the main entry point for calling a Tcl command.
1390 It supports three cases, with regard to threading:
1391 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1392 the context of the calling thread.
1393 2. Tcl is threaded, caller of the command is in the interpreter thread:
1394 Execute the command in the calling thread. Since the Tcl lock will
1395 not be used, we can merge that with case 1.
1396 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1397 the interpreter thread. Allocation of Tcl objects needs to occur in the
1398 interpreter thread, so we ship the PyObject* args to the target thread,
1399 and perform processing there. */
1400
1401static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001402Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001403{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001404 Tcl_Obj *objStore[ARGSZ];
1405 Tcl_Obj **objv = NULL;
1406 int objc, i;
1407 PyObject *res = NULL;
1408 TkappObject *self = (TkappObject*)selfptr;
1409 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 /* If args is a single tuple, replace with contents of tuple */
1412 if (1 == PyTuple_Size(args)){
1413 PyObject* item = PyTuple_GetItem(args, 0);
1414 if (PyTuple_Check(item))
1415 args = item;
1416 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001417#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1419 /* We cannot call the command directly. Instead, we must
1420 marshal the parameters to the interpreter thread. */
1421 Tkapp_CallEvent *ev;
1422 Tcl_Condition cond = NULL;
1423 PyObject *exc_type, *exc_value, *exc_tb;
1424 if (!WaitForMainloop(self))
1425 return NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03001426 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1427 if (ev == NULL) {
1428 PyErr_NoMemory();
1429 return NULL;
1430 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001431 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1432 ev->self = self;
1433 ev->args = args;
1434 ev->res = &res;
1435 ev->exc_type = &exc_type;
1436 ev->exc_value = &exc_value;
1437 ev->exc_tb = &exc_tb;
1438 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001439
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001442 if (res == NULL) {
1443 if (exc_type)
1444 PyErr_Restore(exc_type, exc_value, exc_tb);
1445 else
1446 PyErr_SetObject(Tkinter_TclError, exc_value);
1447 }
1448 Tcl_ConditionFinalize(&cond);
1449 }
1450 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001451#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 objv = Tkapp_CallArgs(args, objStore, &objc);
1455 if (!objv)
1456 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001460 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001464 if (i == TCL_ERROR)
1465 Tkinter_Error(selfptr);
1466 else
1467 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001469 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001471 Tkapp_CallDeallocArgs(objv, objStore, objc);
1472 }
1473 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001474}
1475
1476
1477static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001478Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001479{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001480 char *script;
1481 PyObject *res = NULL;
1482 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 if (!PyArg_ParseTuple(args, "s:eval", &script))
1485 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001486
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001487 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001490 ENTER_TCL
1491 err = Tcl_Eval(Tkapp_Interp(self), script);
1492 ENTER_OVERLAP
1493 if (err == TCL_ERROR)
1494 res = Tkinter_Error(self);
1495 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001496 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 LEAVE_OVERLAP_TCL
1498 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001499}
1500
1501static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001502Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001503{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001504 char *fileName;
1505 PyObject *res = NULL;
1506 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1509 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001510
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001511 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001512 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 ENTER_TCL
1515 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1516 ENTER_OVERLAP
1517 if (err == TCL_ERROR)
1518 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001519 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001520 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001521 LEAVE_OVERLAP_TCL
1522 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001523}
1524
1525static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001526Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001527{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001528 char *script;
1529 PyObject *res = NULL;
1530 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001531
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001532 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001534
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001535 CHECK_STRING_LENGTH(script);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 ENTER_TCL
1539 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1540 ENTER_OVERLAP
1541 if (err == TCL_ERROR)
1542 res = Tkinter_Error(self);
1543 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001544 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 LEAVE_OVERLAP_TCL
1546 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001547}
1548
1549static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001550Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001551{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1555 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001556 CHECK_STRING_LENGTH(msg);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 ENTER_TCL
1560 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1561 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001562
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03001563 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00001564}
1565
Barry Warsawfa701a81997-01-16 00:15:11 +00001566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001567
Guido van Rossum18468821994-06-20 07:49:28 +00001568/** Tcl Variable **/
1569
Benjamin Peterson5879d412009-03-30 14:51:56 +00001570typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1571
1572#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001573TCL_DECLARE_MUTEX(var_mutex)
1574
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001575typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 Tcl_Event ev; /* must be first */
1577 PyObject *self;
1578 PyObject *args;
1579 int flags;
1580 EventFunc func;
1581 PyObject **res;
1582 PyObject **exc_type;
1583 PyObject **exc_val;
1584 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001585} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001586#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001587
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001588static int
1589varname_converter(PyObject *in, void *_out)
1590{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001591 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 char **out = (char**)_out;
1593 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001594 if (PyBytes_Size(in) > INT_MAX) {
1595 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1596 return 0;
1597 }
1598 s = PyBytes_AsString(in);
1599 if (strlen(s) != PyBytes_Size(in)) {
1600 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1601 return 0;
1602 }
1603 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001604 return 1;
1605 }
1606 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001607 Py_ssize_t size;
1608 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001609 if (s == NULL) {
1610 return 0;
1611 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001612 if (size > INT_MAX) {
1613 PyErr_SetString(PyExc_OverflowError, "string is too long");
1614 return 0;
1615 }
1616 if (strlen(s) != size) {
1617 PyErr_SetString(PyExc_ValueError, "null character in string");
1618 return 0;
1619 }
1620 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001621 return 1;
1622 }
1623 if (PyTclObject_Check(in)) {
1624 *out = PyTclObject_TclString(in);
1625 return 1;
1626 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001627 PyErr_Format(PyExc_TypeError,
1628 "must be str, bytes or Tcl_Obj, not %.50s",
1629 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001631}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001632
Benjamin Peterson5879d412009-03-30 14:51:56 +00001633#ifdef WITH_THREAD
1634
Martin v. Löwis59683e82008-06-13 07:50:45 +00001635static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001636var_perform(VarEvent *ev)
1637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001638 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1639 if (!*(ev->res)) {
1640 PyObject *exc, *val, *tb;
1641 PyErr_Fetch(&exc, &val, &tb);
1642 PyErr_NormalizeException(&exc, &val, &tb);
1643 *(ev->exc_type) = exc;
1644 *(ev->exc_val) = val;
1645 Py_DECREF(tb);
1646 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001647
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001648}
1649
1650static int
1651var_proc(VarEvent* ev, int flags)
1652{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001653 ENTER_PYTHON
1654 var_perform(ev);
1655 Tcl_MutexLock(&var_mutex);
1656 Tcl_ConditionNotify(ev->cond);
1657 Tcl_MutexUnlock(&var_mutex);
1658 LEAVE_PYTHON
1659 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001660}
1661
Benjamin Peterson5879d412009-03-30 14:51:56 +00001662#endif
1663
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001664static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001665var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001666{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001667#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001668 TkappObject *self = (TkappObject*)selfptr;
1669 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1670 TkappObject *self = (TkappObject*)selfptr;
1671 VarEvent *ev;
1672 PyObject *res, *exc_type, *exc_val;
1673 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001675 /* The current thread is not the interpreter thread. Marshal
1676 the call to the interpreter thread, then wait for
1677 completion. */
1678 if (!WaitForMainloop(self))
1679 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001680
Serhiy Storchaka07940882014-09-11 10:38:54 +03001681 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1682 if (ev == NULL) {
1683 PyErr_NoMemory();
1684 return NULL;
1685 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001686 ev->self = selfptr;
1687 ev->args = args;
1688 ev->flags = flags;
1689 ev->func = func;
1690 ev->res = &res;
1691 ev->exc_type = &exc_type;
1692 ev->exc_val = &exc_val;
1693 ev->cond = &cond;
1694 ev->ev.proc = (Tcl_EventProc*)var_proc;
1695 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1696 Tcl_ConditionFinalize(&cond);
1697 if (!res) {
1698 PyErr_SetObject(exc_type, exc_val);
1699 Py_DECREF(exc_type);
1700 Py_DECREF(exc_val);
1701 return NULL;
1702 }
1703 return res;
1704 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001705#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001706 /* Tcl is not threaded, or this is the interpreter thread. */
1707 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001708}
1709
Guido van Rossum18468821994-06-20 07:49:28 +00001710static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001711SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001712{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001713 char *name1, *name2;
1714 PyObject *newValue;
1715 PyObject *res = NULL;
1716 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001717
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001718 switch (PyTuple_GET_SIZE(args)) {
1719 case 2:
1720 if (!PyArg_ParseTuple(args, "O&O:setvar",
1721 varname_converter, &name1, &newValue))
1722 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001723 /* XXX Acquire tcl lock??? */
1724 newval = AsObj(newValue);
1725 if (newval == NULL)
1726 return NULL;
1727 ENTER_TCL
1728 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1729 newval, flags);
1730 ENTER_OVERLAP
1731 if (!ok)
1732 Tkinter_Error(self);
1733 else {
1734 res = Py_None;
1735 Py_INCREF(res);
1736 }
1737 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001738 break;
1739 case 3:
1740 if (!PyArg_ParseTuple(args, "ssO:setvar",
1741 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001742 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001743 CHECK_STRING_LENGTH(name1);
1744 CHECK_STRING_LENGTH(name2);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001745 /* XXX must hold tcl lock already??? */
1746 newval = AsObj(newValue);
1747 ENTER_TCL
1748 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1749 ENTER_OVERLAP
1750 if (!ok)
1751 Tkinter_Error(self);
1752 else {
1753 res = Py_None;
1754 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001755 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001756 LEAVE_OVERLAP_TCL
1757 break;
1758 default:
1759 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1760 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001761 }
1762 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001763}
1764
1765static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001766Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001767{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001768 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001769}
1770
1771static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001772Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001773{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001774 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001775}
1776
Barry Warsawfa701a81997-01-16 00:15:11 +00001777
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001778
Guido van Rossum18468821994-06-20 07:49:28 +00001779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001780GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001781{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 char *name1, *name2=NULL;
1783 PyObject *res = NULL;
1784 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001786 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1787 varname_converter, &name1, &name2))
1788 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001789
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001790 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001791 ENTER_TCL
1792 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1793 ENTER_OVERLAP
1794 if (tres == NULL) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001795 PyErr_SetString(Tkinter_TclError,
1796 Tcl_GetStringResult(Tkapp_Interp(self)));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001797 } else {
1798 if (((TkappObject*)self)->wantobjects) {
1799 res = FromObj(self, tres);
1800 }
1801 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001802 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001803 }
1804 }
1805 LEAVE_OVERLAP_TCL
1806 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001807}
1808
1809static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001810Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001811{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001812 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001813}
1814
1815static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001816Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001817{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001818 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001819}
1820
Barry Warsawfa701a81997-01-16 00:15:11 +00001821
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001822
Guido van Rossum18468821994-06-20 07:49:28 +00001823static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001824UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001825{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 char *name1, *name2=NULL;
1827 int code;
1828 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001830 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1831 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001832
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001833 CHECK_STRING_LENGTH(name1);
1834 CHECK_STRING_LENGTH(name2);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001835 ENTER_TCL
1836 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1837 ENTER_OVERLAP
1838 if (code == TCL_ERROR)
1839 res = Tkinter_Error(self);
1840 else {
1841 Py_INCREF(Py_None);
1842 res = Py_None;
1843 }
1844 LEAVE_OVERLAP_TCL
1845 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001846}
1847
1848static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001849Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001850{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001851 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001852}
1853
1854static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001855Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001856{
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03001857 return var_invoke(UnsetVar, self, args,
1858 TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001859}
1860
Barry Warsawfa701a81997-01-16 00:15:11 +00001861
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001862
Guido van Rossum18468821994-06-20 07:49:28 +00001863/** Tcl to Python **/
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001868 char *s;
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001869#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
1870 Tcl_Obj *value;
1871 PyObject *result;
1872#else
1873 int intValue;
1874#endif
Guido van Rossum18468821994-06-20 07:49:28 +00001875
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001876 if (PyTuple_Size(args) == 1) {
1877 PyObject* o = PyTuple_GetItem(args, 0);
1878 if (PyLong_Check(o)) {
1879 Py_INCREF(o);
1880 return o;
1881 }
1882 }
1883 if (!PyArg_ParseTuple(args, "s:getint", &s))
1884 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001885 CHECK_STRING_LENGTH(s);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001886#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
1887 value = Tcl_NewStringObj(s, -1);
1888 if (value == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 return Tkinter_Error(self);
Serhiy Storchakaea134da2015-04-02 18:46:50 +03001890 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1891 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1892
1893 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1894 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1895 */
1896#ifdef HAVE_LIBTOMMAMTH
1897 result = fromBignumObj(self, value);
1898#else
1899 result = fromWideIntObj(self, value);
1900#endif
1901 Tcl_DecrRefCount(value);
1902 if (result != NULL || PyErr_Occurred())
1903 return result;
1904#else
1905 if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
1906 return PyLong_FromLong(intValue);
1907#endif
1908 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001909}
1910
1911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 char *s;
1915 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001916
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001917 if (PyTuple_Size(args) == 1) {
1918 PyObject *o = PyTuple_GetItem(args, 0);
1919 if (PyFloat_Check(o)) {
1920 Py_INCREF(o);
1921 return o;
1922 }
1923 }
1924 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1925 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001926 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1928 return Tkinter_Error(self);
1929 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001930}
1931
1932static PyObject *
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001933Tkapp_GetBoolean(PyObject *self, PyObject *arg)
Guido van Rossum18468821994-06-20 07:49:28 +00001934{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001935 char *s;
1936 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001937
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001938 if (PyLong_Check(arg)) { /* int or bool */
1939 return PyBool_FromLong(Py_SIZE(arg) != 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 }
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03001941
1942 if (PyTclObject_Check(arg)) {
1943 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
1944 ((PyTclObject*)arg)->value,
1945 &v) == TCL_ERROR)
1946 return Tkinter_Error(self);
1947 return PyBool_FromLong(v);
1948 }
1949
1950 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001952 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001953 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1954 return Tkinter_Error(self);
1955 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001956}
1957
1958static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001959Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001960{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001961 char *s;
1962 PyObject *res = NULL;
1963 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001964
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001965 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1966 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001967
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001968 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001969 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971 ENTER_TCL
1972 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1973 ENTER_OVERLAP
1974 if (retval == TCL_ERROR)
1975 res = Tkinter_Error(self);
1976 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001977 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001978 LEAVE_OVERLAP_TCL
1979 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001980}
1981
1982static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001983Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001985 char *s;
1986 PyObject *res = NULL;
1987 int retval;
1988 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001989
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1991 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001992
Serhiy Storchaka79851d72014-05-30 14:24:03 +03001993 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001994 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001995
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001996 ENTER_TCL
1997 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1998 ENTER_OVERLAP
1999 if (retval == TCL_ERROR)
2000 res = Tkinter_Error(self);
2001 else
2002 res = Py_BuildValue("l", v);
2003 LEAVE_OVERLAP_TCL
2004 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002005}
2006
2007static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002008Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002009{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 char *s;
2011 PyObject *res = NULL;
2012 double v;
2013 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002015 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2016 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002017 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002018 CHECK_TCL_APPARTMENT;
2019 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2020 ENTER_TCL
2021 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2022 ENTER_OVERLAP
2023 PyFPE_END_PROTECT(retval)
2024 if (retval == TCL_ERROR)
2025 res = Tkinter_Error(self);
2026 else
2027 res = Py_BuildValue("d", v);
2028 LEAVE_OVERLAP_TCL
2029 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002030}
2031
2032static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002033Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002035 char *s;
2036 PyObject *res = NULL;
2037 int retval;
2038 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002039
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002040 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2041 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002042 CHECK_STRING_LENGTH(s);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002043 CHECK_TCL_APPARTMENT;
2044 ENTER_TCL
2045 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2046 ENTER_OVERLAP
2047 if (retval == TCL_ERROR)
2048 res = Tkinter_Error(self);
2049 else
2050 res = Py_BuildValue("i", v);
2051 LEAVE_OVERLAP_TCL
2052 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Barry Warsawfa701a81997-01-16 00:15:11 +00002055
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002056
Guido van Rossum18468821994-06-20 07:49:28 +00002057static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002058Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002059{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002060 char *list;
2061 int argc;
2062 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002063 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002064 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002066 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2067 return NULL;
2068 if (PyTclObject_Check(arg)) {
2069 int objc;
2070 Tcl_Obj **objv;
2071 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2072 ((PyTclObject*)arg)->value,
2073 &objc, &objv) == TCL_ERROR) {
2074 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002075 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002076 if (!(v = PyTuple_New(objc)))
2077 return NULL;
2078 for (i = 0; i < objc; i++) {
2079 PyObject *s = FromObj(self, objv[i]);
2080 if (!s || PyTuple_SetItem(v, i, s)) {
2081 Py_DECREF(v);
2082 return NULL;
2083 }
2084 }
2085 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002086 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002087 if (PyTuple_Check(arg)) {
2088 Py_INCREF(arg);
2089 return arg;
2090 }
2091
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2093 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002094
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002095 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002096 if (Tcl_SplitList(Tkapp_Interp(self), list,
2097 &argc, &argv) == TCL_ERROR) {
2098 PyMem_Free(list);
2099 return Tkinter_Error(self);
2100 }
Guido van Rossum18468821994-06-20 07:49:28 +00002101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 if (!(v = PyTuple_New(argc)))
2103 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002105 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002106 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002107 if (!s || PyTuple_SetItem(v, i, s)) {
2108 Py_DECREF(v);
2109 v = NULL;
2110 goto finally;
2111 }
2112 }
Guido van Rossum18468821994-06-20 07:49:28 +00002113
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002115 ckfree(FREECAST argv);
2116 PyMem_Free(list);
2117 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002118}
2119
2120static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002121Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002122{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002123 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002125
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002126 if (!PyArg_ParseTuple(args, "O:split", &arg))
2127 return NULL;
2128 if (PyTclObject_Check(arg)) {
2129 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2130 int objc;
2131 Tcl_Obj **objv;
2132 int i;
2133 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2134 &objc, &objv) == TCL_ERROR) {
2135 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002136 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002137 if (objc == 0)
2138 return PyUnicode_FromString("");
2139 if (objc == 1)
2140 return FromObj(self, objv[0]);
2141 if (!(v = PyTuple_New(objc)))
2142 return NULL;
2143 for (i = 0; i < objc; i++) {
2144 PyObject *s = FromObj(self, objv[i]);
2145 if (!s || PyTuple_SetItem(v, i, s)) {
2146 Py_DECREF(v);
2147 return NULL;
2148 }
2149 }
2150 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002151 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002152 if (PyTuple_Check(arg))
2153 return SplitObj(arg);
2154
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002155 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2156 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002157 CHECK_STRING_LENGTH(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002158 v = Split(list);
2159 PyMem_Free(list);
2160 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002161}
2162
Barry Warsawfa701a81997-01-16 00:15:11 +00002163
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002164
Guido van Rossum18468821994-06-20 07:49:28 +00002165/** Tcl Command **/
2166
Guido van Rossum00d93061998-05-28 23:06:38 +00002167/* Client data struct */
2168typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002169 PyObject *self;
2170 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002171} PythonCmd_ClientData;
2172
2173static int
Fred Drake509d79a2000-07-08 04:04:38 +00002174PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002175{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002176 errorInCmd = 1;
2177 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2178 LEAVE_PYTHON
2179 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002180}
2181
Guido van Rossum18468821994-06-20 07:49:28 +00002182/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002183 * function or method.
2184 */
Guido van Rossum18468821994-06-20 07:49:28 +00002185static int
Fred Drake509d79a2000-07-08 04:04:38 +00002186PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002187{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002188 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002189 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002190 int i, rv;
2191 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002194
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002195 /* TBD: no error checking here since we know, via the
2196 * Tkapp_CreateCommand() that the client data is a two-tuple
2197 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002198 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002200 /* Create argument list (argv1, ..., argvN) */
2201 if (!(arg = PyTuple_New(argc - 1)))
2202 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002203
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002204 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002205 PyObject *s = unicodeFromTclString(argv[i + 1]);
2206 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002207 Py_DECREF(arg);
2208 return PythonCmd_Error(interp);
2209 }
2210 }
2211 res = PyEval_CallObject(func, arg);
2212 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002214 if (res == NULL)
2215 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002216
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002217 obj_res = AsObj(res);
2218 if (obj_res == NULL) {
2219 Py_DECREF(res);
2220 return PythonCmd_Error(interp);
2221 }
2222 else {
2223 Tcl_SetObjResult(interp, obj_res);
2224 rv = TCL_OK;
2225 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002227 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002230
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002231 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002232}
2233
2234static void
Fred Drake509d79a2000-07-08 04:04:38 +00002235PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002236{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002237 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002238
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002239 ENTER_PYTHON
2240 Py_XDECREF(data->self);
2241 Py_XDECREF(data->func);
2242 PyMem_DEL(data);
2243 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002244}
2245
Barry Warsawfa701a81997-01-16 00:15:11 +00002246
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002247
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002248
Benjamin Peterson5879d412009-03-30 14:51:56 +00002249#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002250TCL_DECLARE_MUTEX(command_mutex)
2251
2252typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002253 Tcl_Event ev;
2254 Tcl_Interp* interp;
2255 char *name;
2256 int create;
2257 int *status;
2258 ClientData *data;
2259 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002260} CommandEvent;
2261
2262static int
2263Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002264{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002265 if (ev->create)
2266 *ev->status = Tcl_CreateCommand(
2267 ev->interp, ev->name, PythonCmd,
2268 ev->data, PythonCmdDelete) == NULL;
2269 else
2270 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2271 Tcl_MutexLock(&command_mutex);
2272 Tcl_ConditionNotify(ev->done);
2273 Tcl_MutexUnlock(&command_mutex);
2274 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002275}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002276#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002277
2278static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002279Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002280{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002281 TkappObject *self = (TkappObject*)selfptr;
2282 PythonCmd_ClientData *data;
2283 char *cmdName;
2284 PyObject *func;
2285 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2288 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002289 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002290 if (!PyCallable_Check(func)) {
2291 PyErr_SetString(PyExc_TypeError, "command not callable");
2292 return NULL;
2293 }
Guido van Rossum18468821994-06-20 07:49:28 +00002294
Martin v. Löwisa9656492003-03-30 08:44:58 +00002295#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002296 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2297 !WaitForMainloop(self))
2298 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002299#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002300
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 data = PyMem_NEW(PythonCmd_ClientData, 1);
2302 if (!data)
2303 return PyErr_NoMemory();
2304 Py_INCREF(self);
2305 Py_INCREF(func);
2306 data->self = selfptr;
2307 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002308#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002309 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2310 Tcl_Condition cond = NULL;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002311 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2312 if (ev == NULL) {
2313 PyErr_NoMemory();
2314 PyMem_DEL(data);
2315 return NULL;
2316 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2318 ev->interp = self->interp;
2319 ev->create = 1;
2320 ev->name = cmdName;
2321 ev->data = (ClientData)data;
2322 ev->status = &err;
2323 ev->done = &cond;
2324 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2325 Tcl_ConditionFinalize(&cond);
2326 }
2327 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002328#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002329 {
2330 ENTER_TCL
2331 err = Tcl_CreateCommand(
2332 Tkapp_Interp(self), cmdName, PythonCmd,
2333 (ClientData)data, PythonCmdDelete) == NULL;
2334 LEAVE_TCL
2335 }
2336 if (err) {
2337 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2338 PyMem_DEL(data);
2339 return NULL;
2340 }
Guido van Rossum18468821994-06-20 07:49:28 +00002341
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002342 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002343}
2344
Barry Warsawfa701a81997-01-16 00:15:11 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346
Guido van Rossum18468821994-06-20 07:49:28 +00002347static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002348Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 TkappObject *self = (TkappObject*)selfptr;
2351 char *cmdName;
2352 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002354 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2355 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03002356 CHECK_STRING_LENGTH(cmdName);
Benjamin Peterson5879d412009-03-30 14:51:56 +00002357
2358#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002359 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2360 Tcl_Condition cond = NULL;
2361 CommandEvent *ev;
Serhiy Storchaka07940882014-09-11 10:38:54 +03002362 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2363 if (ev == NULL) {
2364 PyErr_NoMemory();
2365 return NULL;
2366 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002367 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2368 ev->interp = self->interp;
2369 ev->create = 0;
2370 ev->name = cmdName;
2371 ev->status = &err;
2372 ev->done = &cond;
2373 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2374 &command_mutex);
2375 Tcl_ConditionFinalize(&cond);
2376 }
2377 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002378#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 {
2380 ENTER_TCL
2381 err = Tcl_DeleteCommand(self->interp, cmdName);
2382 LEAVE_TCL
2383 }
2384 if (err == -1) {
2385 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2386 return NULL;
2387 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002388 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002389}
2390
Barry Warsawfa701a81997-01-16 00:15:11 +00002391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002392
Guido van Rossum00d93061998-05-28 23:06:38 +00002393#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002394/** File Handler **/
2395
Guido van Rossum00d93061998-05-28 23:06:38 +00002396typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002397 PyObject *func;
2398 PyObject *file;
2399 int id;
2400 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002401} FileHandler_ClientData;
2402
2403static FileHandler_ClientData *HeadFHCD;
2404
2405static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002406NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002407{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002408 FileHandler_ClientData *p;
2409 p = PyMem_NEW(FileHandler_ClientData, 1);
2410 if (p != NULL) {
2411 Py_XINCREF(func);
2412 Py_XINCREF(file);
2413 p->func = func;
2414 p->file = file;
2415 p->id = id;
2416 p->next = HeadFHCD;
2417 HeadFHCD = p;
2418 }
2419 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002420}
2421
2422static void
Fred Drake509d79a2000-07-08 04:04:38 +00002423DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002424{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002425 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 pp = &HeadFHCD;
2428 while ((p = *pp) != NULL) {
2429 if (p->id == id) {
2430 *pp = p->next;
2431 Py_XDECREF(p->func);
2432 Py_XDECREF(p->file);
2433 PyMem_DEL(p);
2434 }
2435 else
2436 pp = &p->next;
2437 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002438}
2439
Guido van Rossuma597dde1995-01-10 20:56:29 +00002440static void
Fred Drake509d79a2000-07-08 04:04:38 +00002441FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002443 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2444 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002446 ENTER_PYTHON
2447 func = data->func;
2448 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002449
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002450 arg = Py_BuildValue("(Oi)", file, (long) mask);
2451 res = PyEval_CallObject(func, arg);
2452 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002454 if (res == NULL) {
2455 errorInCmd = 1;
2456 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2457 }
2458 Py_XDECREF(res);
2459 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002460}
2461
Guido van Rossum18468821994-06-20 07:49:28 +00002462static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002463Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2464 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002465{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002466 FileHandler_ClientData *data;
2467 PyObject *file, *func;
2468 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002470 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2471 &file, &mask, &func))
2472 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002473
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002474 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002475
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 tfile = PyObject_AsFileDescriptor(file);
2477 if (tfile < 0)
2478 return NULL;
2479 if (!PyCallable_Check(func)) {
2480 PyErr_SetString(PyExc_TypeError, "bad argument list");
2481 return NULL;
2482 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002483
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002484 data = NewFHCD(func, file, tfile);
2485 if (data == NULL)
2486 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 /* Ought to check for null Tcl_File object... */
2489 ENTER_TCL
2490 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2491 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002492 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002493}
2494
2495static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002496Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002497{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002498 PyObject *file;
2499 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002500
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002501 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2502 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002503
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002504 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002505
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 tfile = PyObject_AsFileDescriptor(file);
2507 if (tfile < 0)
2508 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002509
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002510 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002511
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002512 /* Ought to check for null Tcl_File object... */
2513 ENTER_TCL
2514 Tcl_DeleteFileHandler(tfile);
2515 LEAVE_TCL
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002516 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002517}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002518#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002521/**** Tktt Object (timer token) ****/
2522
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002523static PyObject *Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002524
Guido van Rossum00d93061998-05-28 23:06:38 +00002525typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002526 PyObject_HEAD
2527 Tcl_TimerToken token;
2528 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002529} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002530
2531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002532Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002533{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002534 TkttObject *v = (TkttObject *)self;
2535 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002536
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002537 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2538 return NULL;
2539 if (v->token != NULL) {
2540 Tcl_DeleteTimerHandler(v->token);
2541 v->token = NULL;
2542 }
2543 if (func != NULL) {
2544 v->func = NULL;
2545 Py_DECREF(func);
2546 Py_DECREF(v); /* See Tktt_New() */
2547 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002548 Py_RETURN_NONE;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002549}
2550
2551static PyMethodDef Tktt_methods[] =
2552{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002553 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2554 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002555};
2556
2557static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002558Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002559{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002560 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002561
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002562 v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002563 if (v == NULL)
2564 return NULL;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002565 Py_INCREF(Tktt_Type);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002567 Py_INCREF(func);
2568 v->token = NULL;
2569 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 /* Extra reference, deleted when called or when handler is deleted */
2572 Py_INCREF(v);
2573 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002574}
2575
2576static void
Fred Drake509d79a2000-07-08 04:04:38 +00002577Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002578{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 TkttObject *v = (TkttObject *)self;
2580 PyObject *func = v->func;
Antoine Pitrou584e8152013-08-11 00:22:30 +02002581 PyObject *tp = (PyObject *) Py_TYPE(self);
Guido van Rossum00d93061998-05-28 23:06:38 +00002582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002583 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002585 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002586 Py_DECREF(tp);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002587}
2588
Guido van Rossum597ac201998-05-12 14:36:19 +00002589static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002590Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002591{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002592 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002593 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2594 v,
2595 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002596}
2597
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002598static PyType_Slot Tktt_Type_slots[] = {
2599 {Py_tp_dealloc, Tktt_Dealloc},
2600 {Py_tp_repr, Tktt_Repr},
2601 {Py_tp_methods, Tktt_methods},
2602 {0, 0}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002603};
2604
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002605static PyType_Spec Tktt_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002606 "_tkinter.tktimertoken",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002607 sizeof(TkttObject),
2608 0,
2609 Py_TPFLAGS_DEFAULT,
2610 Tktt_Type_slots,
2611};
Barry Warsawfa701a81997-01-16 00:15:11 +00002612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002614/** Timer Handler **/
2615
2616static void
Fred Drake509d79a2000-07-08 04:04:38 +00002617TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 TkttObject *v = (TkttObject *)clientData;
2620 PyObject *func = v->func;
2621 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002622
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002623 if (func == NULL)
2624 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002625
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002626 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002630 res = PyEval_CallObject(func, NULL);
2631 Py_DECREF(func);
2632 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002633
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 if (res == NULL) {
2635 errorInCmd = 1;
2636 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2637 }
2638 else
2639 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002641 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002642}
2643
2644static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002645Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002646{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002647 int milliseconds;
2648 PyObject *func;
2649 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002650
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002651 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2652 &milliseconds, &func))
2653 return NULL;
2654 if (!PyCallable_Check(func)) {
2655 PyErr_SetString(PyExc_TypeError, "bad argument list");
2656 return NULL;
2657 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002658
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002659 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002660
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002661 v = Tktt_New(func);
2662 if (v) {
2663 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2664 (ClientData)v);
2665 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002667 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002668}
2669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670
Guido van Rossum18468821994-06-20 07:49:28 +00002671/** Event Loop **/
2672
Guido van Rossum18468821994-06-20 07:49:28 +00002673static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002674Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002675{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 int threshold = 0;
2677 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002678#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002679 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002680#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002682 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2683 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002684
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002685 CHECK_TCL_APPARTMENT;
2686 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002687
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002688 quitMainLoop = 0;
2689 while (Tk_GetNumMainWindows() > threshold &&
2690 !quitMainLoop &&
2691 !errorInCmd)
2692 {
2693 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002694
2695#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002696 if (self->threaded) {
2697 /* Allow other Python threads to run. */
2698 ENTER_TCL
2699 result = Tcl_DoOneEvent(0);
2700 LEAVE_TCL
2701 }
2702 else {
2703 Py_BEGIN_ALLOW_THREADS
2704 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2705 tcl_tstate = tstate;
2706 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2707 tcl_tstate = NULL;
2708 if(tcl_lock)PyThread_release_lock(tcl_lock);
2709 if (result == 0)
2710 Sleep(Tkinter_busywaitinterval);
2711 Py_END_ALLOW_THREADS
2712 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002713#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002714 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002715#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002717 if (PyErr_CheckSignals() != 0) {
2718 self->dispatching = 0;
2719 return NULL;
2720 }
2721 if (result < 0)
2722 break;
2723 }
2724 self->dispatching = 0;
2725 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 if (errorInCmd) {
2728 errorInCmd = 0;
2729 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2730 excInCmd = valInCmd = trbInCmd = NULL;
2731 return NULL;
2732 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002733 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002734}
2735
2736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002737Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002739 int flags = 0;
2740 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002741
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002742 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2743 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002744
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002745 ENTER_TCL
2746 rv = Tcl_DoOneEvent(flags);
2747 LEAVE_TCL
2748 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002749}
2750
2751static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002752Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002753{
2754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002755 if (!PyArg_ParseTuple(args, ":quit"))
2756 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 quitMainLoop = 1;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002759 Py_RETURN_NONE;
Guido van Rossum18468821994-06-20 07:49:28 +00002760}
2761
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002762static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002763Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002764{
2765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002766 if (!PyArg_ParseTuple(args, ":interpaddr"))
2767 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002768
Victor Stinnere1040e22013-09-05 00:22:24 +02002769 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002770}
2771
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002772static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002773Tkapp_TkInit(PyObject *self, PyObject *args)
2774{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002775 Tcl_Interp *interp = Tkapp_Interp(self);
2776 const char * _tk_exists = NULL;
2777 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002778
Guilherme Polob681df42009-02-09 22:33:59 +00002779#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002780 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2781 * first call failed.
2782 * To avoid the deadlock, we just refuse the second call through
2783 * a static variable.
2784 */
2785 if (tk_load_failed) {
2786 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2787 return NULL;
2788 }
Guilherme Polob681df42009-02-09 22:33:59 +00002789#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002790
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002791 /* We want to guard against calling Tk_Init() multiple times */
2792 CHECK_TCL_APPARTMENT;
2793 ENTER_TCL
2794 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2795 ENTER_OVERLAP
2796 if (err == TCL_ERROR) {
2797 /* This sets an exception, but we cannot return right
2798 away because we need to exit the overlap first. */
2799 Tkinter_Error(self);
2800 } else {
2801 _tk_exists = Tkapp_Result(self);
2802 }
2803 LEAVE_OVERLAP_TCL
2804 if (err == TCL_ERROR) {
2805 return NULL;
2806 }
2807 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2808 if (Tk_Init(interp) == TCL_ERROR) {
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03002809 PyErr_SetString(Tkinter_TclError,
2810 Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002811#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002812 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002813#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002814 return NULL;
2815 }
2816 }
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002817 Py_RETURN_NONE;
David Aschere2b4b322004-02-18 05:59:53 +00002818}
Barry Warsawfa701a81997-01-16 00:15:11 +00002819
Martin v. Löwisffad6332002-11-26 09:28:05 +00002820static PyObject *
2821Tkapp_WantObjects(PyObject *self, PyObject *args)
2822{
2823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002824 int wantobjects = -1;
2825 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2826 return NULL;
2827 if (wantobjects == -1)
2828 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2829 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002830
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002831 Py_RETURN_NONE;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002832}
2833
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002834static PyObject *
2835Tkapp_WillDispatch(PyObject *self, PyObject *args)
2836{
2837
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002839
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03002840 Py_RETURN_NONE;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002841}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002843
Guido van Rossum18468821994-06-20 07:49:28 +00002844/**** Tkapp Method List ****/
2845
2846static PyMethodDef Tkapp_methods[] =
2847{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002848 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2849 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2850 {"call", Tkapp_Call, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 {"eval", Tkapp_Eval, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2853 {"record", Tkapp_Record, METH_VARARGS},
2854 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2855 {"setvar", Tkapp_SetVar, METH_VARARGS},
2856 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2857 {"getvar", Tkapp_GetVar, METH_VARARGS},
2858 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2859 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2860 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2861 {"getint", Tkapp_GetInt, METH_VARARGS},
2862 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchaka9a6e2012015-04-04 12:43:01 +03002863 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2865 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2866 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2867 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2868 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2869 {"split", Tkapp_Split, METH_VARARGS},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002870 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2871 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002872#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002873 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2874 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002875#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002876 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2877 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2878 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2879 {"quit", Tkapp_Quit, METH_VARARGS},
2880 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2881 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2882 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002883};
2884
Barry Warsawfa701a81997-01-16 00:15:11 +00002885
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002886
Guido van Rossum18468821994-06-20 07:49:28 +00002887/**** Tkapp Type Methods ****/
2888
2889static void
Fred Drake509d79a2000-07-08 04:04:38 +00002890Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002891{
Antoine Pitrou584e8152013-08-11 00:22:30 +02002892 PyObject *tp = (PyObject *) Py_TYPE(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002893 /*CHECK_TCL_APPARTMENT;*/
2894 ENTER_TCL
2895 Tcl_DeleteInterp(Tkapp_Interp(self));
2896 LEAVE_TCL
2897 PyObject_Del(self);
Antoine Pitrou584e8152013-08-11 00:22:30 +02002898 Py_DECREF(tp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002899 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002900}
2901
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002902static PyType_Slot Tkapp_Type_slots[] = {
2903 {Py_tp_dealloc, Tkapp_Dealloc},
2904 {Py_tp_methods, Tkapp_methods},
2905 {0, 0}
2906};
2907
2908
2909static PyType_Spec Tkapp_Type_spec = {
Serhiy Storchakaefdc16f92015-03-01 09:06:29 +02002910 "_tkinter.tkapp",
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03002911 sizeof(TkappObject),
2912 0,
2913 Py_TPFLAGS_DEFAULT,
2914 Tkapp_Type_slots,
Guido van Rossum18468821994-06-20 07:49:28 +00002915};
2916
Barry Warsawfa701a81997-01-16 00:15:11 +00002917
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002918
Guido van Rossum18468821994-06-20 07:49:28 +00002919/**** Tkinter Module ****/
2920
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002921typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002922 PyObject* tuple;
2923 int size; /* current size */
2924 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002925} FlattenContext;
2926
2927static int
2928_bump(FlattenContext* context, int size)
2929{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002930 /* expand tuple to hold (at least) size new items.
2931 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002934
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002935 if (maxsize < context->size + size)
2936 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002938 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002939
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002940 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002941}
2942
2943static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002944_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002945{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002946 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002947
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002948 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002949
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002950 if (depth > 1000) {
2951 PyErr_SetString(PyExc_ValueError,
2952 "nesting too deep in _flatten");
2953 return 0;
2954 } else if (PyList_Check(item)) {
2955 size = PyList_GET_SIZE(item);
2956 /* preallocate (assume no nesting) */
2957 if (context->size + size > context->maxsize &&
2958 !_bump(context, size))
2959 return 0;
2960 /* copy items to output tuple */
2961 for (i = 0; i < size; i++) {
2962 PyObject *o = PyList_GET_ITEM(item, i);
2963 if (PyList_Check(o) || PyTuple_Check(o)) {
2964 if (!_flatten1(context, o, depth + 1))
2965 return 0;
2966 } else if (o != Py_None) {
2967 if (context->size + 1 > context->maxsize &&
2968 !_bump(context, 1))
2969 return 0;
2970 Py_INCREF(o);
2971 PyTuple_SET_ITEM(context->tuple,
2972 context->size++, o);
2973 }
2974 }
2975 } else if (PyTuple_Check(item)) {
2976 /* same, for tuples */
2977 size = PyTuple_GET_SIZE(item);
2978 if (context->size + size > context->maxsize &&
2979 !_bump(context, size))
2980 return 0;
2981 for (i = 0; i < size; i++) {
2982 PyObject *o = PyTuple_GET_ITEM(item, i);
2983 if (PyList_Check(o) || PyTuple_Check(o)) {
2984 if (!_flatten1(context, o, depth + 1))
2985 return 0;
2986 } else if (o != Py_None) {
2987 if (context->size + 1 > context->maxsize &&
2988 !_bump(context, 1))
2989 return 0;
2990 Py_INCREF(o);
2991 PyTuple_SET_ITEM(context->tuple,
2992 context->size++, o);
2993 }
2994 }
2995 } else {
2996 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2997 return 0;
2998 }
2999 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003000}
3001
3002static PyObject *
3003Tkinter_Flatten(PyObject* self, PyObject* args)
3004{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003005 FlattenContext context;
3006 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003008 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3009 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003010
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003011 context.maxsize = PySequence_Size(item);
3012 if (context.maxsize < 0)
3013 return NULL;
3014 if (context.maxsize == 0)
3015 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003016
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003017 context.tuple = PyTuple_New(context.maxsize);
3018 if (!context.tuple)
3019 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003020
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003021 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003023 if (!_flatten1(&context, item,0))
3024 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003026 if (_PyTuple_Resize(&context.tuple, context.size))
3027 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003028
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003030}
3031
Guido van Rossum18468821994-06-20 07:49:28 +00003032static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003033Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003035 char *screenName = NULL;
3036 char *baseName = NULL; /* XXX this is not used anymore;
3037 try getting rid of it. */
3038 char *className = NULL;
3039 int interactive = 0;
3040 int wantobjects = 0;
3041 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3042 int sync = 0; /* pass -sync to wish */
3043 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003044
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003045 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003046
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003047 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3048 &screenName, &baseName, &className,
3049 &interactive, &wantobjects, &wantTk,
3050 &sync, &use))
3051 return NULL;
Serhiy Storchaka79851d72014-05-30 14:24:03 +03003052 CHECK_STRING_LENGTH(screenName);
3053 CHECK_STRING_LENGTH(baseName);
3054 CHECK_STRING_LENGTH(className);
3055 CHECK_STRING_LENGTH(use);
Guido van Rossum18468821994-06-20 07:49:28 +00003056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003057 return (PyObject *) Tkapp_New(screenName, className,
Andrew Svetlovd0ad0b32012-10-16 22:50:34 +03003058 interactive, wantobjects, wantTk,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003059 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003060}
3061
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003062static PyObject *
3063Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 int new_val;
3066 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3067 return NULL;
3068 if (new_val < 0) {
3069 PyErr_SetString(PyExc_ValueError,
3070 "busywaitinterval must be >= 0");
3071 return NULL;
3072 }
3073 Tkinter_busywaitinterval = new_val;
Andrew Svetlov9dc5bdd2012-10-07 12:08:38 +03003074 Py_RETURN_NONE;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003075}
3076
3077static char setbusywaitinterval_doc[] =
3078"setbusywaitinterval(n) -> None\n\
3079\n\
3080Set the busy-wait interval in milliseconds between successive\n\
3081calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3082It should be set to a divisor of the maximum time between\n\
3083frames in an animation.";
3084
3085static PyObject *
3086Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3087{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003088 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003089}
3090
3091static char getbusywaitinterval_doc[] =
3092"getbusywaitinterval() -> int\n\
3093\n\
3094Return the current busy-wait interval between successive\n\
3095calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3096
Guido van Rossum18468821994-06-20 07:49:28 +00003097static PyMethodDef moduleMethods[] =
3098{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003099 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3100 {"create", Tkinter_Create, METH_VARARGS},
3101 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3102 setbusywaitinterval_doc},
3103 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3104 METH_NOARGS, getbusywaitinterval_doc},
3105 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003106};
3107
Guido van Rossum7bf15641998-05-22 18:28:17 +00003108#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003109
3110static int stdin_ready = 0;
3111
Guido van Rossumad4db171998-06-13 13:56:28 +00003112#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003113static void
Fred Drake509d79a2000-07-08 04:04:38 +00003114MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003115{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003116 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003117}
Guido van Rossumad4db171998-06-13 13:56:28 +00003118#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003119
Martin v. Löwisa9656492003-03-30 08:44:58 +00003120#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003121static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003122#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003123
Guido van Rossum18468821994-06-20 07:49:28 +00003124static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003125EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003126{
Guido van Rossumad4db171998-06-13 13:56:28 +00003127#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003128 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003129#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003130#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003131 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003132#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 stdin_ready = 0;
3134 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003135#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003136 tfile = fileno(stdin);
3137 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003138#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003139 while (!errorInCmd && !stdin_ready) {
3140 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003141#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 if (_kbhit()) {
3143 stdin_ready = 1;
3144 break;
3145 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003146#endif
3147#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003148 Py_BEGIN_ALLOW_THREADS
3149 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3150 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003151
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003152 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003153
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003154 tcl_tstate = NULL;
3155 if(tcl_lock)PyThread_release_lock(tcl_lock);
3156 if (result == 0)
3157 Sleep(Tkinter_busywaitinterval);
3158 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003159#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003160 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003161#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003163 if (result < 0)
3164 break;
3165 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003166#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003167 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003168#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 if (errorInCmd) {
3170 errorInCmd = 0;
3171 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3172 excInCmd = valInCmd = trbInCmd = NULL;
3173 PyErr_Print();
3174 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003175#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003176 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003177#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003178 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003179}
Guido van Rossum18468821994-06-20 07:49:28 +00003180
Guido van Rossum00d93061998-05-28 23:06:38 +00003181#endif
3182
Guido van Rossum7bf15641998-05-22 18:28:17 +00003183static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003184EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003185{
Guido van Rossum00d93061998-05-28 23:06:38 +00003186#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003187 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003188#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003189 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003190#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003191 PyOS_InputHook = EventHook;
3192 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003193#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003194}
3195
3196static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003197DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003198{
Guido van Rossum00d93061998-05-28 23:06:38 +00003199#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003200 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3201 PyOS_InputHook = NULL;
3202 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003203#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003204}
3205
Barry Warsawfa701a81997-01-16 00:15:11 +00003206
Martin v. Löwis1a214512008-06-11 05:26:20 +00003207static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003208 PyModuleDef_HEAD_INIT,
3209 "_tkinter",
3210 NULL,
3211 -1,
3212 moduleMethods,
3213 NULL,
3214 NULL,
3215 NULL,
3216 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003217};
3218
Mark Hammond62b1ab12002-07-23 06:31:15 +00003219PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003220PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003221{
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003222 PyObject *m, *uexe, *cexe, *o;
Guido van Rossum18468821994-06-20 07:49:28 +00003223
Guido van Rossum00d93061998-05-28 23:06:38 +00003224#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003225 tcl_lock = PyThread_allocate_lock();
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003226 if (tcl_lock == NULL)
3227 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003228#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003230 m = PyModule_Create(&_tkintermodule);
3231 if (m == NULL)
3232 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003233
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003234 o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3235 if (o == NULL) {
Jesus Ceaef86d122012-07-19 21:18:07 +02003236 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003237 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003238 }
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003239 Py_INCREF(o);
3240 if (PyModule_AddObject(m, "TclError", o)) {
3241 Py_DECREF(o);
3242 Py_DECREF(m);
3243 return NULL;
3244 }
3245 Tkinter_TclError = o;
Guido van Rossum83551bf1997-09-13 00:44:23 +00003246
Andrew Svetlov11dc6c32012-10-14 16:54:35 +03003247 if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3248 Py_DECREF(m);
3249 return NULL;
3250 }
3251 if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3252 Py_DECREF(m);
3253 return NULL;
3254 }
3255 if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3256 Py_DECREF(m);
3257 return NULL;
3258 }
3259 if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3260 Py_DECREF(m);
3261 return NULL;
3262 }
3263 if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3264 Py_DECREF(m);
3265 return NULL;
3266 }
3267 if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3268 Py_DECREF(m);
3269 return NULL;
3270 }
3271 if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3272 Py_DECREF(m);
3273 return NULL;
3274 }
3275 if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3276 Py_DECREF(m);
3277 return NULL;
3278 }
3279 if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3280 Py_DECREF(m);
3281 return NULL;
3282 }
3283 if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3284 Py_DECREF(m);
3285 return NULL;
3286 }
3287 if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3288 Py_DECREF(m);
3289 return NULL;
3290 }
3291
3292 o = PyType_FromSpec(&Tkapp_Type_spec);
3293 if (o == NULL) {
3294 Py_DECREF(m);
3295 return NULL;
3296 }
3297 if (PyModule_AddObject(m, "TkappType", o)) {
3298 Py_DECREF(o);
3299 Py_DECREF(m);
3300 return NULL;
3301 }
3302 Tkapp_Type = o;
3303
3304 o = PyType_FromSpec(&Tktt_Type_spec);
3305 if (o == NULL) {
3306 Py_DECREF(m);
3307 return NULL;
3308 }
3309 if (PyModule_AddObject(m, "TkttType", o)) {
3310 Py_DECREF(o);
3311 Py_DECREF(m);
3312 return NULL;
3313 }
3314 Tktt_Type = o;
3315
3316 o = PyType_FromSpec(&PyTclObject_Type_spec);
3317 if (o == NULL) {
3318 Py_DECREF(m);
3319 return NULL;
3320 }
3321 if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3322 Py_DECREF(o);
3323 Py_DECREF(m);
3324 return NULL;
3325 }
3326 PyTclObject_Type = o;
Jack Jansencb852442001-12-09 23:15:56 +00003327
3328#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003329 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3330 * start waking up. Note that Tcl_FindExecutable will do this, this
3331 * code must be above it! The original warning from
3332 * tkMacOSXAppInit.c is copied below.
3333 *
3334 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3335 * Tcl interpreter for now. It probably should work to do this
3336 * in the other order, but for now it doesn't seem to.
3337 *
3338 */
3339 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003340#endif
3341
3342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003343 /* This helps the dynamic loader; in Unicode aware Tcl versions
3344 it also helps Tcl find its encodings. */
3345 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3346 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003347 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003348 if (cexe)
3349 Tcl_FindExecutable(PyBytes_AsString(cexe));
3350 Py_XDECREF(cexe);
3351 Py_DECREF(uexe);
3352 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003353
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003354 if (PyErr_Occurred()) {
3355 Py_DECREF(m);
3356 return NULL;
3357 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003358
Guido van Rossum43ff8681998-07-14 18:02:13 +00003359#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003360 /* This was not a good idea; through <Destroy> bindings,
3361 Tcl_Finalize() may invoke Python code but at that point the
3362 interpreter and thread state have already been destroyed! */
3363 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003364#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003365 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003366}