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