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