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