Python-2.7.3/Modules/_tkinter.c

No issues found

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