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