Branch data Line data Source code
1 : : /***********************************************************
2 : : Copyright (C) 1994 Steen Lumholt.
3 : :
4 : : All Rights Reserved
5 : :
6 : : ******************************************************************/
7 : :
8 : : /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
9 : :
10 : : /* TCL/TK VERSION INFO:
11 : :
12 : : Only Tcl/Tk 8.5.12 and later are supported. Older versions are not
13 : : supported. Use Python 3.10 or older if you cannot upgrade your
14 : : Tcl/Tk libraries.
15 : : */
16 : :
17 : : /* XXX Further speed-up ideas, involving Tcl 8.0 features:
18 : :
19 : : - 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 : :
22 : : */
23 : :
24 : : #define PY_SSIZE_T_CLEAN
25 : : #ifndef Py_BUILD_CORE_BUILTIN
26 : : # define Py_BUILD_CORE_MODULE 1
27 : : #endif
28 : :
29 : : #include "Python.h"
30 : : #include <ctype.h>
31 : : #ifdef MS_WINDOWS
32 : : # include "pycore_fileutils.h" // _Py_stat()
33 : : #endif
34 : :
35 : : #ifdef MS_WINDOWS
36 : : #include <windows.h>
37 : : #endif
38 : :
39 : : #define CHECK_SIZE(size, elemsize) \
40 : : ((size_t)(size) <= Py_MIN((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
41 : :
42 : : /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
43 : : it always; if Tcl is not threaded, the thread functions in
44 : : Tcl are empty. */
45 : : #define TCL_THREADS
46 : :
47 : : #ifdef TK_FRAMEWORK
48 : : #include <Tcl/tcl.h>
49 : : #include <Tk/tk.h>
50 : : #else
51 : : #include <tcl.h>
52 : : #include <tk.h>
53 : : #endif
54 : :
55 : : #include "tkinter.h"
56 : :
57 : : #if TK_HEX_VERSION < 0x0805020c
58 : : #error "Tk older than 8.5.12 not supported"
59 : : #endif
60 : :
61 : : #include <tclTomMath.h>
62 : :
63 : : #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
64 : : #define HAVE_CREATEFILEHANDLER
65 : : #endif
66 : :
67 : : #ifdef HAVE_CREATEFILEHANDLER
68 : :
69 : : /* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
70 : : with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
71 : : #ifndef TCL_UNIX_FD
72 : : # ifdef TCL_WIN_SOCKET
73 : : # define TCL_UNIX_FD (! TCL_WIN_SOCKET)
74 : : # else
75 : : # define TCL_UNIX_FD 1
76 : : # endif
77 : : #endif
78 : :
79 : : /* Tcl_CreateFileHandler() changed several times; these macros deal with the
80 : : messiness. In Tcl 8.0 and later, it is not available on Windows (and on
81 : : Unix, only because Jack added it back); when available on Windows, it only
82 : : applies to sockets. */
83 : :
84 : : #ifdef MS_WINDOWS
85 : : #define FHANDLETYPE TCL_WIN_SOCKET
86 : : #else
87 : : #define FHANDLETYPE TCL_UNIX_FD
88 : : #endif
89 : :
90 : : /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
91 : : which uses this to handle Tcl events while the user is typing commands. */
92 : :
93 : : #if FHANDLETYPE == TCL_UNIX_FD
94 : : #define WAIT_FOR_STDIN
95 : : #endif
96 : :
97 : : #endif /* HAVE_CREATEFILEHANDLER */
98 : :
99 : : /* Use OS native encoding for converting between Python strings and
100 : : Tcl objects.
101 : : On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
102 : : "surrogatepass" error handler for converting to/from Tcl Unicode objects.
103 : : On Linux use UTF-8 with the "surrogateescape" error handler for converting
104 : : to/from Tcl String objects. */
105 : : #ifdef MS_WINDOWS
106 : : #define USE_TCL_UNICODE 1
107 : : #else
108 : : #define USE_TCL_UNICODE 0
109 : : #endif
110 : :
111 : : #if PY_LITTLE_ENDIAN
112 : : #define NATIVE_BYTEORDER -1
113 : : #else
114 : : #define NATIVE_BYTEORDER 1
115 : : #endif
116 : :
117 : : #ifdef MS_WINDOWS
118 : : #include <conio.h>
119 : : #define WAIT_FOR_STDIN
120 : :
121 : : static PyObject *
122 : : _get_tcl_lib_path()
123 : : {
124 : : static PyObject *tcl_library_path = NULL;
125 : : static int already_checked = 0;
126 : :
127 : : if (already_checked == 0) {
128 : : PyObject *prefix;
129 : : struct stat stat_buf;
130 : : int stat_return_value;
131 : :
132 : : prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
133 : : if (prefix == NULL) {
134 : : return NULL;
135 : : }
136 : :
137 : : /* Check expected location for an installed Python first */
138 : : tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
139 : : if (tcl_library_path == NULL) {
140 : : return NULL;
141 : : }
142 : : tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
143 : : if (tcl_library_path == NULL) {
144 : : return NULL;
145 : : }
146 : : stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
147 : : if (stat_return_value == -2) {
148 : : return NULL;
149 : : }
150 : : if (stat_return_value == -1) {
151 : : /* install location doesn't exist, reset errno and see if
152 : : we're a repository build */
153 : : errno = 0;
154 : : #ifdef Py_TCLTK_DIR
155 : : tcl_library_path = PyUnicode_FromString(
156 : : Py_TCLTK_DIR "\\lib\\tcl" TCL_VERSION);
157 : : if (tcl_library_path == NULL) {
158 : : return NULL;
159 : : }
160 : : stat_return_value = _Py_stat(tcl_library_path, &stat_buf);
161 : : if (stat_return_value == -2) {
162 : : return NULL;
163 : : }
164 : : if (stat_return_value == -1) {
165 : : /* tcltkDir for a repository build doesn't exist either,
166 : : reset errno and leave Tcl to its own devices */
167 : : errno = 0;
168 : : tcl_library_path = NULL;
169 : : }
170 : : #else
171 : : tcl_library_path = NULL;
172 : : #endif
173 : : }
174 : : already_checked = 1;
175 : : }
176 : : return tcl_library_path;
177 : : }
178 : : #endif /* MS_WINDOWS */
179 : :
180 : : /* The threading situation is complicated. Tcl is not thread-safe, except
181 : : when configured with --enable-threads.
182 : :
183 : : So we need to use a lock around all uses of Tcl. Previously, the
184 : : Python interpreter lock was used for this. However, this causes
185 : : problems when other Python threads need to run while Tcl is blocked
186 : : waiting for events.
187 : :
188 : : To solve this problem, a separate lock for Tcl is introduced.
189 : : Holding it is incompatible with holding Python's interpreter lock.
190 : : The following four macros manipulate both locks together.
191 : :
192 : : ENTER_TCL and LEAVE_TCL are brackets, just like
193 : : Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS. They should be
194 : : used whenever a call into Tcl is made that could call an event
195 : : handler, or otherwise affect the state of a Tcl interpreter. These
196 : : assume that the surrounding code has the Python interpreter lock;
197 : : inside the brackets, the Python interpreter lock has been released
198 : : and the lock for Tcl has been acquired.
199 : :
200 : : Sometimes, it is necessary to have both the Python lock and the Tcl
201 : : lock. (For example, when transferring data from the Tcl
202 : : interpreter result to a Python string object.) This can be done by
203 : : using different macros to close the ENTER_TCL block: ENTER_OVERLAP
204 : : reacquires the Python lock (and restores the thread state) but
205 : : doesn't release the Tcl lock; LEAVE_OVERLAP_TCL releases the Tcl
206 : : lock.
207 : :
208 : : By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
209 : : handlers when the handler needs to use Python. Such event handlers
210 : : are entered while the lock for Tcl is held; the event handler
211 : : presumably needs to use Python. ENTER_PYTHON releases the lock for
212 : : Tcl and acquires the Python interpreter lock, restoring the
213 : : appropriate thread state, and LEAVE_PYTHON releases the Python
214 : : interpreter lock and re-acquires the lock for Tcl. It is okay for
215 : : ENTER_TCL/LEAVE_TCL pairs to be contained inside the code between
216 : : ENTER_PYTHON and LEAVE_PYTHON.
217 : :
218 : : These locks expand to several statements and brackets; they should
219 : : not be used in branches of if statements and the like.
220 : :
221 : : If Tcl is threaded, this approach won't work anymore. The Tcl
222 : : interpreter is only valid in the thread that created it, and all Tk
223 : : activity must happen in this thread, also. That means that the
224 : : mainloop must be invoked in the thread that created the
225 : : interpreter. Invoking commands from other threads is possible;
226 : : _tkinter will queue an event for the interpreter thread, which will
227 : : then execute the command and pass back the result. If the main
228 : : thread is not in the mainloop, and invoking commands causes an
229 : : exception; if the main loop is running but not processing events,
230 : : the command invocation will block.
231 : :
232 : : In addition, for a threaded Tcl, a single global tcl_tstate won't
233 : : be sufficient anymore, since multiple Tcl interpreters may
234 : : simultaneously dispatch in different threads. So we use the Tcl TLS
235 : : API.
236 : :
237 : : */
238 : :
239 : : static PyThread_type_lock tcl_lock = 0;
240 : :
241 : : #ifdef TCL_THREADS
242 : : static Tcl_ThreadDataKey state_key;
243 : : typedef PyThreadState *ThreadSpecificData;
244 : : #define tcl_tstate \
245 : : (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
246 : : #else
247 : : static PyThreadState *tcl_tstate = NULL;
248 : : #endif
249 : :
250 : : #define ENTER_TCL \
251 : : { PyThreadState *tstate = PyThreadState_Get(); \
252 : : Py_BEGIN_ALLOW_THREADS \
253 : : if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \
254 : : tcl_tstate = tstate;
255 : :
256 : : #define LEAVE_TCL \
257 : : tcl_tstate = NULL; \
258 : : if(tcl_lock)PyThread_release_lock(tcl_lock); \
259 : : Py_END_ALLOW_THREADS}
260 : :
261 : : #define ENTER_OVERLAP \
262 : : Py_END_ALLOW_THREADS
263 : :
264 : : #define LEAVE_OVERLAP_TCL \
265 : : tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
266 : :
267 : : #define ENTER_PYTHON \
268 : : { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
269 : : if(tcl_lock) \
270 : : PyThread_release_lock(tcl_lock); \
271 : : PyEval_RestoreThread((tstate)); }
272 : :
273 : : #define LEAVE_PYTHON \
274 : : { PyThreadState *tstate = PyEval_SaveThread(); \
275 : : if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); \
276 : : tcl_tstate = tstate; }
277 : :
278 : : #define CHECK_TCL_APPARTMENT \
279 : : if (((TkappObject *)self)->threaded && \
280 : : ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
281 : : PyErr_SetString(PyExc_RuntimeError, \
282 : : "Calling Tcl from different apartment"); \
283 : : return 0; \
284 : : }
285 : :
286 : : #ifndef FREECAST
287 : : #define FREECAST (char *)
288 : : #endif
289 : :
290 : : /**** Tkapp Object Declaration ****/
291 : :
292 : : static PyObject *Tkapp_Type;
293 : :
294 : : typedef struct {
295 : : PyObject_HEAD
296 : : Tcl_Interp *interp;
297 : : int wantobjects;
298 : : int threaded; /* True if tcl_platform[threaded] */
299 : : Tcl_ThreadId thread_id;
300 : : int dispatching;
301 : : /* We cannot include tclInt.h, as this is internal.
302 : : So we cache interesting types here. */
303 : : const Tcl_ObjType *OldBooleanType;
304 : : const Tcl_ObjType *BooleanType;
305 : : const Tcl_ObjType *ByteArrayType;
306 : : const Tcl_ObjType *DoubleType;
307 : : const Tcl_ObjType *IntType;
308 : : const Tcl_ObjType *WideIntType;
309 : : const Tcl_ObjType *BignumType;
310 : : const Tcl_ObjType *ListType;
311 : : const Tcl_ObjType *ProcBodyType;
312 : : const Tcl_ObjType *StringType;
313 : : } TkappObject;
314 : :
315 : : #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
316 : :
317 : :
318 : : /**** Error Handling ****/
319 : :
320 : : static PyObject *Tkinter_TclError;
321 : : static int quitMainLoop = 0;
322 : : static int errorInCmd = 0;
323 : : static PyObject *excInCmd;
324 : : static PyObject *valInCmd;
325 : : static PyObject *trbInCmd;
326 : :
327 : : #ifdef TKINTER_PROTECT_LOADTK
328 : : static int tk_load_failed = 0;
329 : : #endif
330 : :
331 : :
332 : : static PyObject *Tkapp_UnicodeResult(TkappObject *);
333 : :
334 : : static PyObject *
335 : 21 : Tkinter_Error(TkappObject *self)
336 : : {
337 : 21 : PyObject *res = Tkapp_UnicodeResult(self);
338 [ + - ]: 21 : if (res != NULL) {
339 : 21 : PyErr_SetObject(Tkinter_TclError, res);
340 : 21 : Py_DECREF(res);
341 : : }
342 : 21 : return NULL;
343 : : }
344 : :
345 : :
346 : :
347 : : /**** Utils ****/
348 : :
349 : : static int Tkinter_busywaitinterval = 20;
350 : :
351 : : #ifndef MS_WINDOWS
352 : :
353 : : /* Millisecond sleep() for Unix platforms. */
354 : :
355 : : static void
356 : 0 : Sleep(int milli)
357 : : {
358 : : /* XXX Too bad if you don't have select(). */
359 : : struct timeval t;
360 : 0 : t.tv_sec = milli/1000;
361 : 0 : t.tv_usec = (milli%1000) * 1000;
362 : 0 : select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
363 : 0 : }
364 : : #endif /* MS_WINDOWS */
365 : :
366 : : /* Wait up to 1s for the mainloop to come up. */
367 : :
368 : : static int
369 : 0 : WaitForMainloop(TkappObject* self)
370 : : {
371 : : int i;
372 [ # # ]: 0 : for (i = 0; i < 10; i++) {
373 [ # # ]: 0 : if (self->dispatching)
374 : 0 : return 1;
375 : 0 : Py_BEGIN_ALLOW_THREADS
376 : 0 : Sleep(100);
377 : 0 : Py_END_ALLOW_THREADS
378 : : }
379 [ # # ]: 0 : if (self->dispatching)
380 : 0 : return 1;
381 : 0 : PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
382 : 0 : return 0;
383 : : }
384 : :
385 : :
386 : :
387 : : #define ARGSZ 64
388 : :
389 : :
390 : :
391 : : static PyObject *
392 : 473 : unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
393 : : {
394 : 473 : PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
395 [ + + - + ]: 473 : if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
396 : 458 : return r;
397 : : }
398 : :
399 : 15 : char *buf = NULL;
400 : 15 : PyErr_Clear();
401 : : /* Tcl encodes null character as \xc0\x80.
402 : : https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 */
403 [ + + ]: 15 : if (memchr(s, '\xc0', size)) {
404 : : char *q;
405 : 8 : const char *e = s + size;
406 : 8 : q = buf = (char *)PyMem_Malloc(size);
407 [ - + ]: 8 : if (buf == NULL) {
408 : : PyErr_NoMemory();
409 : 0 : return NULL;
410 : : }
411 [ + + ]: 36 : while (s != e) {
412 [ + + + + : 28 : if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
+ - ]
413 : 8 : *q++ = '\0';
414 : 8 : s += 2;
415 : : }
416 : : else
417 : 20 : *q++ = *s++;
418 : : }
419 : 8 : s = buf;
420 : 8 : size = q - s;
421 : : }
422 : 15 : r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
423 [ + + ]: 15 : if (buf != NULL) {
424 : 8 : PyMem_Free(buf);
425 : : }
426 [ + - + + ]: 15 : if (r == NULL || PyUnicode_KIND(r) == PyUnicode_1BYTE_KIND) {
427 : 8 : return r;
428 : : }
429 : :
430 : : /* In CESU-8 non-BMP characters are represented as a surrogate pair,
431 : : like in UTF-16, and then each surrogate code point is encoded in UTF-8.
432 : : https://en.wikipedia.org/wiki/CESU-8 */
433 : 7 : Py_ssize_t len = PyUnicode_GET_LENGTH(r);
434 : : Py_ssize_t i, j;
435 : : /* All encoded surrogate characters start with \xED. */
436 : 7 : i = PyUnicode_FindChar(r, 0xdcED, 0, len, 1);
437 [ - + ]: 7 : if (i == -2) {
438 : 0 : Py_DECREF(r);
439 : 0 : return NULL;
440 : : }
441 [ - + ]: 7 : if (i == -1) {
442 : 0 : return r;
443 : : }
444 : 7 : Py_UCS4 *u = PyUnicode_AsUCS4Copy(r);
445 : 7 : Py_DECREF(r);
446 [ - + ]: 7 : if (u == NULL) {
447 : 0 : return NULL;
448 : : }
449 : : Py_UCS4 ch;
450 [ + + ]: 20 : for (j = i; i < len; i++, u[j++] = ch) {
451 : : Py_UCS4 ch1, ch2, ch3, high, low;
452 : : /* Low surrogates U+D800 - U+DBFF are encoded as
453 : : \xED\xA0\x80 - \xED\xAF\xBF. */
454 : 13 : ch1 = ch = u[i];
455 [ + + ]: 13 : if (ch1 != 0xdcED) continue;
456 : 7 : ch2 = u[i + 1];
457 [ + - - + ]: 7 : if (!(0xdcA0 <= ch2 && ch2 <= 0xdcAF)) continue;
458 : 7 : ch3 = u[i + 2];
459 [ + - - + ]: 7 : if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
460 : 7 : high = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
461 : : assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
462 : : /* High surrogates U+DC00 - U+DFFF are encoded as
463 : : \xED\xB0\x80 - \xED\xBF\xBF. */
464 : 7 : ch1 = u[i + 3];
465 [ - + ]: 7 : if (ch1 != 0xdcED) continue;
466 : 7 : ch2 = u[i + 4];
467 [ + - - + ]: 7 : if (!(0xdcB0 <= ch2 && ch2 <= 0xdcBF)) continue;
468 : 7 : ch3 = u[i + 5];
469 [ + - - + ]: 7 : if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
470 : 7 : low = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
471 : : assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
472 : 7 : ch = Py_UNICODE_JOIN_SURROGATES(high, low);
473 : 7 : i += 5;
474 : : }
475 : 7 : r = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, u, j);
476 : 7 : PyMem_Free(u);
477 : 7 : return r;
478 : : }
479 : :
480 : : static PyObject *
481 : 44 : unicodeFromTclString(const char *s)
482 : : {
483 : 44 : return unicodeFromTclStringAndSize(s, strlen(s));
484 : : }
485 : :
486 : : static PyObject *
487 : 429 : unicodeFromTclObj(Tcl_Obj *value)
488 : : {
489 : : int len;
490 : : #if USE_TCL_UNICODE
491 : : int byteorder = NATIVE_BYTEORDER;
492 : : const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
493 : : if (sizeof(Tcl_UniChar) == 2)
494 : : return PyUnicode_DecodeUTF16((const char *)u, len * 2,
495 : : "surrogatepass", &byteorder);
496 : : else if (sizeof(Tcl_UniChar) == 4)
497 : : return PyUnicode_DecodeUTF32((const char *)u, len * 4,
498 : : "surrogatepass", &byteorder);
499 : : else
500 : : Py_UNREACHABLE();
501 : : #else
502 : 429 : const char *s = Tcl_GetStringFromObj(value, &len);
503 : 429 : return unicodeFromTclStringAndSize(s, len);
504 : : #endif
505 : : }
506 : :
507 : : /*[clinic input]
508 : : module _tkinter
509 : : class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec"
510 : : class _tkinter.Tcl_Obj "PyTclObject *" "&PyTclObject_Type_spec"
511 : : class _tkinter.tktimertoken "TkttObject *" "&Tktt_Type_spec"
512 : : [clinic start generated code]*/
513 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b1ebf15c162ee229]*/
514 : :
515 : : /**** Tkapp Object ****/
516 : :
517 : : #ifndef WITH_APPINIT
518 : : int
519 : : Tcl_AppInit(Tcl_Interp *interp)
520 : : {
521 : : const char * _tkinter_skip_tk_init;
522 : :
523 : : if (Tcl_Init(interp) == TCL_ERROR) {
524 : : PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
525 : : return TCL_ERROR;
526 : : }
527 : :
528 : : _tkinter_skip_tk_init = Tcl_GetVar(interp,
529 : : "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
530 : : if (_tkinter_skip_tk_init != NULL &&
531 : : strcmp(_tkinter_skip_tk_init, "1") == 0) {
532 : : return TCL_OK;
533 : : }
534 : :
535 : : #ifdef TKINTER_PROTECT_LOADTK
536 : : if (tk_load_failed) {
537 : : PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
538 : : return TCL_ERROR;
539 : : }
540 : : #endif
541 : :
542 : : if (Tk_Init(interp) == TCL_ERROR) {
543 : : #ifdef TKINTER_PROTECT_LOADTK
544 : : tk_load_failed = 1;
545 : : #endif
546 : : PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
547 : : return TCL_ERROR;
548 : : }
549 : :
550 : : return TCL_OK;
551 : : }
552 : : #endif /* !WITH_APPINIT */
553 : :
554 : :
555 : :
556 : :
557 : : /* Initialize the Tk application; see the `main' function in
558 : : * `tkMain.c'.
559 : : */
560 : :
561 : : static void EnableEventHook(void); /* Forward */
562 : : static void DisableEventHook(void); /* Forward */
563 : :
564 : : static TkappObject *
565 : 42 : Tkapp_New(const char *screenName, const char *className,
566 : : int interactive, int wantobjects, int wantTk, int sync,
567 : : const char *use)
568 : : {
569 : : TkappObject *v;
570 : : char *argv0;
571 : :
572 : 42 : v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type);
573 [ - + ]: 42 : if (v == NULL)
574 : 0 : return NULL;
575 : :
576 : 42 : v->interp = Tcl_CreateInterp();
577 : 42 : v->wantobjects = wantobjects;
578 : 42 : v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
579 : 42 : TCL_GLOBAL_ONLY) != NULL;
580 : 42 : v->thread_id = Tcl_GetCurrentThread();
581 : 42 : v->dispatching = 0;
582 : :
583 : : #ifndef TCL_THREADS
584 : : if (v->threaded) {
585 : : PyErr_SetString(PyExc_RuntimeError,
586 : : "Tcl is threaded but _tkinter is not");
587 : : Py_DECREF(v);
588 : : return 0;
589 : : }
590 : : #endif
591 [ + - + + ]: 42 : if (v->threaded && tcl_lock) {
592 : : /* If Tcl is threaded, we don't need the lock. */
593 : 2 : PyThread_free_lock(tcl_lock);
594 : 2 : tcl_lock = NULL;
595 : : }
596 : :
597 : 42 : v->OldBooleanType = Tcl_GetObjType("boolean");
598 : 42 : v->BooleanType = Tcl_GetObjType("booleanString");
599 : 42 : v->ByteArrayType = Tcl_GetObjType("bytearray");
600 : 42 : v->DoubleType = Tcl_GetObjType("double");
601 : 42 : v->IntType = Tcl_GetObjType("int");
602 : 42 : v->WideIntType = Tcl_GetObjType("wideInt");
603 : 42 : v->BignumType = Tcl_GetObjType("bignum");
604 : 42 : v->ListType = Tcl_GetObjType("list");
605 : 42 : v->ProcBodyType = Tcl_GetObjType("procbody");
606 : 42 : v->StringType = Tcl_GetObjType("string");
607 : :
608 : : /* Delete the 'exit' command, which can screw things up */
609 : 42 : Tcl_DeleteCommand(v->interp, "exit");
610 : :
611 [ - + ]: 42 : if (screenName != NULL)
612 : 0 : Tcl_SetVar2(v->interp, "env", "DISPLAY",
613 : : screenName, TCL_GLOBAL_ONLY);
614 : :
615 [ - + ]: 42 : if (interactive)
616 : 0 : Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
617 : : else
618 : 42 : Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
619 : :
620 : : /* This is used to get the application class for Tk 4.1 and up */
621 : 42 : argv0 = (char*)PyMem_Malloc(strlen(className) + 1);
622 [ - + ]: 42 : if (!argv0) {
623 : : PyErr_NoMemory();
624 : 0 : Py_DECREF(v);
625 : 0 : return NULL;
626 : : }
627 : :
628 : 42 : strcpy(argv0, className);
629 [ + - ]: 42 : if (Py_ISUPPER(argv0[0]))
630 : 42 : argv0[0] = Py_TOLOWER(argv0[0]);
631 : 42 : Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
632 : 42 : PyMem_Free(argv0);
633 : :
634 [ + - ]: 42 : if (! wantTk) {
635 : 42 : Tcl_SetVar(v->interp,
636 : : "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
637 : : }
638 : : #ifdef TKINTER_PROTECT_LOADTK
639 : : else if (tk_load_failed) {
640 : : Tcl_SetVar(v->interp,
641 : : "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
642 : : }
643 : : #endif
644 : :
645 : : /* some initial arguments need to be in argv */
646 [ + - - + ]: 42 : if (sync || use) {
647 : : char *args;
648 : 0 : Py_ssize_t len = 0;
649 : :
650 [ # # ]: 0 : if (sync)
651 : 0 : len += sizeof "-sync";
652 [ # # ]: 0 : if (use)
653 : 0 : len += strlen(use) + sizeof "-use "; /* never overflows */
654 : :
655 : 0 : args = (char*)PyMem_Malloc(len);
656 [ # # ]: 0 : if (!args) {
657 : : PyErr_NoMemory();
658 : 0 : Py_DECREF(v);
659 : 0 : return NULL;
660 : : }
661 : :
662 : 0 : args[0] = '\0';
663 [ # # ]: 0 : if (sync)
664 : 0 : strcat(args, "-sync");
665 [ # # ]: 0 : if (use) {
666 [ # # ]: 0 : if (sync)
667 : 0 : strcat(args, " ");
668 : 0 : strcat(args, "-use ");
669 : 0 : strcat(args, use);
670 : : }
671 : :
672 : 0 : Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
673 : 0 : PyMem_Free(args);
674 : : }
675 : :
676 : : #ifdef MS_WINDOWS
677 : : {
678 : : PyObject *str_path;
679 : : PyObject *utf8_path;
680 : : DWORD ret;
681 : :
682 : : ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
683 : : if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
684 : : str_path = _get_tcl_lib_path();
685 : : if (str_path == NULL && PyErr_Occurred()) {
686 : : return NULL;
687 : : }
688 : : if (str_path != NULL) {
689 : : utf8_path = PyUnicode_AsUTF8String(str_path);
690 : : if (utf8_path == NULL) {
691 : : return NULL;
692 : : }
693 : : Tcl_SetVar(v->interp,
694 : : "tcl_library",
695 : : PyBytes_AS_STRING(utf8_path),
696 : : TCL_GLOBAL_ONLY);
697 : : Py_DECREF(utf8_path);
698 : : }
699 : : }
700 : : }
701 : : #endif
702 : :
703 [ - + ]: 42 : if (Tcl_AppInit(v->interp) != TCL_OK) {
704 : 0 : PyObject *result = Tkinter_Error(v);
705 : : #ifdef TKINTER_PROTECT_LOADTK
706 : : if (wantTk) {
707 : : const char *_tkinter_tk_failed;
708 : : _tkinter_tk_failed = Tcl_GetVar(v->interp,
709 : : "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
710 : :
711 : : if ( _tkinter_tk_failed != NULL &&
712 : : strcmp(_tkinter_tk_failed, "1") == 0) {
713 : : tk_load_failed = 1;
714 : : }
715 : : }
716 : : #endif
717 : 0 : Py_DECREF((PyObject *)v);
718 : 0 : return (TkappObject *)result;
719 : : }
720 : :
721 : 42 : EnableEventHook();
722 : :
723 : 42 : return v;
724 : : }
725 : :
726 : :
727 : : static void
728 : 0 : Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
729 : : Tcl_Condition *cond, Tcl_Mutex *mutex)
730 : : {
731 : 0 : Py_BEGIN_ALLOW_THREADS;
732 : 0 : Tcl_MutexLock(mutex);
733 : 0 : Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
734 : 0 : Tcl_ThreadAlert(self->thread_id);
735 : 0 : Tcl_ConditionWait(cond, mutex, NULL);
736 : 0 : Tcl_MutexUnlock(mutex);
737 : 0 : Py_END_ALLOW_THREADS
738 : 0 : }
739 : :
740 : :
741 : : /** Tcl Eval **/
742 : :
743 : : typedef struct {
744 : : PyObject_HEAD
745 : : Tcl_Obj *value;
746 : : PyObject *string; /* This cannot cause cycles. */
747 : : } PyTclObject;
748 : :
749 : : static PyObject *PyTclObject_Type;
750 : : #define PyTclObject_Check(v) Py_IS_TYPE(v, (PyTypeObject *) PyTclObject_Type)
751 : :
752 : : static PyObject *
753 : 2 : newPyTclObject(Tcl_Obj *arg)
754 : : {
755 : : PyTclObject *self;
756 : 2 : self = PyObject_New(PyTclObject, (PyTypeObject *) PyTclObject_Type);
757 [ - + ]: 2 : if (self == NULL)
758 : 0 : return NULL;
759 : 2 : Tcl_IncrRefCount(arg);
760 : 2 : self->value = arg;
761 : 2 : self->string = NULL;
762 : 2 : return (PyObject*)self;
763 : : }
764 : :
765 : : static void
766 : 2 : PyTclObject_dealloc(PyTclObject *self)
767 : : {
768 : 2 : PyObject *tp = (PyObject *) Py_TYPE(self);
769 [ + + ]: 2 : Tcl_DecrRefCount(self->value);
770 : 2 : Py_XDECREF(self->string);
771 : 2 : PyObject_Free(self);
772 : 2 : Py_DECREF(tp);
773 : 2 : }
774 : :
775 : : /* Like _str, but create Unicode if necessary. */
776 : : PyDoc_STRVAR(PyTclObject_string__doc__,
777 : : "the string representation of this object, either as str or bytes");
778 : :
779 : : static PyObject *
780 : 0 : PyTclObject_string(PyTclObject *self, void *ignored)
781 : : {
782 [ # # ]: 0 : if (!self->string) {
783 : 0 : self->string = unicodeFromTclObj(self->value);
784 [ # # ]: 0 : if (!self->string)
785 : 0 : return NULL;
786 : : }
787 : 0 : Py_INCREF(self->string);
788 : 0 : return self->string;
789 : : }
790 : :
791 : : static PyObject *
792 : 1 : PyTclObject_str(PyTclObject *self)
793 : : {
794 [ - + ]: 1 : if (self->string) {
795 : 0 : Py_INCREF(self->string);
796 : 0 : return self->string;
797 : : }
798 : : /* XXX Could cache result if it is non-ASCII. */
799 : 1 : return unicodeFromTclObj(self->value);
800 : : }
801 : :
802 : : static PyObject *
803 : 1 : PyTclObject_repr(PyTclObject *self)
804 : : {
805 : 1 : PyObject *repr, *str = PyTclObject_str(self);
806 [ - + ]: 1 : if (str == NULL)
807 : 0 : return NULL;
808 : 1 : repr = PyUnicode_FromFormat("<%s object: %R>",
809 : 1 : self->value->typePtr->name, str);
810 : 1 : Py_DECREF(str);
811 : 1 : return repr;
812 : : }
813 : :
814 : : static PyObject *
815 : 0 : PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
816 : : {
817 : : int result;
818 : :
819 : : /* neither argument should be NULL, unless something's gone wrong */
820 [ # # # # ]: 0 : if (self == NULL || other == NULL) {
821 : 0 : PyErr_BadInternalCall();
822 : 0 : return NULL;
823 : : }
824 : :
825 : : /* both arguments should be instances of PyTclObject */
826 [ # # # # ]: 0 : if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
827 : 0 : Py_RETURN_NOTIMPLEMENTED;
828 : : }
829 : :
830 [ # # ]: 0 : if (self == other)
831 : : /* fast path when self and other are identical */
832 : 0 : result = 0;
833 : : else
834 : 0 : result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
835 : 0 : Tcl_GetString(((PyTclObject *)other)->value));
836 [ # # # # : 0 : Py_RETURN_RICHCOMPARE(result, 0, op);
# # # # #
# # # # #
# # # #
# ]
837 : : }
838 : :
839 : : PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
840 : :
841 : : static PyObject*
842 : 0 : get_typename(PyTclObject* obj, void* ignored)
843 : : {
844 : 0 : return unicodeFromTclString(obj->value->typePtr->name);
845 : : }
846 : :
847 : :
848 : : static PyGetSetDef PyTclObject_getsetlist[] = {
849 : : {"typename", (getter)get_typename, NULL, get_typename__doc__},
850 : : {"string", (getter)PyTclObject_string, NULL,
851 : : PyTclObject_string__doc__},
852 : : {0},
853 : : };
854 : :
855 : : static PyType_Slot PyTclObject_Type_slots[] = {
856 : : {Py_tp_dealloc, (destructor)PyTclObject_dealloc},
857 : : {Py_tp_repr, (reprfunc)PyTclObject_repr},
858 : : {Py_tp_str, (reprfunc)PyTclObject_str},
859 : : {Py_tp_getattro, PyObject_GenericGetAttr},
860 : : {Py_tp_richcompare, PyTclObject_richcompare},
861 : : {Py_tp_getset, PyTclObject_getsetlist},
862 : : {0, 0}
863 : : };
864 : :
865 : : static PyType_Spec PyTclObject_Type_spec = {
866 : : "_tkinter.Tcl_Obj",
867 : : sizeof(PyTclObject),
868 : : 0,
869 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
870 : : PyTclObject_Type_slots,
871 : : };
872 : :
873 : :
874 : : #if SIZE_MAX > INT_MAX
875 : : #define CHECK_STRING_LENGTH(s) do { \
876 : : if (s != NULL && strlen(s) >= INT_MAX) { \
877 : : PyErr_SetString(PyExc_OverflowError, "string is too long"); \
878 : : return NULL; \
879 : : } } while(0)
880 : : #else
881 : : #define CHECK_STRING_LENGTH(s)
882 : : #endif
883 : :
884 : : static Tcl_Obj*
885 : 8 : asBignumObj(PyObject *value)
886 : : {
887 : : Tcl_Obj *result;
888 : : int neg;
889 : : PyObject *hexstr;
890 : : const char *hexchars;
891 : : mp_int bigValue;
892 : :
893 : 8 : neg = Py_SIZE(value) < 0;
894 : 8 : hexstr = _PyLong_Format(value, 16);
895 [ - + ]: 8 : if (hexstr == NULL)
896 : 0 : return NULL;
897 : 8 : hexchars = PyUnicode_AsUTF8(hexstr);
898 [ - + ]: 8 : if (hexchars == NULL) {
899 : 0 : Py_DECREF(hexstr);
900 : 0 : return NULL;
901 : : }
902 : 8 : hexchars += neg + 2; /* skip sign and "0x" */
903 : 8 : mp_init(&bigValue);
904 [ - + ]: 8 : if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
905 : 0 : mp_clear(&bigValue);
906 : 0 : Py_DECREF(hexstr);
907 : : PyErr_NoMemory();
908 : 0 : return NULL;
909 : : }
910 : 8 : Py_DECREF(hexstr);
911 : 8 : bigValue.sign = neg ? MP_NEG : MP_ZPOS;
912 : 8 : result = Tcl_NewBignumObj(&bigValue);
913 : 8 : mp_clear(&bigValue);
914 [ - + ]: 8 : if (result == NULL) {
915 : : PyErr_NoMemory();
916 : 0 : return NULL;
917 : : }
918 : 8 : return result;
919 : : }
920 : :
921 : : static Tcl_Obj*
922 : 1123 : AsObj(PyObject *value)
923 : : {
924 : : Tcl_Obj *result;
925 : :
926 [ + + ]: 1123 : if (PyBytes_Check(value)) {
927 [ - + ]: 11 : if (PyBytes_GET_SIZE(value) >= INT_MAX) {
928 : 0 : PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
929 : 0 : return NULL;
930 : : }
931 : 11 : return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value),
932 : 11 : (int)PyBytes_GET_SIZE(value));
933 : : }
934 : :
935 [ + + ]: 1112 : if (PyBool_Check(value))
936 : 4 : return Tcl_NewBooleanObj(PyObject_IsTrue(value));
937 : :
938 [ + + ]: 1108 : if (PyLong_CheckExact(value)) {
939 : : int overflow;
940 : : long longValue;
941 : : #ifdef TCL_WIDE_INT_TYPE
942 : : Tcl_WideInt wideValue;
943 : : #endif
944 : 294 : longValue = PyLong_AsLongAndOverflow(value, &overflow);
945 [ + + ]: 294 : if (!overflow) {
946 : 286 : return Tcl_NewLongObj(longValue);
947 : : }
948 : : /* If there is an overflow in the long conversion,
949 : : fall through to wideInt handling. */
950 : : #ifdef TCL_WIDE_INT_TYPE
951 [ - + ]: 8 : if (_PyLong_AsByteArray((PyLongObject *)value,
952 : : (unsigned char *)(void *)&wideValue,
953 : : sizeof(wideValue),
954 : : PY_LITTLE_ENDIAN,
955 : : /* signed */ 1) == 0) {
956 : 0 : return Tcl_NewWideIntObj(wideValue);
957 : : }
958 : 8 : PyErr_Clear();
959 : : #endif
960 : : /* If there is an overflow in the wideInt conversion,
961 : : fall through to bignum handling. */
962 : 8 : return asBignumObj(value);
963 : : /* If there is no wideInt or bignum support,
964 : : fall through to default object handling. */
965 : : }
966 : :
967 [ + + ]: 814 : if (PyFloat_Check(value))
968 : 24 : return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
969 : :
970 [ + + + + ]: 790 : if (PyTuple_Check(value) || PyList_Check(value)) {
971 : : Tcl_Obj **argv;
972 : : Py_ssize_t size, i;
973 : :
974 [ + + ]: 19 : size = PySequence_Fast_GET_SIZE(value);
975 [ + + ]: 19 : if (size == 0)
976 : 5 : return Tcl_NewListObj(0, NULL);
977 [ - + ]: 14 : if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
978 [ # # ]: 0 : PyErr_SetString(PyExc_OverflowError,
979 : 0 : PyTuple_Check(value) ? "tuple is too long" :
980 : : "list is too long");
981 : 0 : return NULL;
982 : : }
983 : 14 : argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *));
984 [ - + ]: 14 : if (!argv) {
985 : : PyErr_NoMemory();
986 : 0 : return NULL;
987 : : }
988 [ + + ]: 46 : for (i = 0; i < size; i++)
989 [ + + ]: 32 : argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i));
990 : 14 : result = Tcl_NewListObj((int)size, argv);
991 : 14 : PyMem_Free(argv);
992 : 14 : return result;
993 : : }
994 : :
995 [ + - ]: 771 : if (PyUnicode_Check(value)) {
996 [ - + ]: 771 : if (PyUnicode_READY(value) == -1)
997 : 0 : return NULL;
998 : :
999 : 771 : Py_ssize_t size = PyUnicode_GET_LENGTH(value);
1000 [ + + ]: 771 : if (size == 0) {
1001 : 4 : return Tcl_NewStringObj("", 0);
1002 : : }
1003 [ - + ]: 767 : if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1004 : 0 : PyErr_SetString(PyExc_OverflowError, "string is too long");
1005 : 0 : return NULL;
1006 : : }
1007 [ + + ]: 767 : if (PyUnicode_IS_ASCII(value)) {
1008 : 741 : return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
1009 : : (int)size);
1010 : : }
1011 : :
1012 : : PyObject *encoded;
1013 : : #if USE_TCL_UNICODE
1014 : : if (sizeof(Tcl_UniChar) == 2)
1015 : : encoded = _PyUnicode_EncodeUTF16(value,
1016 : : "surrogatepass", NATIVE_BYTEORDER);
1017 : : else if (sizeof(Tcl_UniChar) == 4)
1018 : : encoded = _PyUnicode_EncodeUTF32(value,
1019 : : "surrogatepass", NATIVE_BYTEORDER);
1020 : : else
1021 : : Py_UNREACHABLE();
1022 : : #else
1023 : 26 : encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
1024 : : #endif
1025 [ - + ]: 26 : if (!encoded) {
1026 : 0 : return NULL;
1027 : : }
1028 : 26 : size = PyBytes_GET_SIZE(encoded);
1029 [ - + ]: 26 : if (size > INT_MAX) {
1030 : 0 : Py_DECREF(encoded);
1031 : 0 : PyErr_SetString(PyExc_OverflowError, "string is too long");
1032 : 0 : return NULL;
1033 : : }
1034 : : #if USE_TCL_UNICODE
1035 : : result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
1036 : : (int)(size / sizeof(Tcl_UniChar)));
1037 : : #else
1038 : 26 : result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
1039 : : #endif
1040 : 26 : Py_DECREF(encoded);
1041 : 26 : return result;
1042 : : }
1043 : :
1044 [ # # ]: 0 : if (PyTclObject_Check(value)) {
1045 : 0 : return ((PyTclObject*)value)->value;
1046 : : }
1047 : :
1048 : : {
1049 : 0 : PyObject *v = PyObject_Str(value);
1050 [ # # ]: 0 : if (!v)
1051 : 0 : return 0;
1052 : 0 : result = AsObj(v);
1053 : 0 : Py_DECREF(v);
1054 : 0 : return result;
1055 : : }
1056 : : }
1057 : :
1058 : : static PyObject *
1059 : 6 : fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
1060 : : {
1061 : : int boolValue;
1062 [ - + ]: 6 : if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1063 : 0 : return Tkinter_Error(tkapp);
1064 : 6 : return PyBool_FromLong(boolValue);
1065 : : }
1066 : :
1067 : : static PyObject*
1068 : 0 : fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
1069 : : {
1070 : : Tcl_WideInt wideValue;
1071 [ # # ]: 0 : if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1072 : : if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1073 : 0 : return PyLong_FromLongLong(wideValue);
1074 : : return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1075 : : sizeof(wideValue),
1076 : : PY_LITTLE_ENDIAN,
1077 : : /* signed */ 1);
1078 : : }
1079 : 0 : return NULL;
1080 : : }
1081 : :
1082 : : static PyObject*
1083 : 61 : fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
1084 : : {
1085 : : mp_int bigValue;
1086 : : unsigned long numBytes;
1087 : : unsigned char *bytes;
1088 : : PyObject *res;
1089 : :
1090 [ + + ]: 61 : if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1091 : 1 : return Tkinter_Error(tkapp);
1092 : 60 : numBytes = mp_unsigned_bin_size(&bigValue);
1093 : 60 : bytes = PyMem_Malloc(numBytes);
1094 [ - + ]: 60 : if (bytes == NULL) {
1095 : 0 : mp_clear(&bigValue);
1096 : : return PyErr_NoMemory();
1097 : : }
1098 [ - + ]: 60 : if (mp_to_unsigned_bin_n(&bigValue, bytes,
1099 : : &numBytes) != MP_OKAY) {
1100 : 0 : mp_clear(&bigValue);
1101 : 0 : PyMem_Free(bytes);
1102 : : return PyErr_NoMemory();
1103 : : }
1104 : 60 : res = _PyLong_FromByteArray(bytes, numBytes,
1105 : : /* big-endian */ 0,
1106 : : /* unsigned */ 0);
1107 : 60 : PyMem_Free(bytes);
1108 [ + - + + ]: 60 : if (res != NULL && bigValue.sign == MP_NEG) {
1109 : 28 : PyObject *res2 = PyNumber_Negative(res);
1110 : 28 : Py_DECREF(res);
1111 : 28 : res = res2;
1112 : : }
1113 : 60 : mp_clear(&bigValue);
1114 : 60 : return res;
1115 : : }
1116 : :
1117 : : static PyObject*
1118 : 401 : FromObj(TkappObject *tkapp, Tcl_Obj *value)
1119 : : {
1120 : 401 : PyObject *result = NULL;
1121 : 401 : Tcl_Interp *interp = Tkapp_Interp(tkapp);
1122 : :
1123 [ + + ]: 401 : if (value->typePtr == NULL) {
1124 : 318 : return unicodeFromTclObj(value);
1125 : : }
1126 : :
1127 [ + + ]: 83 : if (value->typePtr == tkapp->BooleanType ||
1128 [ - + ]: 78 : value->typePtr == tkapp->OldBooleanType) {
1129 : 5 : return fromBoolean(tkapp, value);
1130 : : }
1131 : :
1132 [ + + ]: 78 : if (value->typePtr == tkapp->ByteArrayType) {
1133 : : int size;
1134 : 4 : char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1135 : 4 : return PyBytes_FromStringAndSize(data, size);
1136 : : }
1137 : :
1138 [ + + ]: 74 : if (value->typePtr == tkapp->DoubleType) {
1139 : 14 : return PyFloat_FromDouble(value->internalRep.doubleValue);
1140 : : }
1141 : :
1142 [ + + ]: 60 : if (value->typePtr == tkapp->IntType) {
1143 : : long longValue;
1144 [ + - ]: 39 : if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1145 : 39 : return PyLong_FromLong(longValue);
1146 : : /* If there is an error in the long conversion,
1147 : : fall through to wideInt handling. */
1148 : : }
1149 : :
1150 [ + - ]: 21 : if (value->typePtr == tkapp->IntType ||
1151 [ - + ]: 21 : value->typePtr == tkapp->WideIntType) {
1152 : 0 : result = fromWideIntObj(tkapp, value);
1153 [ # # # # ]: 0 : if (result != NULL || PyErr_Occurred())
1154 : 0 : return result;
1155 : 0 : Tcl_ResetResult(interp);
1156 : : /* If there is an error in the wideInt conversion,
1157 : : fall through to bignum handling. */
1158 : : }
1159 : :
1160 [ + - ]: 21 : if (value->typePtr == tkapp->IntType ||
1161 [ + - ]: 21 : value->typePtr == tkapp->WideIntType ||
1162 [ + + ]: 21 : value->typePtr == tkapp->BignumType) {
1163 : 6 : return fromBignumObj(tkapp, value);
1164 : : }
1165 : :
1166 [ + + ]: 15 : if (value->typePtr == tkapp->ListType) {
1167 : : int size;
1168 : : int i, status;
1169 : : PyObject *elem;
1170 : : Tcl_Obj *tcl_elem;
1171 : :
1172 : 10 : status = Tcl_ListObjLength(interp, value, &size);
1173 [ - + ]: 10 : if (status == TCL_ERROR)
1174 : 0 : return Tkinter_Error(tkapp);
1175 : 10 : result = PyTuple_New(size);
1176 [ - + ]: 10 : if (!result)
1177 : 0 : return NULL;
1178 [ + + ]: 35 : for (i = 0; i < size; i++) {
1179 : 25 : status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
1180 [ - + ]: 25 : if (status == TCL_ERROR) {
1181 : 0 : Py_DECREF(result);
1182 : 0 : return Tkinter_Error(tkapp);
1183 : : }
1184 : 25 : elem = FromObj(tkapp, tcl_elem);
1185 [ - + ]: 25 : if (!elem) {
1186 : 0 : Py_DECREF(result);
1187 : 0 : return NULL;
1188 : : }
1189 : 25 : PyTuple_SET_ITEM(result, i, elem);
1190 : : }
1191 : 10 : return result;
1192 : : }
1193 : :
1194 : 5 : if (value->typePtr == tkapp->ProcBodyType) {
1195 : : /* fall through: return tcl object. */
1196 : : }
1197 : :
1198 [ - + ]: 5 : if (value->typePtr == tkapp->StringType) {
1199 : 0 : return unicodeFromTclObj(value);
1200 : : }
1201 : :
1202 [ + - ]: 5 : if (tkapp->BooleanType == NULL &&
1203 [ + + ]: 5 : strcmp(value->typePtr->name, "booleanString") == 0) {
1204 : : /* booleanString type is not registered in Tcl */
1205 : 1 : tkapp->BooleanType = value->typePtr;
1206 : 1 : return fromBoolean(tkapp, value);
1207 : : }
1208 : :
1209 [ + - ]: 4 : if (tkapp->BignumType == NULL &&
1210 [ + + ]: 4 : strcmp(value->typePtr->name, "bignum") == 0) {
1211 : : /* bignum type is not registered in Tcl */
1212 : 2 : tkapp->BignumType = value->typePtr;
1213 : 2 : return fromBignumObj(tkapp, value);
1214 : : }
1215 : :
1216 : 2 : return newPyTclObject(value);
1217 : : }
1218 : :
1219 : : /* This mutex synchronizes inter-thread command calls. */
1220 : : TCL_DECLARE_MUTEX(call_mutex)
1221 : :
1222 : : typedef struct Tkapp_CallEvent {
1223 : : Tcl_Event ev; /* Must be first */
1224 : : TkappObject *self;
1225 : : PyObject *args;
1226 : : int flags;
1227 : : PyObject **res;
1228 : : PyObject **exc_type, **exc_value, **exc_tb;
1229 : : Tcl_Condition *done;
1230 : : } Tkapp_CallEvent;
1231 : :
1232 : : void
1233 : 366 : Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1234 : : {
1235 : : int i;
1236 [ + + ]: 1407 : for (i = 0; i < objc; i++)
1237 [ + + ]: 1041 : Tcl_DecrRefCount(objv[i]);
1238 [ - + ]: 366 : if (objv != objStore)
1239 : 0 : PyMem_Free(objv);
1240 : 366 : }
1241 : :
1242 : : /* Convert Python objects to Tcl objects. This must happen in the
1243 : : interpreter thread, which may or may not be the calling thread. */
1244 : :
1245 : : static Tcl_Obj**
1246 : 366 : Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1247 : : {
1248 : 366 : Tcl_Obj **objv = objStore;
1249 : 366 : Py_ssize_t objc = 0, i;
1250 [ + - ]: 366 : if (args == NULL)
1251 : : /* do nothing */;
1252 : :
1253 [ - + - - ]: 366 : else if (!(PyTuple_Check(args) || PyList_Check(args))) {
1254 : 0 : objv[0] = AsObj(args);
1255 [ # # ]: 0 : if (objv[0] == NULL)
1256 : 0 : goto finally;
1257 : 0 : objc = 1;
1258 : 0 : Tcl_IncrRefCount(objv[0]);
1259 : : }
1260 : : else {
1261 [ - + ]: 366 : objc = PySequence_Fast_GET_SIZE(args);
1262 : :
1263 [ - + ]: 366 : if (objc > ARGSZ) {
1264 [ # # ]: 0 : if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1265 [ # # ]: 0 : PyErr_SetString(PyExc_OverflowError,
1266 : 0 : PyTuple_Check(args) ? "tuple is too long" :
1267 : : "list is too long");
1268 : 0 : return NULL;
1269 : : }
1270 : 0 : objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *));
1271 [ # # ]: 0 : if (objv == NULL) {
1272 : : PyErr_NoMemory();
1273 : 0 : objc = 0;
1274 : 0 : goto finally;
1275 : : }
1276 : : }
1277 : :
1278 [ + + ]: 1407 : for (i = 0; i < objc; i++) {
1279 [ - + ]: 1041 : PyObject *v = PySequence_Fast_GET_ITEM(args, i);
1280 [ - + ]: 1041 : if (v == Py_None) {
1281 : 0 : objc = i;
1282 : 0 : break;
1283 : : }
1284 : 1041 : objv[i] = AsObj(v);
1285 [ - + ]: 1041 : if (!objv[i]) {
1286 : : /* Reset objc, so it attempts to clear
1287 : : objects only up to i. */
1288 : 0 : objc = i;
1289 : 0 : goto finally;
1290 : : }
1291 : 1041 : Tcl_IncrRefCount(objv[i]);
1292 : : }
1293 : : }
1294 : 366 : *pobjc = (int)objc;
1295 : 366 : return objv;
1296 : 0 : finally:
1297 : 0 : Tkapp_CallDeallocArgs(objv, objStore, (int)objc);
1298 : 0 : return NULL;
1299 : : }
1300 : :
1301 : : /* Convert the results of a command call into a Python string. */
1302 : :
1303 : : static PyObject *
1304 : 65 : Tkapp_UnicodeResult(TkappObject *self)
1305 : : {
1306 : 65 : return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
1307 : : }
1308 : :
1309 : :
1310 : : /* Convert the results of a command call into a Python objects. */
1311 : :
1312 : : static PyObject *
1313 : 364 : Tkapp_ObjectResult(TkappObject *self)
1314 : : {
1315 : 364 : PyObject *res = NULL;
1316 : 364 : Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1317 [ + - ]: 364 : if (self->wantobjects) {
1318 : : /* Not sure whether the IncrRef is necessary, but something
1319 : : may overwrite the interpreter result while we are
1320 : : converting it. */
1321 : 364 : Tcl_IncrRefCount(value);
1322 : 364 : res = FromObj(self, value);
1323 [ - + ]: 364 : Tcl_DecrRefCount(value);
1324 : : } else {
1325 : 0 : res = unicodeFromTclObj(value);
1326 : : }
1327 : 364 : return res;
1328 : : }
1329 : :
1330 : :
1331 : : /* Tkapp_CallProc is the event procedure that is executed in the context of
1332 : : the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1333 : : hold the Python lock. */
1334 : :
1335 : : static int
1336 : 0 : Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1337 : : {
1338 : : Tcl_Obj *objStore[ARGSZ];
1339 : : Tcl_Obj **objv;
1340 : : int objc;
1341 : : int i;
1342 [ # # ]: 0 : ENTER_PYTHON
1343 : 0 : objv = Tkapp_CallArgs(e->args, objStore, &objc);
1344 [ # # ]: 0 : if (!objv) {
1345 : 0 : PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1346 : 0 : *(e->res) = NULL;
1347 : : }
1348 [ # # ]: 0 : LEAVE_PYTHON
1349 [ # # ]: 0 : if (!objv)
1350 : 0 : goto done;
1351 : 0 : i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1352 [ # # ]: 0 : ENTER_PYTHON
1353 [ # # ]: 0 : if (i == TCL_ERROR) {
1354 : 0 : *(e->res) = Tkinter_Error(e->self);
1355 : : }
1356 : : else {
1357 : 0 : *(e->res) = Tkapp_ObjectResult(e->self);
1358 : : }
1359 [ # # ]: 0 : if (*(e->res) == NULL) {
1360 : 0 : PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1361 : : }
1362 [ # # ]: 0 : LEAVE_PYTHON
1363 : :
1364 : 0 : Tkapp_CallDeallocArgs(objv, objStore, objc);
1365 : 0 : done:
1366 : : /* Wake up calling thread. */
1367 : 0 : Tcl_MutexLock(&call_mutex);
1368 : 0 : Tcl_ConditionNotify(e->done);
1369 : 0 : Tcl_MutexUnlock(&call_mutex);
1370 : 0 : return 1;
1371 : : }
1372 : :
1373 : :
1374 : : /* This is the main entry point for calling a Tcl command.
1375 : : It supports three cases, with regard to threading:
1376 : : 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1377 : : the context of the calling thread.
1378 : : 2. Tcl is threaded, caller of the command is in the interpreter thread:
1379 : : Execute the command in the calling thread. Since the Tcl lock will
1380 : : not be used, we can merge that with case 1.
1381 : : 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1382 : : the interpreter thread. Allocation of Tcl objects needs to occur in the
1383 : : interpreter thread, so we ship the PyObject* args to the target thread,
1384 : : and perform processing there. */
1385 : :
1386 : : static PyObject *
1387 : 366 : Tkapp_Call(PyObject *selfptr, PyObject *args)
1388 : : {
1389 : : Tcl_Obj *objStore[ARGSZ];
1390 : 366 : Tcl_Obj **objv = NULL;
1391 : : int objc, i;
1392 : 366 : PyObject *res = NULL;
1393 : 366 : TkappObject *self = (TkappObject*)selfptr;
1394 : 366 : int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1395 : :
1396 : : /* If args is a single tuple, replace with contents of tuple */
1397 [ - + ]: 366 : if (PyTuple_GET_SIZE(args) == 1) {
1398 : 0 : PyObject *item = PyTuple_GET_ITEM(args, 0);
1399 [ # # ]: 0 : if (PyTuple_Check(item))
1400 : 0 : args = item;
1401 : : }
1402 [ + - - + ]: 366 : if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1403 : : /* We cannot call the command directly. Instead, we must
1404 : : marshal the parameters to the interpreter thread. */
1405 : : Tkapp_CallEvent *ev;
1406 : 0 : Tcl_Condition cond = NULL;
1407 : : PyObject *exc_type, *exc_value, *exc_tb;
1408 [ # # ]: 0 : if (!WaitForMainloop(self))
1409 : 0 : return NULL;
1410 : 0 : ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1411 [ # # ]: 0 : if (ev == NULL) {
1412 : : PyErr_NoMemory();
1413 : 0 : return NULL;
1414 : : }
1415 : 0 : ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1416 : 0 : ev->self = self;
1417 : 0 : ev->args = args;
1418 : 0 : ev->res = &res;
1419 : 0 : ev->exc_type = &exc_type;
1420 : 0 : ev->exc_value = &exc_value;
1421 : 0 : ev->exc_tb = &exc_tb;
1422 : 0 : ev->done = &cond;
1423 : :
1424 : 0 : Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1425 : :
1426 [ # # ]: 0 : if (res == NULL) {
1427 [ # # ]: 0 : if (exc_type)
1428 : 0 : PyErr_Restore(exc_type, exc_value, exc_tb);
1429 : : else
1430 : 0 : PyErr_SetObject(Tkinter_TclError, exc_value);
1431 : : }
1432 : 0 : Tcl_ConditionFinalize(&cond);
1433 : : }
1434 : : else
1435 : : {
1436 : :
1437 : 366 : objv = Tkapp_CallArgs(args, objStore, &objc);
1438 [ - + ]: 366 : if (!objv)
1439 : 0 : return NULL;
1440 : :
1441 [ - + ]: 366 : ENTER_TCL
1442 : :
1443 : 366 : i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1444 : :
1445 : 366 : ENTER_OVERLAP
1446 : :
1447 [ + + ]: 366 : if (i == TCL_ERROR)
1448 : 2 : Tkinter_Error(self);
1449 : : else
1450 : 364 : res = Tkapp_ObjectResult(self);
1451 : :
1452 [ - + ]: 366 : LEAVE_OVERLAP_TCL
1453 : :
1454 : 366 : Tkapp_CallDeallocArgs(objv, objStore, objc);
1455 : : }
1456 : 366 : return res;
1457 : : }
1458 : :
1459 : :
1460 : : /*[clinic input]
1461 : : _tkinter.tkapp.eval
1462 : :
1463 : : script: str
1464 : : /
1465 : :
1466 : : [clinic start generated code]*/
1467 : :
1468 : : static PyObject *
1469 : 24 : _tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
1470 : : /*[clinic end generated code: output=24b79831f700dea0 input=481484123a455f22]*/
1471 : : {
1472 : 24 : PyObject *res = NULL;
1473 : : int err;
1474 : :
1475 [ + - - + ]: 24 : CHECK_STRING_LENGTH(script);
1476 [ + - - + ]: 24 : CHECK_TCL_APPARTMENT;
1477 : :
1478 [ - + ]: 24 : ENTER_TCL
1479 : 24 : err = Tcl_Eval(Tkapp_Interp(self), script);
1480 : 24 : ENTER_OVERLAP
1481 [ + + ]: 24 : if (err == TCL_ERROR)
1482 : 3 : res = Tkinter_Error(self);
1483 : : else
1484 : 21 : res = Tkapp_UnicodeResult(self);
1485 [ - + ]: 24 : LEAVE_OVERLAP_TCL
1486 : 24 : return res;
1487 : : }
1488 : :
1489 : : /*[clinic input]
1490 : : _tkinter.tkapp.evalfile
1491 : :
1492 : : fileName: str
1493 : : /
1494 : :
1495 : : [clinic start generated code]*/
1496 : :
1497 : : static PyObject *
1498 : 4 : _tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
1499 : : /*[clinic end generated code: output=63be88dcee4f11d3 input=873ab707e5e947e1]*/
1500 : : {
1501 : 4 : PyObject *res = NULL;
1502 : : int err;
1503 : :
1504 [ + - - + ]: 4 : CHECK_STRING_LENGTH(fileName);
1505 [ + - - + ]: 4 : CHECK_TCL_APPARTMENT;
1506 : :
1507 [ - + ]: 4 : ENTER_TCL
1508 : 4 : err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1509 : 4 : ENTER_OVERLAP
1510 [ + + ]: 4 : if (err == TCL_ERROR)
1511 : 1 : res = Tkinter_Error(self);
1512 : : else
1513 : 3 : res = Tkapp_UnicodeResult(self);
1514 [ - + ]: 4 : LEAVE_OVERLAP_TCL
1515 : 4 : return res;
1516 : : }
1517 : :
1518 : : /*[clinic input]
1519 : : _tkinter.tkapp.record
1520 : :
1521 : : script: str
1522 : : /
1523 : :
1524 : : [clinic start generated code]*/
1525 : :
1526 : : static PyObject *
1527 : 0 : _tkinter_tkapp_record_impl(TkappObject *self, const char *script)
1528 : : /*[clinic end generated code: output=0ffe08a0061730df input=c0b0db5a21412cac]*/
1529 : : {
1530 : 0 : PyObject *res = NULL;
1531 : : int err;
1532 : :
1533 [ # # # # ]: 0 : CHECK_STRING_LENGTH(script);
1534 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
1535 : :
1536 [ # # ]: 0 : ENTER_TCL
1537 : 0 : err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1538 : 0 : ENTER_OVERLAP
1539 [ # # ]: 0 : if (err == TCL_ERROR)
1540 : 0 : res = Tkinter_Error(self);
1541 : : else
1542 : 0 : res = Tkapp_UnicodeResult(self);
1543 [ # # ]: 0 : LEAVE_OVERLAP_TCL
1544 : 0 : return res;
1545 : : }
1546 : :
1547 : : /*[clinic input]
1548 : : _tkinter.tkapp.adderrorinfo
1549 : :
1550 : : msg: str
1551 : : /
1552 : :
1553 : : [clinic start generated code]*/
1554 : :
1555 : : static PyObject *
1556 : 0 : _tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
1557 : : /*[clinic end generated code: output=52162eaca2ee53cb input=f4b37aec7c7e8c77]*/
1558 : : {
1559 [ # # # # ]: 0 : CHECK_STRING_LENGTH(msg);
1560 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
1561 : :
1562 [ # # ]: 0 : ENTER_TCL
1563 : 0 : Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1564 [ # # ]: 0 : LEAVE_TCL
1565 : :
1566 : 0 : Py_RETURN_NONE;
1567 : : }
1568 : :
1569 : :
1570 : :
1571 : : /** Tcl Variable **/
1572 : :
1573 : : typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
1574 : :
1575 : : TCL_DECLARE_MUTEX(var_mutex)
1576 : :
1577 : : typedef struct VarEvent {
1578 : : Tcl_Event ev; /* must be first */
1579 : : TkappObject *self;
1580 : : PyObject *args;
1581 : : int flags;
1582 : : EventFunc func;
1583 : : PyObject **res;
1584 : : PyObject **exc_type;
1585 : : PyObject **exc_val;
1586 : : Tcl_Condition *cond;
1587 : : } VarEvent;
1588 : :
1589 : : /*[python]
1590 : :
1591 : : class varname_converter(CConverter):
1592 : : type = 'const char *'
1593 : : converter = 'varname_converter'
1594 : :
1595 : : [python]*/
1596 : : /*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
1597 : :
1598 : : static int
1599 : 9 : varname_converter(PyObject *in, void *_out)
1600 : : {
1601 : : const char *s;
1602 : 9 : const char **out = (const char**)_out;
1603 [ - + ]: 9 : if (PyBytes_Check(in)) {
1604 [ # # ]: 0 : if (PyBytes_GET_SIZE(in) > INT_MAX) {
1605 : 0 : PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1606 : 0 : return 0;
1607 : : }
1608 : 0 : s = PyBytes_AS_STRING(in);
1609 [ # # ]: 0 : if (strlen(s) != (size_t)PyBytes_GET_SIZE(in)) {
1610 : 0 : PyErr_SetString(PyExc_ValueError, "embedded null byte");
1611 : 0 : return 0;
1612 : : }
1613 : 0 : *out = s;
1614 : 0 : return 1;
1615 : : }
1616 [ + - ]: 9 : if (PyUnicode_Check(in)) {
1617 : : Py_ssize_t size;
1618 : 9 : s = PyUnicode_AsUTF8AndSize(in, &size);
1619 [ - + ]: 9 : if (s == NULL) {
1620 : 0 : return 0;
1621 : : }
1622 [ - + ]: 9 : if (size > INT_MAX) {
1623 : 0 : PyErr_SetString(PyExc_OverflowError, "string is too long");
1624 : 0 : return 0;
1625 : : }
1626 [ - + ]: 9 : if (strlen(s) != (size_t)size) {
1627 : 0 : PyErr_SetString(PyExc_ValueError, "embedded null character");
1628 : 0 : return 0;
1629 : : }
1630 : 9 : *out = s;
1631 : 9 : return 1;
1632 : : }
1633 [ # # ]: 0 : if (PyTclObject_Check(in)) {
1634 : 0 : *out = Tcl_GetString(((PyTclObject *)in)->value);
1635 : 0 : return 1;
1636 : : }
1637 : 0 : PyErr_Format(PyExc_TypeError,
1638 : : "must be str, bytes or Tcl_Obj, not %.50s",
1639 : 0 : Py_TYPE(in)->tp_name);
1640 : 0 : return 0;
1641 : : }
1642 : :
1643 : :
1644 : : static void
1645 : 0 : var_perform(VarEvent *ev)
1646 : : {
1647 : 0 : *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1648 [ # # ]: 0 : if (!*(ev->res)) {
1649 : : PyObject *exc, *val, *tb;
1650 : 0 : PyErr_Fetch(&exc, &val, &tb);
1651 : 0 : PyErr_NormalizeException(&exc, &val, &tb);
1652 : 0 : *(ev->exc_type) = exc;
1653 : 0 : *(ev->exc_val) = val;
1654 : 0 : Py_XDECREF(tb);
1655 : : }
1656 : :
1657 : 0 : }
1658 : :
1659 : : static int
1660 : 0 : var_proc(VarEvent* ev, int flags)
1661 : : {
1662 [ # # ]: 0 : ENTER_PYTHON
1663 : 0 : var_perform(ev);
1664 : 0 : Tcl_MutexLock(&var_mutex);
1665 : 0 : Tcl_ConditionNotify(ev->cond);
1666 : 0 : Tcl_MutexUnlock(&var_mutex);
1667 [ # # ]: 0 : LEAVE_PYTHON
1668 : 0 : return 1;
1669 : : }
1670 : :
1671 : :
1672 : : static PyObject*
1673 : 12 : var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1674 : : {
1675 : 12 : TkappObject *self = (TkappObject*)selfptr;
1676 [ + - - + ]: 12 : if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1677 : : VarEvent *ev;
1678 : : PyObject *res, *exc_type, *exc_val;
1679 : 0 : Tcl_Condition cond = NULL;
1680 : :
1681 : : /* The current thread is not the interpreter thread. Marshal
1682 : : the call to the interpreter thread, then wait for
1683 : : completion. */
1684 [ # # ]: 0 : if (!WaitForMainloop(self))
1685 : 0 : return NULL;
1686 : :
1687 : 0 : ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1688 [ # # ]: 0 : if (ev == NULL) {
1689 : : PyErr_NoMemory();
1690 : 0 : return NULL;
1691 : : }
1692 : 0 : ev->self = self;
1693 : 0 : ev->args = args;
1694 : 0 : ev->flags = flags;
1695 : 0 : ev->func = func;
1696 : 0 : ev->res = &res;
1697 : 0 : ev->exc_type = &exc_type;
1698 : 0 : ev->exc_val = &exc_val;
1699 : 0 : ev->cond = &cond;
1700 : 0 : ev->ev.proc = (Tcl_EventProc*)var_proc;
1701 : 0 : Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1702 : 0 : Tcl_ConditionFinalize(&cond);
1703 [ # # ]: 0 : if (!res) {
1704 : 0 : PyErr_SetObject(exc_type, exc_val);
1705 : 0 : Py_DECREF(exc_type);
1706 : 0 : Py_DECREF(exc_val);
1707 : 0 : return NULL;
1708 : : }
1709 : 0 : return res;
1710 : : }
1711 : : /* Tcl is not threaded, or this is the interpreter thread. */
1712 : 12 : return func(self, args, flags);
1713 : : }
1714 : :
1715 : : static PyObject *
1716 : 5 : SetVar(TkappObject *self, PyObject *args, int flags)
1717 : : {
1718 : : const char *name1, *name2;
1719 : : PyObject *newValue;
1720 : 5 : PyObject *res = NULL;
1721 : : Tcl_Obj *newval, *ok;
1722 : :
1723 [ + - - ]: 5 : switch (PyTuple_GET_SIZE(args)) {
1724 : 5 : case 2:
1725 [ - + ]: 5 : if (!PyArg_ParseTuple(args, "O&O:setvar",
1726 : : varname_converter, &name1, &newValue))
1727 : 0 : return NULL;
1728 : : /* XXX Acquire tcl lock??? */
1729 : 5 : newval = AsObj(newValue);
1730 [ - + ]: 5 : if (newval == NULL)
1731 : 0 : return NULL;
1732 [ - + ]: 5 : ENTER_TCL
1733 : 5 : ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1734 : : newval, flags);
1735 : 5 : ENTER_OVERLAP
1736 [ - + ]: 5 : if (!ok)
1737 : 0 : Tkinter_Error(self);
1738 : : else {
1739 : 5 : res = Py_None;
1740 : 5 : Py_INCREF(res);
1741 : : }
1742 [ - + ]: 5 : LEAVE_OVERLAP_TCL
1743 : 5 : break;
1744 : 0 : case 3:
1745 [ # # ]: 0 : if (!PyArg_ParseTuple(args, "ssO:setvar",
1746 : : &name1, &name2, &newValue))
1747 : 0 : return NULL;
1748 [ # # # # ]: 0 : CHECK_STRING_LENGTH(name1);
1749 [ # # # # ]: 0 : CHECK_STRING_LENGTH(name2);
1750 : : /* XXX must hold tcl lock already??? */
1751 : 0 : newval = AsObj(newValue);
1752 [ # # ]: 0 : ENTER_TCL
1753 : 0 : ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1754 : 0 : ENTER_OVERLAP
1755 [ # # ]: 0 : if (!ok)
1756 : 0 : Tkinter_Error(self);
1757 : : else {
1758 : 0 : res = Py_None;
1759 : 0 : Py_INCREF(res);
1760 : : }
1761 [ # # ]: 0 : LEAVE_OVERLAP_TCL
1762 : 0 : break;
1763 : 0 : default:
1764 : 0 : PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1765 : 0 : return NULL;
1766 : : }
1767 : 5 : return res;
1768 : : }
1769 : :
1770 : : static PyObject *
1771 : 5 : Tkapp_SetVar(PyObject *self, PyObject *args)
1772 : : {
1773 : 5 : return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1774 : : }
1775 : :
1776 : : static PyObject *
1777 : 0 : Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1778 : : {
1779 : 0 : return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1780 : : }
1781 : :
1782 : :
1783 : :
1784 : : static PyObject *
1785 : 4 : GetVar(TkappObject *self, PyObject *args, int flags)
1786 : : {
1787 : 4 : const char *name1, *name2=NULL;
1788 : 4 : PyObject *res = NULL;
1789 : : Tcl_Obj *tres;
1790 : :
1791 [ - + ]: 4 : if (!PyArg_ParseTuple(args, "O&|s:getvar",
1792 : : varname_converter, &name1, &name2))
1793 : 0 : return NULL;
1794 : :
1795 [ - + - - ]: 4 : CHECK_STRING_LENGTH(name2);
1796 [ - + ]: 4 : ENTER_TCL
1797 : 4 : tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1798 : 4 : ENTER_OVERLAP
1799 [ + + ]: 4 : if (tres == NULL) {
1800 : 2 : Tkinter_Error(self);
1801 : : } else {
1802 [ + - ]: 2 : if (self->wantobjects) {
1803 : 2 : res = FromObj(self, tres);
1804 : : }
1805 : : else {
1806 : 0 : res = unicodeFromTclObj(tres);
1807 : : }
1808 : : }
1809 [ - + ]: 4 : LEAVE_OVERLAP_TCL
1810 : 4 : return res;
1811 : : }
1812 : :
1813 : : static PyObject *
1814 : 4 : Tkapp_GetVar(PyObject *self, PyObject *args)
1815 : : {
1816 : 4 : return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1817 : : }
1818 : :
1819 : : static PyObject *
1820 : 0 : Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1821 : : {
1822 : 0 : return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1823 : : }
1824 : :
1825 : :
1826 : :
1827 : : static PyObject *
1828 : 3 : UnsetVar(TkappObject *self, PyObject *args, int flags)
1829 : : {
1830 : 3 : char *name1, *name2=NULL;
1831 : : int code;
1832 : 3 : PyObject *res = NULL;
1833 : :
1834 [ - + ]: 3 : if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1835 : 0 : return NULL;
1836 : :
1837 [ + - - + ]: 3 : CHECK_STRING_LENGTH(name1);
1838 [ - + - - ]: 3 : CHECK_STRING_LENGTH(name2);
1839 [ - + ]: 3 : ENTER_TCL
1840 : 3 : code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1841 : 3 : ENTER_OVERLAP
1842 [ + + ]: 3 : if (code == TCL_ERROR)
1843 : 1 : res = Tkinter_Error(self);
1844 : : else {
1845 : 2 : Py_INCREF(Py_None);
1846 : 2 : res = Py_None;
1847 : : }
1848 [ - + ]: 3 : LEAVE_OVERLAP_TCL
1849 : 3 : return res;
1850 : : }
1851 : :
1852 : : static PyObject *
1853 : 3 : Tkapp_UnsetVar(PyObject *self, PyObject *args)
1854 : : {
1855 : 3 : return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1856 : : }
1857 : :
1858 : : static PyObject *
1859 : 0 : Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1860 : : {
1861 : 0 : return var_invoke(UnsetVar, self, args,
1862 : : TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1863 : : }
1864 : :
1865 : :
1866 : :
1867 : : /** Tcl to Python **/
1868 : :
1869 : : /*[clinic input]
1870 : : _tkinter.tkapp.getint
1871 : :
1872 : : arg: object
1873 : : /
1874 : :
1875 : : [clinic start generated code]*/
1876 : :
1877 : : static PyObject *
1878 : 58 : _tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
1879 : : /*[clinic end generated code: output=88cf293fae307cfe input=034026997c5b91f8]*/
1880 : : {
1881 : : char *s;
1882 : : Tcl_Obj *value;
1883 : : PyObject *result;
1884 : :
1885 [ + + ]: 58 : if (PyLong_Check(arg)) {
1886 : 1 : Py_INCREF(arg);
1887 : 1 : return arg;
1888 : : }
1889 : :
1890 [ - + ]: 57 : if (PyTclObject_Check(arg)) {
1891 : 0 : value = ((PyTclObject*)arg)->value;
1892 : 0 : Tcl_IncrRefCount(value);
1893 : : }
1894 : : else {
1895 [ + + ]: 57 : if (!PyArg_Parse(arg, "s:getint", &s))
1896 : 4 : return NULL;
1897 [ + - - + ]: 53 : CHECK_STRING_LENGTH(s);
1898 : 53 : value = Tcl_NewStringObj(s, -1);
1899 [ - + ]: 53 : if (value == NULL)
1900 : 0 : return Tkinter_Error(self);
1901 : : }
1902 : : /* Don't use Tcl_GetInt() because it returns ambiguous result for value
1903 : : in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
1904 : :
1905 : : Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
1906 : : value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
1907 : : */
1908 : 53 : result = fromBignumObj(self, value);
1909 [ + - ]: 53 : Tcl_DecrRefCount(value);
1910 [ + + + - ]: 53 : if (result != NULL || PyErr_Occurred())
1911 : 53 : return result;
1912 : 0 : return Tkinter_Error(self);
1913 : : }
1914 : :
1915 : : /*[clinic input]
1916 : : _tkinter.tkapp.getdouble
1917 : :
1918 : : arg: object
1919 : : /
1920 : :
1921 : : [clinic start generated code]*/
1922 : :
1923 : : static PyObject *
1924 : 8 : _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
1925 : : /*[clinic end generated code: output=c52b138bd8b956b9 input=22015729ce9ef7f8]*/
1926 : : {
1927 : : char *s;
1928 : : double v;
1929 : :
1930 [ + + ]: 8 : if (PyFloat_Check(arg)) {
1931 : 1 : Py_INCREF(arg);
1932 : 1 : return arg;
1933 : : }
1934 : :
1935 [ + + ]: 7 : if (PyNumber_Check(arg)) {
1936 : 1 : return PyNumber_Float(arg);
1937 : : }
1938 : :
1939 [ - + ]: 6 : if (PyTclObject_Check(arg)) {
1940 [ # # ]: 0 : if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
1941 : : ((PyTclObject*)arg)->value,
1942 : : &v) == TCL_ERROR)
1943 : 0 : return Tkinter_Error(self);
1944 : 0 : return PyFloat_FromDouble(v);
1945 : : }
1946 : :
1947 [ + + ]: 6 : if (!PyArg_Parse(arg, "s:getdouble", &s))
1948 : 3 : return NULL;
1949 [ + - - + ]: 3 : CHECK_STRING_LENGTH(s);
1950 [ + + ]: 3 : if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1951 : 1 : return Tkinter_Error(self);
1952 : 2 : return PyFloat_FromDouble(v);
1953 : : }
1954 : :
1955 : : /*[clinic input]
1956 : : _tkinter.tkapp.getboolean
1957 : :
1958 : : arg: object
1959 : : /
1960 : :
1961 : : [clinic start generated code]*/
1962 : :
1963 : : static PyObject *
1964 : 9 : _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
1965 : : /*[clinic end generated code: output=726a9ae445821d91 input=7f11248ef8f8776e]*/
1966 : : {
1967 : : char *s;
1968 : : int v;
1969 : :
1970 [ + + ]: 9 : if (PyLong_Check(arg)) { /* int or bool */
1971 : 2 : return PyBool_FromLong(Py_SIZE(arg) != 0);
1972 : : }
1973 : :
1974 [ - + ]: 7 : if (PyTclObject_Check(arg)) {
1975 [ # # ]: 0 : if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
1976 : : ((PyTclObject*)arg)->value,
1977 : : &v) == TCL_ERROR)
1978 : 0 : return Tkinter_Error(self);
1979 : 0 : return PyBool_FromLong(v);
1980 : : }
1981 : :
1982 [ + + ]: 7 : if (!PyArg_Parse(arg, "s:getboolean", &s))
1983 : 4 : return NULL;
1984 [ + - - + ]: 3 : CHECK_STRING_LENGTH(s);
1985 [ + + ]: 3 : if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1986 : 1 : return Tkinter_Error(self);
1987 : 2 : return PyBool_FromLong(v);
1988 : : }
1989 : :
1990 : : /*[clinic input]
1991 : : _tkinter.tkapp.exprstring
1992 : :
1993 : : s: str
1994 : : /
1995 : :
1996 : : [clinic start generated code]*/
1997 : :
1998 : : static PyObject *
1999 : 21 : _tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
2000 : : /*[clinic end generated code: output=beda323d3ed0abb1 input=fa78f751afb2f21b]*/
2001 : : {
2002 : 21 : PyObject *res = NULL;
2003 : : int retval;
2004 : :
2005 [ + - - + ]: 21 : CHECK_STRING_LENGTH(s);
2006 [ + - - + ]: 21 : CHECK_TCL_APPARTMENT;
2007 : :
2008 [ - + ]: 21 : ENTER_TCL
2009 : 21 : retval = Tcl_ExprString(Tkapp_Interp(self), s);
2010 : 21 : ENTER_OVERLAP
2011 [ + + ]: 21 : if (retval == TCL_ERROR)
2012 : 1 : res = Tkinter_Error(self);
2013 : : else
2014 : 20 : res = Tkapp_UnicodeResult(self);
2015 [ - + ]: 21 : LEAVE_OVERLAP_TCL
2016 : 21 : return res;
2017 : : }
2018 : :
2019 : : /*[clinic input]
2020 : : _tkinter.tkapp.exprlong
2021 : :
2022 : : s: str
2023 : : /
2024 : :
2025 : : [clinic start generated code]*/
2026 : :
2027 : : static PyObject *
2028 : 18 : _tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
2029 : : /*[clinic end generated code: output=5d6a46b63c6ebcf9 input=11bd7eee0c57b4dc]*/
2030 : : {
2031 : 18 : PyObject *res = NULL;
2032 : : int retval;
2033 : : long v;
2034 : :
2035 [ + - - + ]: 18 : CHECK_STRING_LENGTH(s);
2036 [ + - - + ]: 18 : CHECK_TCL_APPARTMENT;
2037 : :
2038 [ - + ]: 18 : ENTER_TCL
2039 : 18 : retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2040 : 18 : ENTER_OVERLAP
2041 [ + + ]: 18 : if (retval == TCL_ERROR)
2042 : 3 : res = Tkinter_Error(self);
2043 : : else
2044 : 15 : res = PyLong_FromLong(v);
2045 [ - + ]: 18 : LEAVE_OVERLAP_TCL
2046 : 18 : return res;
2047 : : }
2048 : :
2049 : : /*[clinic input]
2050 : : _tkinter.tkapp.exprdouble
2051 : :
2052 : : s: str
2053 : : /
2054 : :
2055 : : [clinic start generated code]*/
2056 : :
2057 : : static PyObject *
2058 : 18 : _tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
2059 : : /*[clinic end generated code: output=ff78df1081ea4158 input=ff02bc11798832d5]*/
2060 : : {
2061 : 18 : PyObject *res = NULL;
2062 : : double v;
2063 : : int retval;
2064 : :
2065 [ + - - + ]: 18 : CHECK_STRING_LENGTH(s);
2066 [ + - - + ]: 18 : CHECK_TCL_APPARTMENT;
2067 [ - + ]: 18 : ENTER_TCL
2068 : 18 : retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2069 : 18 : ENTER_OVERLAP
2070 [ + + ]: 18 : if (retval == TCL_ERROR)
2071 : 2 : res = Tkinter_Error(self);
2072 : : else
2073 : 16 : res = PyFloat_FromDouble(v);
2074 [ - + ]: 18 : LEAVE_OVERLAP_TCL
2075 : 18 : return res;
2076 : : }
2077 : :
2078 : : /*[clinic input]
2079 : : _tkinter.tkapp.exprboolean
2080 : :
2081 : : s: str
2082 : : /
2083 : :
2084 : : [clinic start generated code]*/
2085 : :
2086 : : static PyObject *
2087 : 42 : _tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
2088 : : /*[clinic end generated code: output=8b28038c22887311 input=c8c66022bdb8d5d3]*/
2089 : : {
2090 : 42 : PyObject *res = NULL;
2091 : : int retval;
2092 : : int v;
2093 : :
2094 [ + - - + ]: 42 : CHECK_STRING_LENGTH(s);
2095 [ + - - + ]: 42 : CHECK_TCL_APPARTMENT;
2096 [ - + ]: 42 : ENTER_TCL
2097 : 42 : retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2098 : 42 : ENTER_OVERLAP
2099 [ + + ]: 42 : if (retval == TCL_ERROR)
2100 : 2 : res = Tkinter_Error(self);
2101 : : else
2102 : 40 : res = PyLong_FromLong(v);
2103 [ - + ]: 42 : LEAVE_OVERLAP_TCL
2104 : 42 : return res;
2105 : : }
2106 : :
2107 : :
2108 : :
2109 : : /*[clinic input]
2110 : : _tkinter.tkapp.splitlist
2111 : :
2112 : : arg: object
2113 : : /
2114 : :
2115 : : [clinic start generated code]*/
2116 : :
2117 : : static PyObject *
2118 : 34 : _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
2119 : : /*[clinic end generated code: output=13b51d34386d36fb input=2b2e13351e3c0b53]*/
2120 : : {
2121 : : char *list;
2122 : : int argc;
2123 : : const char **argv;
2124 : : PyObject *v;
2125 : : int i;
2126 : :
2127 [ + + ]: 34 : if (PyTclObject_Check(arg)) {
2128 : : int objc;
2129 : : Tcl_Obj **objv;
2130 [ - + ]: 2 : if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2131 : : ((PyTclObject*)arg)->value,
2132 : : &objc, &objv) == TCL_ERROR) {
2133 : 0 : return Tkinter_Error(self);
2134 : : }
2135 [ - + ]: 2 : if (!(v = PyTuple_New(objc)))
2136 : 0 : return NULL;
2137 [ + + ]: 12 : for (i = 0; i < objc; i++) {
2138 : 10 : PyObject *s = FromObj(self, objv[i]);
2139 [ - + ]: 10 : if (!s) {
2140 : 0 : Py_DECREF(v);
2141 : 0 : return NULL;
2142 : : }
2143 : 10 : PyTuple_SET_ITEM(v, i, s);
2144 : : }
2145 : 2 : return v;
2146 : : }
2147 [ + + ]: 32 : if (PyTuple_Check(arg)) {
2148 : 9 : Py_INCREF(arg);
2149 : 9 : return arg;
2150 : : }
2151 [ + + ]: 23 : if (PyList_Check(arg)) {
2152 : 2 : return PySequence_Tuple(arg);
2153 : : }
2154 : :
2155 [ + + ]: 21 : if (!PyArg_Parse(arg, "et:splitlist", "utf-8", &list))
2156 : 1 : return NULL;
2157 : :
2158 [ - + ]: 20 : if (strlen(list) >= INT_MAX) {
2159 : 0 : PyErr_SetString(PyExc_OverflowError, "string is too long");
2160 : 0 : PyMem_Free(list);
2161 : 0 : return NULL;
2162 : : }
2163 [ + + ]: 20 : if (Tcl_SplitList(Tkapp_Interp(self), list,
2164 : : &argc, &argv) == TCL_ERROR) {
2165 : 1 : PyMem_Free(list);
2166 : 1 : return Tkinter_Error(self);
2167 : : }
2168 : :
2169 [ - + ]: 19 : if (!(v = PyTuple_New(argc)))
2170 : 0 : goto finally;
2171 : :
2172 [ + + ]: 63 : for (i = 0; i < argc; i++) {
2173 : 44 : PyObject *s = unicodeFromTclString(argv[i]);
2174 [ - + ]: 44 : if (!s) {
2175 : 0 : Py_DECREF(v);
2176 : 0 : v = NULL;
2177 : 0 : goto finally;
2178 : : }
2179 : 44 : PyTuple_SET_ITEM(v, i, s);
2180 : : }
2181 : :
2182 : 19 : finally:
2183 : 19 : ckfree(FREECAST argv);
2184 : 19 : PyMem_Free(list);
2185 : 19 : return v;
2186 : : }
2187 : :
2188 : :
2189 : : /** Tcl Command **/
2190 : :
2191 : : /* Client data struct */
2192 : : typedef struct {
2193 : : PyObject *self;
2194 : : PyObject *func;
2195 : : } PythonCmd_ClientData;
2196 : :
2197 : : static int
2198 : 0 : PythonCmd_Error(Tcl_Interp *interp)
2199 : : {
2200 : 0 : errorInCmd = 1;
2201 : 0 : PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2202 [ # # ]: 0 : LEAVE_PYTHON
2203 : 0 : return TCL_ERROR;
2204 : : }
2205 : :
2206 : : /* This is the Tcl command that acts as a wrapper for Python
2207 : : * function or method.
2208 : : */
2209 : : static int
2210 : 45 : PythonCmd(ClientData clientData, Tcl_Interp *interp,
2211 : : int objc, Tcl_Obj *const objv[])
2212 : : {
2213 : 45 : PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2214 : : PyObject *args, *res;
2215 : : int i;
2216 : : Tcl_Obj *obj_res;
2217 : :
2218 [ - + ]: 45 : ENTER_PYTHON
2219 : :
2220 : : /* Create argument tuple (objv1, ..., objvN) */
2221 [ - + ]: 45 : if (!(args = PyTuple_New(objc - 1)))
2222 : 0 : return PythonCmd_Error(interp);
2223 : :
2224 [ + + ]: 90 : for (i = 0; i < (objc - 1); i++) {
2225 : 45 : PyObject *s = unicodeFromTclObj(objv[i + 1]);
2226 [ - + ]: 45 : if (!s) {
2227 : 0 : Py_DECREF(args);
2228 : 0 : return PythonCmd_Error(interp);
2229 : : }
2230 : 45 : PyTuple_SET_ITEM(args, i, s);
2231 : : }
2232 : :
2233 : 45 : res = PyObject_Call(data->func, args, NULL);
2234 : 45 : Py_DECREF(args);
2235 : :
2236 [ - + ]: 45 : if (res == NULL)
2237 : 0 : return PythonCmd_Error(interp);
2238 : :
2239 : 45 : obj_res = AsObj(res);
2240 [ - + ]: 45 : if (obj_res == NULL) {
2241 : 0 : Py_DECREF(res);
2242 : 0 : return PythonCmd_Error(interp);
2243 : : }
2244 : 45 : Tcl_SetObjResult(interp, obj_res);
2245 : 45 : Py_DECREF(res);
2246 : :
2247 [ - + ]: 45 : LEAVE_PYTHON
2248 : :
2249 : 45 : return TCL_OK;
2250 : : }
2251 : :
2252 : :
2253 : : static void
2254 : 1 : PythonCmdDelete(ClientData clientData)
2255 : : {
2256 : 1 : PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2257 : :
2258 [ - + ]: 1 : ENTER_PYTHON
2259 : 1 : Py_XDECREF(data->self);
2260 : 1 : Py_XDECREF(data->func);
2261 : 1 : PyMem_Free(data);
2262 [ - + ]: 1 : LEAVE_PYTHON
2263 : 1 : }
2264 : :
2265 : :
2266 : :
2267 : :
2268 : : TCL_DECLARE_MUTEX(command_mutex)
2269 : :
2270 : : typedef struct CommandEvent{
2271 : : Tcl_Event ev;
2272 : : Tcl_Interp* interp;
2273 : : const char *name;
2274 : : int create;
2275 : : int *status;
2276 : : ClientData *data;
2277 : : Tcl_Condition *done;
2278 : : } CommandEvent;
2279 : :
2280 : : static int
2281 : 0 : Tkapp_CommandProc(CommandEvent *ev, int flags)
2282 : : {
2283 [ # # ]: 0 : if (ev->create)
2284 : 0 : *ev->status = Tcl_CreateObjCommand(
2285 : : ev->interp, ev->name, PythonCmd,
2286 : 0 : ev->data, PythonCmdDelete) == NULL;
2287 : : else
2288 : 0 : *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2289 : 0 : Tcl_MutexLock(&command_mutex);
2290 : 0 : Tcl_ConditionNotify(ev->done);
2291 : 0 : Tcl_MutexUnlock(&command_mutex);
2292 : 0 : return 1;
2293 : : }
2294 : :
2295 : : /*[clinic input]
2296 : : _tkinter.tkapp.createcommand
2297 : :
2298 : : name: str
2299 : : func: object
2300 : : /
2301 : :
2302 : : [clinic start generated code]*/
2303 : :
2304 : : static PyObject *
2305 : 1 : _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
2306 : : PyObject *func)
2307 : : /*[clinic end generated code: output=2a1c79a4ee2af410 input=255785cb70edc6a0]*/
2308 : : {
2309 : : PythonCmd_ClientData *data;
2310 : : int err;
2311 : :
2312 [ + - - + ]: 1 : CHECK_STRING_LENGTH(name);
2313 [ - + ]: 1 : if (!PyCallable_Check(func)) {
2314 : 0 : PyErr_SetString(PyExc_TypeError, "command not callable");
2315 : 0 : return NULL;
2316 : : }
2317 : :
2318 [ + - - + : 1 : if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
- - ]
2319 : 0 : !WaitForMainloop(self))
2320 : 0 : return NULL;
2321 : :
2322 : 1 : data = PyMem_NEW(PythonCmd_ClientData, 1);
2323 [ - + ]: 1 : if (!data)
2324 : : return PyErr_NoMemory();
2325 : 1 : Py_INCREF(self);
2326 : 1 : Py_INCREF(func);
2327 : 1 : data->self = (PyObject *) self;
2328 : 1 : data->func = func;
2329 [ + - - + ]: 1 : if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2330 : 0 : Tcl_Condition cond = NULL;
2331 : 0 : CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2332 [ # # ]: 0 : if (ev == NULL) {
2333 : : PyErr_NoMemory();
2334 : 0 : PyMem_Free(data);
2335 : 0 : return NULL;
2336 : : }
2337 : 0 : ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2338 : 0 : ev->interp = self->interp;
2339 : 0 : ev->create = 1;
2340 : 0 : ev->name = name;
2341 : 0 : ev->data = (ClientData)data;
2342 : 0 : ev->status = &err;
2343 : 0 : ev->done = &cond;
2344 : 0 : Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2345 : 0 : Tcl_ConditionFinalize(&cond);
2346 : : }
2347 : : else
2348 : : {
2349 [ - + ]: 1 : ENTER_TCL
2350 : 1 : err = Tcl_CreateObjCommand(
2351 : : Tkapp_Interp(self), name, PythonCmd,
2352 : 1 : (ClientData)data, PythonCmdDelete) == NULL;
2353 [ - + ]: 1 : LEAVE_TCL
2354 : : }
2355 [ - + ]: 1 : if (err) {
2356 : 0 : PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2357 : 0 : PyMem_Free(data);
2358 : 0 : return NULL;
2359 : : }
2360 : :
2361 : 1 : Py_RETURN_NONE;
2362 : : }
2363 : :
2364 : :
2365 : :
2366 : : /*[clinic input]
2367 : : _tkinter.tkapp.deletecommand
2368 : :
2369 : : name: str
2370 : : /
2371 : :
2372 : : [clinic start generated code]*/
2373 : :
2374 : : static PyObject *
2375 : 1 : _tkinter_tkapp_deletecommand_impl(TkappObject *self, const char *name)
2376 : : /*[clinic end generated code: output=a67e8cb5845e0d2d input=53e9952eae1f85f5]*/
2377 : : {
2378 : : int err;
2379 : :
2380 [ + - - + ]: 1 : CHECK_STRING_LENGTH(name);
2381 : :
2382 [ + - - + ]: 1 : if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2383 : 0 : Tcl_Condition cond = NULL;
2384 : : CommandEvent *ev;
2385 : 0 : ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2386 [ # # ]: 0 : if (ev == NULL) {
2387 : : PyErr_NoMemory();
2388 : 0 : return NULL;
2389 : : }
2390 : 0 : ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2391 : 0 : ev->interp = self->interp;
2392 : 0 : ev->create = 0;
2393 : 0 : ev->name = name;
2394 : 0 : ev->status = &err;
2395 : 0 : ev->done = &cond;
2396 : 0 : Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2397 : : &command_mutex);
2398 : 0 : Tcl_ConditionFinalize(&cond);
2399 : : }
2400 : : else
2401 : : {
2402 [ - + ]: 1 : ENTER_TCL
2403 : 1 : err = Tcl_DeleteCommand(self->interp, name);
2404 [ - + ]: 1 : LEAVE_TCL
2405 : : }
2406 [ - + ]: 1 : if (err == -1) {
2407 : 0 : PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2408 : 0 : return NULL;
2409 : : }
2410 : 1 : Py_RETURN_NONE;
2411 : : }
2412 : :
2413 : :
2414 : :
2415 : : #ifdef HAVE_CREATEFILEHANDLER
2416 : : /** File Handler **/
2417 : :
2418 : : typedef struct _fhcdata {
2419 : : PyObject *func;
2420 : : PyObject *file;
2421 : : int id;
2422 : : struct _fhcdata *next;
2423 : : } FileHandler_ClientData;
2424 : :
2425 : : static FileHandler_ClientData *HeadFHCD;
2426 : :
2427 : : static FileHandler_ClientData *
2428 : 0 : NewFHCD(PyObject *func, PyObject *file, int id)
2429 : : {
2430 : : FileHandler_ClientData *p;
2431 : 0 : p = PyMem_NEW(FileHandler_ClientData, 1);
2432 [ # # ]: 0 : if (p != NULL) {
2433 : 0 : Py_XINCREF(func);
2434 : 0 : Py_XINCREF(file);
2435 : 0 : p->func = func;
2436 : 0 : p->file = file;
2437 : 0 : p->id = id;
2438 : 0 : p->next = HeadFHCD;
2439 : 0 : HeadFHCD = p;
2440 : : }
2441 : 0 : return p;
2442 : : }
2443 : :
2444 : : static void
2445 : 0 : DeleteFHCD(int id)
2446 : : {
2447 : : FileHandler_ClientData *p, **pp;
2448 : :
2449 : 0 : pp = &HeadFHCD;
2450 [ # # ]: 0 : while ((p = *pp) != NULL) {
2451 [ # # ]: 0 : if (p->id == id) {
2452 : 0 : *pp = p->next;
2453 : 0 : Py_XDECREF(p->func);
2454 : 0 : Py_XDECREF(p->file);
2455 : 0 : PyMem_Free(p);
2456 : : }
2457 : : else
2458 : 0 : pp = &p->next;
2459 : : }
2460 : 0 : }
2461 : :
2462 : : static void
2463 : 0 : FileHandler(ClientData clientData, int mask)
2464 : : {
2465 : 0 : FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2466 : : PyObject *func, *file, *res;
2467 : :
2468 [ # # ]: 0 : ENTER_PYTHON
2469 : 0 : func = data->func;
2470 : 0 : file = data->file;
2471 : :
2472 : 0 : res = PyObject_CallFunction(func, "Oi", file, mask);
2473 [ # # ]: 0 : if (res == NULL) {
2474 : 0 : errorInCmd = 1;
2475 : 0 : PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2476 : : }
2477 : 0 : Py_XDECREF(res);
2478 [ # # ]: 0 : LEAVE_PYTHON
2479 : 0 : }
2480 : :
2481 : : /*[clinic input]
2482 : : _tkinter.tkapp.createfilehandler
2483 : :
2484 : : file: object
2485 : : mask: int
2486 : : func: object
2487 : : /
2488 : :
2489 : : [clinic start generated code]*/
2490 : :
2491 : : static PyObject *
2492 : 0 : _tkinter_tkapp_createfilehandler_impl(TkappObject *self, PyObject *file,
2493 : : int mask, PyObject *func)
2494 : : /*[clinic end generated code: output=f73ce82de801c353 input=84943a5286e47947]*/
2495 : : {
2496 : : FileHandler_ClientData *data;
2497 : : int tfile;
2498 : :
2499 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
2500 : :
2501 : 0 : tfile = PyObject_AsFileDescriptor(file);
2502 [ # # ]: 0 : if (tfile < 0)
2503 : 0 : return NULL;
2504 [ # # ]: 0 : if (!PyCallable_Check(func)) {
2505 : 0 : PyErr_SetString(PyExc_TypeError, "bad argument list");
2506 : 0 : return NULL;
2507 : : }
2508 : :
2509 : 0 : data = NewFHCD(func, file, tfile);
2510 [ # # ]: 0 : if (data == NULL)
2511 : 0 : return NULL;
2512 : :
2513 : : /* Ought to check for null Tcl_File object... */
2514 [ # # ]: 0 : ENTER_TCL
2515 : 0 : Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2516 [ # # ]: 0 : LEAVE_TCL
2517 : 0 : Py_RETURN_NONE;
2518 : : }
2519 : :
2520 : : /*[clinic input]
2521 : : _tkinter.tkapp.deletefilehandler
2522 : :
2523 : : file: object
2524 : : /
2525 : :
2526 : : [clinic start generated code]*/
2527 : :
2528 : : static PyObject *
2529 : 0 : _tkinter_tkapp_deletefilehandler(TkappObject *self, PyObject *file)
2530 : : /*[clinic end generated code: output=b53cc96ebf9476fd input=abbec19d66312e2a]*/
2531 : : {
2532 : : int tfile;
2533 : :
2534 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
2535 : :
2536 : 0 : tfile = PyObject_AsFileDescriptor(file);
2537 [ # # ]: 0 : if (tfile < 0)
2538 : 0 : return NULL;
2539 : :
2540 : 0 : DeleteFHCD(tfile);
2541 : :
2542 : : /* Ought to check for null Tcl_File object... */
2543 [ # # ]: 0 : ENTER_TCL
2544 : 0 : Tcl_DeleteFileHandler(tfile);
2545 [ # # ]: 0 : LEAVE_TCL
2546 : 0 : Py_RETURN_NONE;
2547 : : }
2548 : : #endif /* HAVE_CREATEFILEHANDLER */
2549 : :
2550 : :
2551 : : /**** Tktt Object (timer token) ****/
2552 : :
2553 : : static PyObject *Tktt_Type;
2554 : :
2555 : : typedef struct {
2556 : : PyObject_HEAD
2557 : : Tcl_TimerToken token;
2558 : : PyObject *func;
2559 : : } TkttObject;
2560 : :
2561 : : /*[clinic input]
2562 : : _tkinter.tktimertoken.deletetimerhandler
2563 : :
2564 : : [clinic start generated code]*/
2565 : :
2566 : : static PyObject *
2567 : 0 : _tkinter_tktimertoken_deletetimerhandler_impl(TkttObject *self)
2568 : : /*[clinic end generated code: output=bd7fe17f328cfa55 input=40bd070ff85f5cf3]*/
2569 : : {
2570 : 0 : TkttObject *v = self;
2571 : 0 : PyObject *func = v->func;
2572 : :
2573 [ # # ]: 0 : if (v->token != NULL) {
2574 : 0 : Tcl_DeleteTimerHandler(v->token);
2575 : 0 : v->token = NULL;
2576 : : }
2577 [ # # ]: 0 : if (func != NULL) {
2578 : 0 : v->func = NULL;
2579 : 0 : Py_DECREF(func);
2580 : 0 : Py_DECREF(v); /* See Tktt_New() */
2581 : : }
2582 : 0 : Py_RETURN_NONE;
2583 : : }
2584 : :
2585 : : static TkttObject *
2586 : 0 : Tktt_New(PyObject *func)
2587 : : {
2588 : : TkttObject *v;
2589 : :
2590 : 0 : v = PyObject_New(TkttObject, (PyTypeObject *) Tktt_Type);
2591 [ # # ]: 0 : if (v == NULL)
2592 : 0 : return NULL;
2593 : :
2594 : 0 : Py_INCREF(func);
2595 : 0 : v->token = NULL;
2596 : 0 : v->func = func;
2597 : :
2598 : : /* Extra reference, deleted when called or when handler is deleted */
2599 : 0 : Py_INCREF(v);
2600 : 0 : return v;
2601 : : }
2602 : :
2603 : : static void
2604 : 0 : Tktt_Dealloc(PyObject *self)
2605 : : {
2606 : 0 : TkttObject *v = (TkttObject *)self;
2607 : 0 : PyObject *func = v->func;
2608 : 0 : PyObject *tp = (PyObject *) Py_TYPE(self);
2609 : :
2610 : 0 : Py_XDECREF(func);
2611 : :
2612 : 0 : PyObject_Free(self);
2613 : 0 : Py_DECREF(tp);
2614 : 0 : }
2615 : :
2616 : : static PyObject *
2617 : 0 : Tktt_Repr(PyObject *self)
2618 : : {
2619 : 0 : TkttObject *v = (TkttObject *)self;
2620 : 0 : return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2621 : : v,
2622 [ # # ]: 0 : v->func == NULL ? ", handler deleted" : "");
2623 : : }
2624 : :
2625 : : /** Timer Handler **/
2626 : :
2627 : : static void
2628 : 0 : TimerHandler(ClientData clientData)
2629 : : {
2630 : 0 : TkttObject *v = (TkttObject *)clientData;
2631 : 0 : PyObject *func = v->func;
2632 : : PyObject *res;
2633 : :
2634 [ # # ]: 0 : if (func == NULL)
2635 : 0 : return;
2636 : :
2637 : 0 : v->func = NULL;
2638 : :
2639 [ # # ]: 0 : ENTER_PYTHON
2640 : :
2641 : 0 : res = PyObject_CallNoArgs(func);
2642 : 0 : Py_DECREF(func);
2643 : 0 : Py_DECREF(v); /* See Tktt_New() */
2644 : :
2645 [ # # ]: 0 : if (res == NULL) {
2646 : 0 : errorInCmd = 1;
2647 : 0 : PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2648 : : }
2649 : : else
2650 : 0 : Py_DECREF(res);
2651 : :
2652 [ # # ]: 0 : LEAVE_PYTHON
2653 : : }
2654 : :
2655 : : /*[clinic input]
2656 : : _tkinter.tkapp.createtimerhandler
2657 : :
2658 : : milliseconds: int
2659 : : func: object
2660 : : /
2661 : :
2662 : : [clinic start generated code]*/
2663 : :
2664 : : static PyObject *
2665 : 0 : _tkinter_tkapp_createtimerhandler_impl(TkappObject *self, int milliseconds,
2666 : : PyObject *func)
2667 : : /*[clinic end generated code: output=2da5959b9d031911 input=ba6729f32f0277a5]*/
2668 : : {
2669 : : TkttObject *v;
2670 : :
2671 [ # # ]: 0 : if (!PyCallable_Check(func)) {
2672 : 0 : PyErr_SetString(PyExc_TypeError, "bad argument list");
2673 : 0 : return NULL;
2674 : : }
2675 : :
2676 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
2677 : :
2678 : 0 : v = Tktt_New(func);
2679 [ # # ]: 0 : if (v) {
2680 : 0 : v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2681 : : (ClientData)v);
2682 : : }
2683 : :
2684 : 0 : return (PyObject *) v;
2685 : : }
2686 : :
2687 : :
2688 : : /** Event Loop **/
2689 : :
2690 : : /*[clinic input]
2691 : : _tkinter.tkapp.mainloop
2692 : :
2693 : : threshold: int = 0
2694 : : /
2695 : :
2696 : : [clinic start generated code]*/
2697 : :
2698 : : static PyObject *
2699 : 0 : _tkinter_tkapp_mainloop_impl(TkappObject *self, int threshold)
2700 : : /*[clinic end generated code: output=0ba8eabbe57841b0 input=036bcdcf03d5eca0]*/
2701 : : {
2702 : 0 : PyThreadState *tstate = PyThreadState_Get();
2703 : :
2704 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
2705 : 0 : self->dispatching = 1;
2706 : :
2707 : 0 : quitMainLoop = 0;
2708 : 0 : while (Tk_GetNumMainWindows() > threshold &&
2709 [ # # # # ]: 0 : !quitMainLoop &&
2710 [ # # ]: 0 : !errorInCmd)
2711 : : {
2712 : : int result;
2713 : :
2714 [ # # ]: 0 : if (self->threaded) {
2715 : : /* Allow other Python threads to run. */
2716 [ # # ]: 0 : ENTER_TCL
2717 : 0 : result = Tcl_DoOneEvent(0);
2718 [ # # ]: 0 : LEAVE_TCL
2719 : : }
2720 : : else {
2721 : 0 : Py_BEGIN_ALLOW_THREADS
2722 [ # # ]: 0 : if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2723 : 0 : tcl_tstate = tstate;
2724 : 0 : result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2725 : 0 : tcl_tstate = NULL;
2726 [ # # ]: 0 : if(tcl_lock)PyThread_release_lock(tcl_lock);
2727 [ # # ]: 0 : if (result == 0)
2728 : 0 : Sleep(Tkinter_busywaitinterval);
2729 : 0 : Py_END_ALLOW_THREADS
2730 : : }
2731 : :
2732 [ # # ]: 0 : if (PyErr_CheckSignals() != 0) {
2733 : 0 : self->dispatching = 0;
2734 : 0 : return NULL;
2735 : : }
2736 [ # # ]: 0 : if (result < 0)
2737 : 0 : break;
2738 : : }
2739 : 0 : self->dispatching = 0;
2740 : 0 : quitMainLoop = 0;
2741 : :
2742 [ # # ]: 0 : if (errorInCmd) {
2743 : 0 : errorInCmd = 0;
2744 : 0 : PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2745 : 0 : excInCmd = valInCmd = trbInCmd = NULL;
2746 : 0 : return NULL;
2747 : : }
2748 : 0 : Py_RETURN_NONE;
2749 : : }
2750 : :
2751 : : /*[clinic input]
2752 : : _tkinter.tkapp.dooneevent
2753 : :
2754 : : flags: int = 0
2755 : : /
2756 : :
2757 : : [clinic start generated code]*/
2758 : :
2759 : : static PyObject *
2760 : 0 : _tkinter_tkapp_dooneevent_impl(TkappObject *self, int flags)
2761 : : /*[clinic end generated code: output=27c6b2aa464cac29 input=6542b928e364b793]*/
2762 : : {
2763 : : int rv;
2764 : :
2765 [ # # ]: 0 : ENTER_TCL
2766 : 0 : rv = Tcl_DoOneEvent(flags);
2767 [ # # ]: 0 : LEAVE_TCL
2768 : 0 : return PyLong_FromLong(rv);
2769 : : }
2770 : :
2771 : : /*[clinic input]
2772 : : _tkinter.tkapp.quit
2773 : : [clinic start generated code]*/
2774 : :
2775 : : static PyObject *
2776 : 0 : _tkinter_tkapp_quit_impl(TkappObject *self)
2777 : : /*[clinic end generated code: output=7f21eeff481f754f input=e03020dc38aff23c]*/
2778 : : {
2779 : 0 : quitMainLoop = 1;
2780 : 0 : Py_RETURN_NONE;
2781 : : }
2782 : :
2783 : : /*[clinic input]
2784 : : _tkinter.tkapp.interpaddr
2785 : : [clinic start generated code]*/
2786 : :
2787 : : static PyObject *
2788 : 0 : _tkinter_tkapp_interpaddr_impl(TkappObject *self)
2789 : : /*[clinic end generated code: output=6caaae3273b3c95a input=2dd32cbddb55a111]*/
2790 : : {
2791 : 0 : return PyLong_FromVoidPtr(Tkapp_Interp(self));
2792 : : }
2793 : :
2794 : : /*[clinic input]
2795 : : _tkinter.tkapp.loadtk
2796 : : [clinic start generated code]*/
2797 : :
2798 : : static PyObject *
2799 : 0 : _tkinter_tkapp_loadtk_impl(TkappObject *self)
2800 : : /*[clinic end generated code: output=e9e10a954ce46d2a input=b5e82afedd6354f0]*/
2801 : : {
2802 : 0 : Tcl_Interp *interp = Tkapp_Interp(self);
2803 : 0 : const char * _tk_exists = NULL;
2804 : : int err;
2805 : :
2806 : : #ifdef TKINTER_PROTECT_LOADTK
2807 : : /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2808 : : * first call failed.
2809 : : * To avoid the deadlock, we just refuse the second call through
2810 : : * a static variable.
2811 : : */
2812 : : if (tk_load_failed) {
2813 : : PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2814 : : return NULL;
2815 : : }
2816 : : #endif
2817 : :
2818 : : /* We want to guard against calling Tk_Init() multiple times */
2819 [ # # # # ]: 0 : CHECK_TCL_APPARTMENT;
2820 [ # # ]: 0 : ENTER_TCL
2821 : 0 : err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2822 : 0 : ENTER_OVERLAP
2823 [ # # ]: 0 : if (err == TCL_ERROR) {
2824 : : /* This sets an exception, but we cannot return right
2825 : : away because we need to exit the overlap first. */
2826 : 0 : Tkinter_Error(self);
2827 : : } else {
2828 : 0 : _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
2829 : : }
2830 [ # # ]: 0 : LEAVE_OVERLAP_TCL
2831 [ # # ]: 0 : if (err == TCL_ERROR) {
2832 : 0 : return NULL;
2833 : : }
2834 [ # # # # ]: 0 : if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2835 [ # # ]: 0 : if (Tk_Init(interp) == TCL_ERROR) {
2836 : 0 : Tkinter_Error(self);
2837 : : #ifdef TKINTER_PROTECT_LOADTK
2838 : : tk_load_failed = 1;
2839 : : #endif
2840 : 0 : return NULL;
2841 : : }
2842 : : }
2843 : 0 : Py_RETURN_NONE;
2844 : : }
2845 : :
2846 : : static PyObject *
2847 : 45 : Tkapp_WantObjects(PyObject *self, PyObject *args)
2848 : : {
2849 : :
2850 : 45 : int wantobjects = -1;
2851 [ - + ]: 45 : if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2852 : 0 : return NULL;
2853 [ + - ]: 45 : if (wantobjects == -1)
2854 : 45 : return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2855 : 0 : ((TkappObject*)self)->wantobjects = wantobjects;
2856 : :
2857 : 0 : Py_RETURN_NONE;
2858 : : }
2859 : :
2860 : : /*[clinic input]
2861 : : _tkinter.tkapp.willdispatch
2862 : :
2863 : : [clinic start generated code]*/
2864 : :
2865 : : static PyObject *
2866 : 0 : _tkinter_tkapp_willdispatch_impl(TkappObject *self)
2867 : : /*[clinic end generated code: output=0e3f46d244642155 input=d88f5970843d6dab]*/
2868 : : {
2869 : 0 : self->dispatching = 1;
2870 : :
2871 : 0 : Py_RETURN_NONE;
2872 : : }
2873 : :
2874 : :
2875 : : /**** Tkapp Type Methods ****/
2876 : :
2877 : : static void
2878 : 42 : Tkapp_Dealloc(PyObject *self)
2879 : : {
2880 : 42 : PyObject *tp = (PyObject *) Py_TYPE(self);
2881 : : /*CHECK_TCL_APPARTMENT;*/
2882 [ - + ]: 42 : ENTER_TCL
2883 : 42 : Tcl_DeleteInterp(Tkapp_Interp(self));
2884 [ - + ]: 42 : LEAVE_TCL
2885 : 42 : PyObject_Free(self);
2886 : 42 : Py_DECREF(tp);
2887 : 42 : DisableEventHook();
2888 : 42 : }
2889 : :
2890 : :
2891 : :
2892 : : /**** Tkinter Module ****/
2893 : :
2894 : : typedef struct {
2895 : : PyObject* tuple;
2896 : : Py_ssize_t size; /* current size */
2897 : : Py_ssize_t maxsize; /* allocated size */
2898 : : } FlattenContext;
2899 : :
2900 : : static int
2901 : 0 : _bump(FlattenContext* context, Py_ssize_t size)
2902 : : {
2903 : : /* expand tuple to hold (at least) size new items.
2904 : : return true if successful, false if an exception was raised */
2905 : :
2906 : 0 : Py_ssize_t maxsize = context->maxsize * 2; /* never overflows */
2907 : :
2908 [ # # ]: 0 : if (maxsize < context->size + size)
2909 : 0 : maxsize = context->size + size; /* never overflows */
2910 : :
2911 : 0 : context->maxsize = maxsize;
2912 : :
2913 : 0 : return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2914 : : }
2915 : :
2916 : : static int
2917 : 66 : _flatten1(FlattenContext* context, PyObject* item, int depth)
2918 : : {
2919 : : /* add tuple or list to argument tuple (recursively) */
2920 : :
2921 : : Py_ssize_t i, size;
2922 : :
2923 [ - + ]: 66 : if (depth > 1000) {
2924 : 0 : PyErr_SetString(PyExc_ValueError,
2925 : : "nesting too deep in _flatten");
2926 : 0 : return 0;
2927 [ + + + + ]: 66 : } else if (PyTuple_Check(item) || PyList_Check(item)) {
2928 [ + + ]: 64 : size = PySequence_Fast_GET_SIZE(item);
2929 : : /* preallocate (assume no nesting) */
2930 [ - + - - ]: 64 : if (context->size + size > context->maxsize &&
2931 : 0 : !_bump(context, size))
2932 : 0 : return 0;
2933 : : /* copy items to output tuple */
2934 [ + + ]: 209 : for (i = 0; i < size; i++) {
2935 [ + + ]: 145 : PyObject *o = PySequence_Fast_GET_ITEM(item, i);
2936 [ + - - + ]: 145 : if (PyList_Check(o) || PyTuple_Check(o)) {
2937 [ # # ]: 0 : if (!_flatten1(context, o, depth + 1))
2938 : 0 : return 0;
2939 [ + - ]: 145 : } else if (o != Py_None) {
2940 [ - + - - ]: 145 : if (context->size + 1 > context->maxsize &&
2941 : 0 : !_bump(context, 1))
2942 : 0 : return 0;
2943 : 145 : Py_INCREF(o);
2944 : 145 : PyTuple_SET_ITEM(context->tuple,
2945 : : context->size++, o);
2946 : : }
2947 : : }
2948 : : } else {
2949 : 2 : PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2950 : 2 : return 0;
2951 : : }
2952 : 64 : return 1;
2953 : : }
2954 : :
2955 : : /*[clinic input]
2956 : : _tkinter._flatten
2957 : :
2958 : : item: object
2959 : : /
2960 : :
2961 : : [clinic start generated code]*/
2962 : :
2963 : : static PyObject *
2964 : 91 : _tkinter__flatten(PyObject *module, PyObject *item)
2965 : : /*[clinic end generated code: output=cad02a3f97f29862 input=6b9c12260aa1157f]*/
2966 : : {
2967 : : FlattenContext context;
2968 : :
2969 : 91 : context.maxsize = PySequence_Size(item);
2970 [ + + ]: 91 : if (context.maxsize < 0)
2971 : 2 : return NULL;
2972 [ + + ]: 89 : if (context.maxsize == 0)
2973 : 23 : return PyTuple_New(0);
2974 : :
2975 : 66 : context.tuple = PyTuple_New(context.maxsize);
2976 [ - + ]: 66 : if (!context.tuple)
2977 : 0 : return NULL;
2978 : :
2979 : 66 : context.size = 0;
2980 : :
2981 [ + + ]: 66 : if (!_flatten1(&context, item, 0)) {
2982 : 2 : Py_XDECREF(context.tuple);
2983 : 2 : return NULL;
2984 : : }
2985 : :
2986 [ - + ]: 64 : if (_PyTuple_Resize(&context.tuple, context.size))
2987 : 0 : return NULL;
2988 : :
2989 : 64 : return context.tuple;
2990 : : }
2991 : :
2992 : : /*[clinic input]
2993 : : _tkinter.create
2994 : :
2995 : : screenName: str(accept={str, NoneType}) = None
2996 : : baseName: str = ""
2997 : : className: str = "Tk"
2998 : : interactive: bool(accept={int}) = False
2999 : : wantobjects: bool(accept={int}) = False
3000 : : wantTk: bool(accept={int}) = True
3001 : : if false, then Tk_Init() doesn't get called
3002 : : sync: bool(accept={int}) = False
3003 : : if true, then pass -sync to wish
3004 : : use: str(accept={str, NoneType}) = None
3005 : : if not None, then pass -use to wish
3006 : : /
3007 : :
3008 : : [clinic start generated code]*/
3009 : :
3010 : : static PyObject *
3011 : 42 : _tkinter_create_impl(PyObject *module, const char *screenName,
3012 : : const char *baseName, const char *className,
3013 : : int interactive, int wantobjects, int wantTk, int sync,
3014 : : const char *use)
3015 : : /*[clinic end generated code: output=e3315607648e6bb4 input=da9b17ee7358d862]*/
3016 : : {
3017 : : /* XXX baseName is not used anymore;
3018 : : * try getting rid of it. */
3019 [ - + - - ]: 42 : CHECK_STRING_LENGTH(screenName);
3020 [ + - - + ]: 42 : CHECK_STRING_LENGTH(baseName);
3021 [ + - - + ]: 42 : CHECK_STRING_LENGTH(className);
3022 [ - + - - ]: 42 : CHECK_STRING_LENGTH(use);
3023 : :
3024 : 42 : return (PyObject *) Tkapp_New(screenName, className,
3025 : : interactive, wantobjects, wantTk,
3026 : : sync, use);
3027 : : }
3028 : :
3029 : : /*[clinic input]
3030 : : _tkinter.setbusywaitinterval
3031 : :
3032 : : new_val: int
3033 : : /
3034 : :
3035 : : Set the busy-wait interval in milliseconds between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3036 : :
3037 : : It should be set to a divisor of the maximum time between frames in an animation.
3038 : : [clinic start generated code]*/
3039 : :
3040 : : static PyObject *
3041 : 0 : _tkinter_setbusywaitinterval_impl(PyObject *module, int new_val)
3042 : : /*[clinic end generated code: output=42bf7757dc2d0ab6 input=deca1d6f9e6dae47]*/
3043 : : {
3044 [ # # ]: 0 : if (new_val < 0) {
3045 : 0 : PyErr_SetString(PyExc_ValueError,
3046 : : "busywaitinterval must be >= 0");
3047 : 0 : return NULL;
3048 : : }
3049 : 0 : Tkinter_busywaitinterval = new_val;
3050 : 0 : Py_RETURN_NONE;
3051 : : }
3052 : :
3053 : : /*[clinic input]
3054 : : _tkinter.getbusywaitinterval -> int
3055 : :
3056 : : Return the current busy-wait interval between successive calls to Tcl_DoOneEvent in a threaded Python interpreter.
3057 : : [clinic start generated code]*/
3058 : :
3059 : : static int
3060 : 0 : _tkinter_getbusywaitinterval_impl(PyObject *module)
3061 : : /*[clinic end generated code: output=23b72d552001f5c7 input=a695878d2d576a84]*/
3062 : : {
3063 : 0 : return Tkinter_busywaitinterval;
3064 : : }
3065 : :
3066 : : #include "clinic/_tkinter.c.h"
3067 : :
3068 : : static PyMethodDef Tktt_methods[] =
3069 : : {
3070 : : _TKINTER_TKTIMERTOKEN_DELETETIMERHANDLER_METHODDEF
3071 : : {NULL, NULL}
3072 : : };
3073 : :
3074 : : static PyType_Slot Tktt_Type_slots[] = {
3075 : : {Py_tp_dealloc, Tktt_Dealloc},
3076 : : {Py_tp_repr, Tktt_Repr},
3077 : : {Py_tp_methods, Tktt_methods},
3078 : : {0, 0}
3079 : : };
3080 : :
3081 : : static PyType_Spec Tktt_Type_spec = {
3082 : : "_tkinter.tktimertoken",
3083 : : sizeof(TkttObject),
3084 : : 0,
3085 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3086 : : Tktt_Type_slots,
3087 : : };
3088 : :
3089 : :
3090 : : /**** Tkapp Method List ****/
3091 : :
3092 : : static PyMethodDef Tkapp_methods[] =
3093 : : {
3094 : : _TKINTER_TKAPP_WILLDISPATCH_METHODDEF
3095 : : {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3096 : : {"call", Tkapp_Call, METH_VARARGS},
3097 : : _TKINTER_TKAPP_EVAL_METHODDEF
3098 : : _TKINTER_TKAPP_EVALFILE_METHODDEF
3099 : : _TKINTER_TKAPP_RECORD_METHODDEF
3100 : : _TKINTER_TKAPP_ADDERRORINFO_METHODDEF
3101 : : {"setvar", Tkapp_SetVar, METH_VARARGS},
3102 : : {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3103 : : {"getvar", Tkapp_GetVar, METH_VARARGS},
3104 : : {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3105 : : {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3106 : : {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3107 : : _TKINTER_TKAPP_GETINT_METHODDEF
3108 : : _TKINTER_TKAPP_GETDOUBLE_METHODDEF
3109 : : _TKINTER_TKAPP_GETBOOLEAN_METHODDEF
3110 : : _TKINTER_TKAPP_EXPRSTRING_METHODDEF
3111 : : _TKINTER_TKAPP_EXPRLONG_METHODDEF
3112 : : _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF
3113 : : _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF
3114 : : _TKINTER_TKAPP_SPLITLIST_METHODDEF
3115 : : _TKINTER_TKAPP_CREATECOMMAND_METHODDEF
3116 : : _TKINTER_TKAPP_DELETECOMMAND_METHODDEF
3117 : : _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF
3118 : : _TKINTER_TKAPP_DELETEFILEHANDLER_METHODDEF
3119 : : _TKINTER_TKAPP_CREATETIMERHANDLER_METHODDEF
3120 : : _TKINTER_TKAPP_MAINLOOP_METHODDEF
3121 : : _TKINTER_TKAPP_DOONEEVENT_METHODDEF
3122 : : _TKINTER_TKAPP_QUIT_METHODDEF
3123 : : _TKINTER_TKAPP_INTERPADDR_METHODDEF
3124 : : _TKINTER_TKAPP_LOADTK_METHODDEF
3125 : : {NULL, NULL}
3126 : : };
3127 : :
3128 : : static PyType_Slot Tkapp_Type_slots[] = {
3129 : : {Py_tp_dealloc, Tkapp_Dealloc},
3130 : : {Py_tp_methods, Tkapp_methods},
3131 : : {0, 0}
3132 : : };
3133 : :
3134 : :
3135 : : static PyType_Spec Tkapp_Type_spec = {
3136 : : "_tkinter.tkapp",
3137 : : sizeof(TkappObject),
3138 : : 0,
3139 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
3140 : : Tkapp_Type_slots,
3141 : : };
3142 : :
3143 : : static PyMethodDef moduleMethods[] =
3144 : : {
3145 : : _TKINTER__FLATTEN_METHODDEF
3146 : : _TKINTER_CREATE_METHODDEF
3147 : : _TKINTER_SETBUSYWAITINTERVAL_METHODDEF
3148 : : _TKINTER_GETBUSYWAITINTERVAL_METHODDEF
3149 : : {NULL, NULL}
3150 : : };
3151 : :
3152 : : #ifdef WAIT_FOR_STDIN
3153 : :
3154 : : static int stdin_ready = 0;
3155 : :
3156 : : #ifndef MS_WINDOWS
3157 : : static void
3158 : 0 : MyFileProc(void *clientData, int mask)
3159 : : {
3160 : 0 : stdin_ready = 1;
3161 : 0 : }
3162 : : #endif
3163 : :
3164 : : static PyThreadState *event_tstate = NULL;
3165 : :
3166 : : static int
3167 : 0 : EventHook(void)
3168 : : {
3169 : : #ifndef MS_WINDOWS
3170 : : int tfile;
3171 : : #endif
3172 : 0 : PyEval_RestoreThread(event_tstate);
3173 : 0 : stdin_ready = 0;
3174 : 0 : errorInCmd = 0;
3175 : : #ifndef MS_WINDOWS
3176 : 0 : tfile = fileno(stdin);
3177 : 0 : Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3178 : : #endif
3179 [ # # # # ]: 0 : while (!errorInCmd && !stdin_ready) {
3180 : : int result;
3181 : : #ifdef MS_WINDOWS
3182 : : if (_kbhit()) {
3183 : : stdin_ready = 1;
3184 : : break;
3185 : : }
3186 : : #endif
3187 : 0 : Py_BEGIN_ALLOW_THREADS
3188 [ # # ]: 0 : if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3189 : 0 : tcl_tstate = event_tstate;
3190 : :
3191 : 0 : result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3192 : :
3193 : 0 : tcl_tstate = NULL;
3194 [ # # ]: 0 : if(tcl_lock)PyThread_release_lock(tcl_lock);
3195 [ # # ]: 0 : if (result == 0)
3196 : 0 : Sleep(Tkinter_busywaitinterval);
3197 : 0 : Py_END_ALLOW_THREADS
3198 : :
3199 [ # # ]: 0 : if (result < 0)
3200 : 0 : break;
3201 : : }
3202 : : #ifndef MS_WINDOWS
3203 : 0 : Tcl_DeleteFileHandler(tfile);
3204 : : #endif
3205 [ # # ]: 0 : if (errorInCmd) {
3206 : 0 : errorInCmd = 0;
3207 : 0 : PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3208 : 0 : excInCmd = valInCmd = trbInCmd = NULL;
3209 : 0 : PyErr_Print();
3210 : : }
3211 : 0 : PyEval_SaveThread();
3212 : 0 : return 0;
3213 : : }
3214 : :
3215 : : #endif
3216 : :
3217 : : static void
3218 : 42 : EnableEventHook(void)
3219 : : {
3220 : : #ifdef WAIT_FOR_STDIN
3221 [ + + ]: 42 : if (PyOS_InputHook == NULL) {
3222 : 38 : event_tstate = PyThreadState_Get();
3223 : 38 : PyOS_InputHook = EventHook;
3224 : : }
3225 : : #endif
3226 : 42 : }
3227 : :
3228 : : static void
3229 : 42 : DisableEventHook(void)
3230 : : {
3231 : : #ifdef WAIT_FOR_STDIN
3232 [ + - + + ]: 42 : if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3233 : 38 : PyOS_InputHook = NULL;
3234 : : }
3235 : : #endif
3236 : 42 : }
3237 : :
3238 : :
3239 : : static struct PyModuleDef _tkintermodule = {
3240 : : PyModuleDef_HEAD_INIT,
3241 : : "_tkinter",
3242 : : NULL,
3243 : : -1,
3244 : : moduleMethods,
3245 : : NULL,
3246 : : NULL,
3247 : : NULL,
3248 : : NULL
3249 : : };
3250 : :
3251 : : PyMODINIT_FUNC
3252 : 10 : PyInit__tkinter(void)
3253 : : {
3254 : : PyObject *m, *uexe, *cexe, *o;
3255 : :
3256 : 10 : tcl_lock = PyThread_allocate_lock();
3257 [ - + ]: 10 : if (tcl_lock == NULL)
3258 : 0 : return NULL;
3259 : :
3260 : 10 : m = PyModule_Create(&_tkintermodule);
3261 [ - + ]: 10 : if (m == NULL)
3262 : 0 : return NULL;
3263 : :
3264 : 10 : o = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3265 [ - + ]: 10 : if (o == NULL) {
3266 : 0 : Py_DECREF(m);
3267 : 0 : return NULL;
3268 : : }
3269 : 10 : Py_INCREF(o);
3270 [ - + ]: 10 : if (PyModule_AddObject(m, "TclError", o)) {
3271 : 0 : Py_DECREF(o);
3272 : 0 : Py_DECREF(m);
3273 : 0 : return NULL;
3274 : : }
3275 : 10 : Tkinter_TclError = o;
3276 : :
3277 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "READABLE", TCL_READABLE)) {
3278 : 0 : Py_DECREF(m);
3279 : 0 : return NULL;
3280 : : }
3281 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "WRITABLE", TCL_WRITABLE)) {
3282 : 0 : Py_DECREF(m);
3283 : 0 : return NULL;
3284 : : }
3285 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "EXCEPTION", TCL_EXCEPTION)) {
3286 : 0 : Py_DECREF(m);
3287 : 0 : return NULL;
3288 : : }
3289 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "WINDOW_EVENTS", TCL_WINDOW_EVENTS)) {
3290 : 0 : Py_DECREF(m);
3291 : 0 : return NULL;
3292 : : }
3293 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "FILE_EVENTS", TCL_FILE_EVENTS)) {
3294 : 0 : Py_DECREF(m);
3295 : 0 : return NULL;
3296 : : }
3297 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "TIMER_EVENTS", TCL_TIMER_EVENTS)) {
3298 : 0 : Py_DECREF(m);
3299 : 0 : return NULL;
3300 : : }
3301 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "IDLE_EVENTS", TCL_IDLE_EVENTS)) {
3302 : 0 : Py_DECREF(m);
3303 : 0 : return NULL;
3304 : : }
3305 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "ALL_EVENTS", TCL_ALL_EVENTS)) {
3306 : 0 : Py_DECREF(m);
3307 : 0 : return NULL;
3308 : : }
3309 [ - + ]: 10 : if (PyModule_AddIntConstant(m, "DONT_WAIT", TCL_DONT_WAIT)) {
3310 : 0 : Py_DECREF(m);
3311 : 0 : return NULL;
3312 : : }
3313 [ - + ]: 10 : if (PyModule_AddStringConstant(m, "TK_VERSION", TK_VERSION)) {
3314 : 0 : Py_DECREF(m);
3315 : 0 : return NULL;
3316 : : }
3317 [ - + ]: 10 : if (PyModule_AddStringConstant(m, "TCL_VERSION", TCL_VERSION)) {
3318 : 0 : Py_DECREF(m);
3319 : 0 : return NULL;
3320 : : }
3321 : :
3322 : 10 : o = PyType_FromSpec(&Tkapp_Type_spec);
3323 [ - + ]: 10 : if (o == NULL) {
3324 : 0 : Py_DECREF(m);
3325 : 0 : return NULL;
3326 : : }
3327 [ - + ]: 10 : if (PyModule_AddObject(m, "TkappType", o)) {
3328 : 0 : Py_DECREF(o);
3329 : 0 : Py_DECREF(m);
3330 : 0 : return NULL;
3331 : : }
3332 : 10 : Tkapp_Type = o;
3333 : :
3334 : 10 : o = PyType_FromSpec(&Tktt_Type_spec);
3335 [ - + ]: 10 : if (o == NULL) {
3336 : 0 : Py_DECREF(m);
3337 : 0 : return NULL;
3338 : : }
3339 [ - + ]: 10 : if (PyModule_AddObject(m, "TkttType", o)) {
3340 : 0 : Py_DECREF(o);
3341 : 0 : Py_DECREF(m);
3342 : 0 : return NULL;
3343 : : }
3344 : 10 : Tktt_Type = o;
3345 : :
3346 : 10 : o = PyType_FromSpec(&PyTclObject_Type_spec);
3347 [ - + ]: 10 : if (o == NULL) {
3348 : 0 : Py_DECREF(m);
3349 : 0 : return NULL;
3350 : : }
3351 [ - + ]: 10 : if (PyModule_AddObject(m, "Tcl_Obj", o)) {
3352 : 0 : Py_DECREF(o);
3353 : 0 : Py_DECREF(m);
3354 : 0 : return NULL;
3355 : : }
3356 : 10 : PyTclObject_Type = o;
3357 : :
3358 : : #ifdef TK_AQUA
3359 : : /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3360 : : * start waking up. Note that Tcl_FindExecutable will do this, this
3361 : : * code must be above it! The original warning from
3362 : : * tkMacOSXAppInit.c is copied below.
3363 : : *
3364 : : * NB - You have to swap in the Tk Notifier BEFORE you start up the
3365 : : * Tcl interpreter for now. It probably should work to do this
3366 : : * in the other order, but for now it doesn't seem to.
3367 : : *
3368 : : */
3369 : : Tk_MacOSXSetupTkNotifier();
3370 : : #endif
3371 : :
3372 : :
3373 : : /* This helps the dynamic loader; in Unicode aware Tcl versions
3374 : : it also helps Tcl find its encodings. */
3375 : 10 : uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3376 [ + - ]: 10 : if (uexe) {
3377 : 10 : cexe = PyUnicode_EncodeFSDefault(uexe);
3378 [ + - ]: 10 : if (cexe) {
3379 : : #ifdef MS_WINDOWS
3380 : : int set_var = 0;
3381 : : PyObject *str_path;
3382 : : wchar_t *wcs_path;
3383 : : DWORD ret;
3384 : :
3385 : : ret = GetEnvironmentVariableW(L"TCL_LIBRARY", NULL, 0);
3386 : :
3387 : : if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
3388 : : str_path = _get_tcl_lib_path();
3389 : : if (str_path == NULL && PyErr_Occurred()) {
3390 : : Py_DECREF(m);
3391 : : return NULL;
3392 : : }
3393 : : if (str_path != NULL) {
3394 : : wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
3395 : : if (wcs_path == NULL) {
3396 : : Py_DECREF(m);
3397 : : return NULL;
3398 : : }
3399 : : SetEnvironmentVariableW(L"TCL_LIBRARY", wcs_path);
3400 : : set_var = 1;
3401 : : }
3402 : : }
3403 : :
3404 : : Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
3405 : :
3406 : : if (set_var) {
3407 : : SetEnvironmentVariableW(L"TCL_LIBRARY", NULL);
3408 : : PyMem_Free(wcs_path);
3409 : : }
3410 : : #else
3411 : 10 : Tcl_FindExecutable(PyBytes_AS_STRING(cexe));
3412 : : #endif /* MS_WINDOWS */
3413 : : }
3414 : 10 : Py_XDECREF(cexe);
3415 : 10 : Py_DECREF(uexe);
3416 : : }
3417 : :
3418 [ - + ]: 10 : if (PyErr_Occurred()) {
3419 : 0 : Py_DECREF(m);
3420 : 0 : return NULL;
3421 : : }
3422 : :
3423 : 10 : return m;
3424 : : }
|