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