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