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