602
602
static TkappObject *
603
603
Tkapp_New(char *screenName, char *className,
604
int interactive, int wantobjects, int wantTk, int sync, char *use)
604
int interactive, int wantobjects, int wantTk, int sync, char *use)
609
v = PyObject_New(TkappObject, &Tkapp_Type);
613
v->interp = Tcl_CreateInterp();
614
v->wantobjects = wantobjects;
615
v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
616
TCL_GLOBAL_ONLY) != NULL;
617
v->thread_id = Tcl_GetCurrentThread();
609
v = PyObject_New(TkappObject, &Tkapp_Type);
613
v->interp = Tcl_CreateInterp();
614
v->wantobjects = wantobjects;
615
v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
616
TCL_GLOBAL_ONLY) != NULL;
617
v->thread_id = Tcl_GetCurrentThread();
620
620
#ifndef TCL_THREADS
622
PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
622
PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
627
627
#ifdef WITH_THREAD
628
if (v->threaded && tcl_lock) {
629
/* If Tcl is threaded, we don't need the lock. */
630
PyThread_free_lock(tcl_lock);
635
v->BooleanType = Tcl_GetObjType("boolean");
636
v->ByteArrayType = Tcl_GetObjType("bytearray");
637
v->DoubleType = Tcl_GetObjType("double");
638
v->IntType = Tcl_GetObjType("int");
639
v->ListType = Tcl_GetObjType("list");
640
v->ProcBodyType = Tcl_GetObjType("procbody");
641
v->StringType = Tcl_GetObjType("string");
643
/* Delete the 'exit' command, which can screw things up */
644
Tcl_DeleteCommand(v->interp, "exit");
646
if (screenName != NULL)
647
Tcl_SetVar2(v->interp, "env", "DISPLAY",
648
screenName, TCL_GLOBAL_ONLY);
651
Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
653
Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
655
/* This is used to get the application class for Tk 4.1 and up */
656
argv0 = (char*)ckalloc(strlen(className) + 1);
663
strcpy(argv0, className);
664
if (isupper(Py_CHARMASK(argv0[0])))
665
argv0[0] = tolower(Py_CHARMASK(argv0[0]));
666
Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
670
Tcl_SetVar(v->interp,
671
"_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
673
#ifdef TKINTER_PROTECT_LOADTK
674
else if (tk_load_failed) {
675
Tcl_SetVar(v->interp,
676
"_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
680
/* some initial arguments need to be in argv */
686
len += sizeof "-sync";
688
len += strlen(use) + sizeof "-use ";
690
args = (char*)ckalloc(len);
699
strcat(args, "-sync");
703
strcat(args, "-use ");
707
Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
711
if (Tcl_AppInit(v->interp) != TCL_OK) {
712
PyObject *result = Tkinter_Error((PyObject *)v);
713
#ifdef TKINTER_PROTECT_LOADTK
715
const char *_tkinter_tk_failed;
716
_tkinter_tk_failed = Tcl_GetVar(v->interp,
717
"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
719
if ( _tkinter_tk_failed != NULL &&
720
strcmp(_tkinter_tk_failed, "1") == 0) {
725
Py_DECREF((PyObject *)v);
726
return (TkappObject *)result;
628
if (v->threaded && tcl_lock) {
629
/* If Tcl is threaded, we don't need the lock. */
630
PyThread_free_lock(tcl_lock);
635
v->BooleanType = Tcl_GetObjType("boolean");
636
v->ByteArrayType = Tcl_GetObjType("bytearray");
637
v->DoubleType = Tcl_GetObjType("double");
638
v->IntType = Tcl_GetObjType("int");
639
v->ListType = Tcl_GetObjType("list");
640
v->ProcBodyType = Tcl_GetObjType("procbody");
641
v->StringType = Tcl_GetObjType("string");
643
/* Delete the 'exit' command, which can screw things up */
644
Tcl_DeleteCommand(v->interp, "exit");
646
if (screenName != NULL)
647
Tcl_SetVar2(v->interp, "env", "DISPLAY",
648
screenName, TCL_GLOBAL_ONLY);
651
Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
653
Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
655
/* This is used to get the application class for Tk 4.1 and up */
656
argv0 = (char*)ckalloc(strlen(className) + 1);
663
strcpy(argv0, className);
664
if (isupper(Py_CHARMASK(argv0[0])))
665
argv0[0] = tolower(Py_CHARMASK(argv0[0]));
666
Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
670
Tcl_SetVar(v->interp,
671
"_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
673
#ifdef TKINTER_PROTECT_LOADTK
674
else if (tk_load_failed) {
675
Tcl_SetVar(v->interp,
676
"_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
680
/* some initial arguments need to be in argv */
686
len += sizeof "-sync";
688
len += strlen(use) + sizeof "-use ";
690
args = (char*)ckalloc(len);
699
strcat(args, "-sync");
703
strcat(args, "-use ");
707
Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
711
if (Tcl_AppInit(v->interp) != TCL_OK) {
712
PyObject *result = Tkinter_Error((PyObject *)v);
713
#ifdef TKINTER_PROTECT_LOADTK
715
const char *_tkinter_tk_failed;
716
_tkinter_tk_failed = Tcl_GetVar(v->interp,
717
"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
719
if ( _tkinter_tk_failed != NULL &&
720
strcmp(_tkinter_tk_failed, "1") == 0) {
725
Py_DECREF((PyObject *)v);
726
return (TkappObject *)result;
735
735
#ifdef WITH_THREAD
737
737
Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
738
Tcl_Condition *cond, Tcl_Mutex *mutex)
738
Tcl_Condition *cond, Tcl_Mutex *mutex)
740
Py_BEGIN_ALLOW_THREADS;
741
Tcl_MutexLock(mutex);
742
Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
743
Tcl_ThreadAlert(self->thread_id);
744
Tcl_ConditionWait(cond, mutex, NULL);
745
Tcl_MutexUnlock(mutex);
740
Py_BEGIN_ALLOW_THREADS;
741
Tcl_MutexLock(mutex);
742
Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
743
Tcl_ThreadAlert(self->thread_id);
744
Tcl_ConditionWait(cond, mutex, NULL);
745
Tcl_MutexUnlock(mutex);
756
PyObject *string; /* This cannot cause cycles. */
756
PyObject *string; /* This cannot cause cycles. */
759
759
static PyTypeObject PyTclObject_Type;
760
#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
760
#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
762
762
static PyObject *
763
763
newPyTclObject(Tcl_Obj *arg)
766
self = PyObject_New(PyTclObject, &PyTclObject_Type);
769
Tcl_IncrRefCount(arg);
772
return (PyObject*)self;
766
self = PyObject_New(PyTclObject, &PyTclObject_Type);
769
Tcl_IncrRefCount(arg);
772
return (PyObject*)self;
776
776
PyTclObject_dealloc(PyTclObject *self)
778
Tcl_DecrRefCount(self->value);
779
Py_XDECREF(self->string);
778
Tcl_DecrRefCount(self->value);
779
Py_XDECREF(self->string);
784
784
PyTclObject_TclString(PyObject *self)
786
return Tcl_GetString(((PyTclObject*)self)->value);
786
return Tcl_GetString(((PyTclObject*)self)->value);
789
789
/* Like _str, but create Unicode if necessary. */
887
887
get_typename(PyTclObject* obj, void* ignored)
889
return PyUnicode_FromString(obj->value->typePtr->name);
889
return PyUnicode_FromString(obj->value->typePtr->name);
893
893
static PyGetSetDef PyTclObject_getsetlist[] = {
894
{"typename", (getter)get_typename, NULL, get_typename__doc__},
895
{"string", (getter)PyTclObject_string, NULL,
896
PyTclObject_string__doc__},
894
{"typename", (getter)get_typename, NULL, get_typename__doc__},
895
{"string", (getter)PyTclObject_string, NULL,
896
PyTclObject_string__doc__},
900
900
static PyTypeObject PyTclObject_Type = {
901
PyVarObject_HEAD_INIT(NULL, 0)
902
"_tkinter.Tcl_Obj", /*tp_name*/
903
sizeof(PyTclObject), /*tp_basicsize*/
906
(destructor)PyTclObject_dealloc,/*tp_dealloc*/
911
(reprfunc)PyTclObject_repr, /*tp_repr*/
913
0, /*tp_as_sequence*/
917
(reprfunc)PyTclObject_str, /*tp_str*/
918
PyObject_GenericGetAttr, /*tp_getattro*/
921
Py_TPFLAGS_DEFAULT, /*tp_flags*/
925
PyTclObject_richcompare, /*tp_richcompare*/
926
0, /*tp_weaklistoffset*/
931
PyTclObject_getsetlist, /*tp_getset*/
901
PyVarObject_HEAD_INIT(NULL, 0)
902
"_tkinter.Tcl_Obj", /*tp_name*/
903
sizeof(PyTclObject), /*tp_basicsize*/
906
(destructor)PyTclObject_dealloc,/*tp_dealloc*/
911
(reprfunc)PyTclObject_repr, /*tp_repr*/
913
0, /*tp_as_sequence*/
917
(reprfunc)PyTclObject_str, /*tp_str*/
918
PyObject_GenericGetAttr, /*tp_getattro*/
921
Py_TPFLAGS_DEFAULT, /*tp_flags*/
925
PyTclObject_richcompare, /*tp_richcompare*/
926
0, /*tp_weaklistoffset*/
931
PyTclObject_getsetlist, /*tp_getset*/
945
945
AsObj(PyObject *value)
951
if (PyBytes_Check(value))
952
return Tcl_NewStringObj(PyBytes_AS_STRING(value),
953
PyBytes_GET_SIZE(value));
954
else if (PyBool_Check(value))
955
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
956
else if (PyLong_CheckExact(value) &&
957
((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
959
/* If there is an overflow in the long conversion,
960
fall through to default object handling. */
961
return Tcl_NewLongObj(longVal);
963
else if (PyFloat_Check(value))
964
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
965
else if (PyTuple_Check(value)) {
966
Tcl_Obj **argv = (Tcl_Obj**)
967
ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
971
for(i=0;i<PyTuple_Size(value);i++)
972
argv[i] = AsObj(PyTuple_GetItem(value,i));
973
result = Tcl_NewListObj(PyTuple_Size(value), argv);
974
ckfree(FREECAST argv);
977
else if (PyUnicode_Check(value)) {
978
Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
979
Py_ssize_t size = PyUnicode_GET_SIZE(value);
980
/* This #ifdef assumes that Tcl uses UCS-2.
981
See TCL_UTF_MAX test above. */
951
if (PyBytes_Check(value))
952
return Tcl_NewStringObj(PyBytes_AS_STRING(value),
953
PyBytes_GET_SIZE(value));
954
else if (PyBool_Check(value))
955
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
956
else if (PyLong_CheckExact(value) &&
957
((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
959
/* If there is an overflow in the long conversion,
960
fall through to default object handling. */
961
return Tcl_NewLongObj(longVal);
963
else if (PyFloat_Check(value))
964
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
965
else if (PyTuple_Check(value)) {
966
Tcl_Obj **argv = (Tcl_Obj**)
967
ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
971
for(i=0;i<PyTuple_Size(value);i++)
972
argv[i] = AsObj(PyTuple_GetItem(value,i));
973
result = Tcl_NewListObj(PyTuple_Size(value), argv);
974
ckfree(FREECAST argv);
977
else if (PyUnicode_Check(value)) {
978
Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
979
Py_ssize_t size = PyUnicode_GET_SIZE(value);
980
/* This #ifdef assumes that Tcl uses UCS-2.
981
See TCL_UTF_MAX test above. */
982
982
#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
983
Tcl_UniChar *outbuf = NULL;
985
size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
986
if (allocsize >= size)
987
outbuf = (Tcl_UniChar*)ckalloc(allocsize);
988
/* Else overflow occurred, and we take the next exit */
993
for (i = 0; i < size; i++) {
994
if (inbuf[i] >= 0x10000) {
995
/* Tcl doesn't do UTF-16, yet. */
996
PyErr_SetString(PyExc_ValueError,
997
"unsupported character");
998
ckfree(FREECAST outbuf);
1001
outbuf[i] = inbuf[i];
1003
result = Tcl_NewUnicodeObj(outbuf, size);
1004
ckfree(FREECAST outbuf);
983
Tcl_UniChar *outbuf = NULL;
985
size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
986
if (allocsize >= size)
987
outbuf = (Tcl_UniChar*)ckalloc(allocsize);
988
/* Else overflow occurred, and we take the next exit */
993
for (i = 0; i < size; i++) {
994
if (inbuf[i] >= 0x10000) {
995
/* Tcl doesn't do UTF-16, yet. */
996
PyErr_SetString(PyExc_ValueError,
997
"unsupported character");
998
ckfree(FREECAST outbuf);
1001
outbuf[i] = inbuf[i];
1003
result = Tcl_NewUnicodeObj(outbuf, size);
1004
ckfree(FREECAST outbuf);
1007
return Tcl_NewUnicodeObj(inbuf, size);
1007
return Tcl_NewUnicodeObj(inbuf, size);
1011
else if(PyTclObject_Check(value)) {
1012
Tcl_Obj *v = ((PyTclObject*)value)->value;
1013
Tcl_IncrRefCount(v);
1017
PyObject *v = PyObject_Str(value);
1011
else if(PyTclObject_Check(value)) {
1012
Tcl_Obj *v = ((PyTclObject*)value)->value;
1013
Tcl_IncrRefCount(v);
1017
PyObject *v = PyObject_Str(value);
1026
1026
static PyObject*
1027
1027
FromObj(PyObject* tkapp, Tcl_Obj *value)
1029
PyObject *result = NULL;
1030
TkappObject *app = (TkappObject*)tkapp;
1032
if (value->typePtr == NULL) {
1033
return PyUnicode_FromStringAndSize(value->bytes,
1037
if (value->typePtr == app->BooleanType) {
1038
result = value->internalRep.longValue ? Py_True : Py_False;
1043
if (value->typePtr == app->ByteArrayType) {
1045
char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1046
return PyBytes_FromStringAndSize(data, size);
1049
if (value->typePtr == app->DoubleType) {
1050
return PyFloat_FromDouble(value->internalRep.doubleValue);
1053
if (value->typePtr == app->IntType) {
1054
return PyLong_FromLong(value->internalRep.longValue);
1057
if (value->typePtr == app->ListType) {
1063
status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1064
if (status == TCL_ERROR)
1065
return Tkinter_Error(tkapp);
1066
result = PyTuple_New(size);
1069
for (i = 0; i < size; i++) {
1070
status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1071
value, i, &tcl_elem);
1072
if (status == TCL_ERROR) {
1074
return Tkinter_Error(tkapp);
1076
elem = FromObj(tkapp, tcl_elem);
1081
PyTuple_SetItem(result, i, elem);
1086
if (value->typePtr == app->ProcBodyType) {
1087
/* fall through: return tcl object. */
1090
if (value->typePtr == app->StringType) {
1029
PyObject *result = NULL;
1030
TkappObject *app = (TkappObject*)tkapp;
1032
if (value->typePtr == NULL) {
1033
return PyUnicode_FromStringAndSize(value->bytes,
1037
if (value->typePtr == app->BooleanType) {
1038
result = value->internalRep.longValue ? Py_True : Py_False;
1043
if (value->typePtr == app->ByteArrayType) {
1045
char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1046
return PyBytes_FromStringAndSize(data, size);
1049
if (value->typePtr == app->DoubleType) {
1050
return PyFloat_FromDouble(value->internalRep.doubleValue);
1053
if (value->typePtr == app->IntType) {
1054
return PyLong_FromLong(value->internalRep.longValue);
1057
if (value->typePtr == app->ListType) {
1063
status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1064
if (status == TCL_ERROR)
1065
return Tkinter_Error(tkapp);
1066
result = PyTuple_New(size);
1069
for (i = 0; i < size; i++) {
1070
status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1071
value, i, &tcl_elem);
1072
if (status == TCL_ERROR) {
1074
return Tkinter_Error(tkapp);
1076
elem = FromObj(tkapp, tcl_elem);
1081
PyTuple_SetItem(result, i, elem);
1086
if (value->typePtr == app->ProcBodyType) {
1087
/* fall through: return tcl object. */
1090
if (value->typePtr == app->StringType) {
1091
1091
#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1097
size = Tcl_GetCharLength(value);
1098
result = PyUnicode_FromUnicode(NULL, size);
1101
input = Tcl_GetUnicode(value);
1102
output = PyUnicode_AS_UNICODE(result);
1104
*output++ = *input++;
1097
size = Tcl_GetCharLength(value);
1098
result = PyUnicode_FromUnicode(NULL, size);
1101
input = Tcl_GetUnicode(value);
1102
output = PyUnicode_AS_UNICODE(result);
1104
*output++ = *input++;
1107
return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1108
Tcl_GetCharLength(value));
1107
return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1108
Tcl_GetCharLength(value));
1112
return newPyTclObject(value);
1112
return newPyTclObject(value);
1115
1115
#ifdef WITH_THREAD
1276
1276
static PyObject *
1277
1277
Tkapp_Call(PyObject *selfptr, PyObject *args)
1279
Tcl_Obj *objStore[ARGSZ];
1280
Tcl_Obj **objv = NULL;
1282
PyObject *res = NULL;
1283
TkappObject *self = (TkappObject*)selfptr;
1284
int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1279
Tcl_Obj *objStore[ARGSZ];
1280
Tcl_Obj **objv = NULL;
1282
PyObject *res = NULL;
1283
TkappObject *self = (TkappObject*)selfptr;
1284
int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1286
/* If args is a single tuple, replace with contents of tuple */
1287
if (1 == PyTuple_Size(args)){
1288
PyObject* item = PyTuple_GetItem(args, 0);
1289
if (PyTuple_Check(item))
1286
/* If args is a single tuple, replace with contents of tuple */
1287
if (1 == PyTuple_Size(args)){
1288
PyObject* item = PyTuple_GetItem(args, 0);
1289
if (PyTuple_Check(item))
1292
1292
#ifdef WITH_THREAD
1293
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1294
/* We cannot call the command directly. Instead, we must
1295
marshal the parameters to the interpreter thread. */
1296
Tkapp_CallEvent *ev;
1297
Tcl_Condition cond = NULL;
1298
PyObject *exc_type, *exc_value, *exc_tb;
1299
if (!WaitForMainloop(self))
1301
ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1302
ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1306
ev->exc_type = &exc_type;
1307
ev->exc_value = &exc_value;
1308
ev->exc_tb = &exc_tb;
1311
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1315
PyErr_Restore(exc_type, exc_value, exc_tb);
1317
PyErr_SetObject(Tkinter_TclError, exc_value);
1319
Tcl_ConditionFinalize(&cond);
1293
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1294
/* We cannot call the command directly. Instead, we must
1295
marshal the parameters to the interpreter thread. */
1296
Tkapp_CallEvent *ev;
1297
Tcl_Condition cond = NULL;
1298
PyObject *exc_type, *exc_value, *exc_tb;
1299
if (!WaitForMainloop(self))
1301
ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1302
ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1306
ev->exc_type = &exc_type;
1307
ev->exc_value = &exc_value;
1308
ev->exc_tb = &exc_tb;
1311
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1315
PyErr_Restore(exc_type, exc_value, exc_tb);
1317
PyErr_SetObject(Tkinter_TclError, exc_value);
1319
Tcl_ConditionFinalize(&cond);
1325
objv = Tkapp_CallArgs(args, objStore, &objc);
1331
i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1336
Tkinter_Error(selfptr);
1338
res = Tkapp_CallResult(self);
1342
Tkapp_CallDeallocArgs(objv, objStore, objc);
1325
objv = Tkapp_CallArgs(args, objStore, &objc);
1331
i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1336
Tkinter_Error(selfptr);
1338
res = Tkapp_CallResult(self);
1342
Tkapp_CallDeallocArgs(objv, objStore, objc);
1348
1348
static PyObject *
1349
1349
Tkapp_GlobalCall(PyObject *self, PyObject *args)
1351
/* Could do the same here as for Tkapp_Call(), but this is not used
1352
much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353
way for the user to do what all its Global* variants do (save and
1354
reset the scope pointer, call the local version, restore the saved
1358
PyObject *res = NULL;
1360
CHECK_TCL_APPARTMENT;
1366
err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1368
if (err == TCL_ERROR)
1369
res = Tkinter_Error(self);
1371
res = PyUnicode_FromString(Tkapp_Result(self));
1351
/* Could do the same here as for Tkapp_Call(), but this is not used
1352
much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353
way for the user to do what all its Global* variants do (save and
1354
reset the scope pointer, call the local version, restore the saved
1358
PyObject *res = NULL;
1360
CHECK_TCL_APPARTMENT;
1366
err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1368
if (err == TCL_ERROR)
1369
res = Tkinter_Error(self);
1371
res = PyUnicode_FromString(Tkapp_Result(self));
1379
1379
static PyObject *
1380
1380
Tkapp_Eval(PyObject *self, PyObject *args)
1383
PyObject *res = NULL;
1386
if (!PyArg_ParseTuple(args, "s:eval", &script))
1389
CHECK_TCL_APPARTMENT;
1392
err = Tcl_Eval(Tkapp_Interp(self), script);
1394
if (err == TCL_ERROR)
1395
res = Tkinter_Error(self);
1397
res = PyUnicode_FromString(Tkapp_Result(self));
1383
PyObject *res = NULL;
1386
if (!PyArg_ParseTuple(args, "s:eval", &script))
1389
CHECK_TCL_APPARTMENT;
1392
err = Tcl_Eval(Tkapp_Interp(self), script);
1394
if (err == TCL_ERROR)
1395
res = Tkinter_Error(self);
1397
res = PyUnicode_FromString(Tkapp_Result(self));
1402
1402
static PyObject *
1403
1403
Tkapp_GlobalEval(PyObject *self, PyObject *args)
1406
PyObject *res = NULL;
1409
if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1412
CHECK_TCL_APPARTMENT;
1415
err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1417
if (err == TCL_ERROR)
1418
res = Tkinter_Error(self);
1420
res = PyUnicode_FromString(Tkapp_Result(self));
1406
PyObject *res = NULL;
1409
if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1412
CHECK_TCL_APPARTMENT;
1415
err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1417
if (err == TCL_ERROR)
1418
res = Tkinter_Error(self);
1420
res = PyUnicode_FromString(Tkapp_Result(self));
1425
1425
static PyObject *
1426
1426
Tkapp_EvalFile(PyObject *self, PyObject *args)
1429
PyObject *res = NULL;
1432
if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1435
CHECK_TCL_APPARTMENT;
1438
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1440
if (err == TCL_ERROR)
1441
res = Tkinter_Error(self);
1444
res = PyUnicode_FromString(Tkapp_Result(self));
1429
PyObject *res = NULL;
1432
if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1435
CHECK_TCL_APPARTMENT;
1438
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1440
if (err == TCL_ERROR)
1441
res = Tkinter_Error(self);
1444
res = PyUnicode_FromString(Tkapp_Result(self));
1449
1449
static PyObject *
1450
1450
Tkapp_Record(PyObject *self, PyObject *args)
1453
PyObject *res = NULL;
1456
if (!PyArg_ParseTuple(args, "s", &script))
1459
CHECK_TCL_APPARTMENT;
1462
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1464
if (err == TCL_ERROR)
1465
res = Tkinter_Error(self);
1467
res = PyUnicode_FromString(Tkapp_Result(self));
1453
PyObject *res = NULL;
1456
if (!PyArg_ParseTuple(args, "s", &script))
1459
CHECK_TCL_APPARTMENT;
1462
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1464
if (err == TCL_ERROR)
1465
res = Tkinter_Error(self);
1467
res = PyUnicode_FromString(Tkapp_Result(self));
1472
1472
static PyObject *
1473
1473
Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1477
if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1479
CHECK_TCL_APPARTMENT;
1482
Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1477
if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1479
CHECK_TCL_APPARTMENT;
1482
Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1491
1491
/** Tcl Variable **/
1493
1493
typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1563
1563
var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1565
1565
#ifdef WITH_THREAD
1566
TkappObject *self = (TkappObject*)selfptr;
1567
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1568
TkappObject *self = (TkappObject*)selfptr;
1570
PyObject *res, *exc_type, *exc_val;
1571
Tcl_Condition cond = NULL;
1573
/* The current thread is not the interpreter thread. Marshal
1574
the call to the interpreter thread, then wait for
1576
if (!WaitForMainloop(self))
1579
ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1586
ev->exc_type = &exc_type;
1587
ev->exc_val = &exc_val;
1589
ev->ev.proc = (Tcl_EventProc*)var_proc;
1590
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1591
Tcl_ConditionFinalize(&cond);
1593
PyErr_SetObject(exc_type, exc_val);
1594
Py_DECREF(exc_type);
1566
TkappObject *self = (TkappObject*)selfptr;
1567
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1568
TkappObject *self = (TkappObject*)selfptr;
1570
PyObject *res, *exc_type, *exc_val;
1571
Tcl_Condition cond = NULL;
1573
/* The current thread is not the interpreter thread. Marshal
1574
the call to the interpreter thread, then wait for
1576
if (!WaitForMainloop(self))
1579
ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1586
ev->exc_type = &exc_type;
1587
ev->exc_val = &exc_val;
1589
ev->ev.proc = (Tcl_EventProc*)var_proc;
1590
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1591
Tcl_ConditionFinalize(&cond);
1593
PyErr_SetObject(exc_type, exc_val);
1594
Py_DECREF(exc_type);
1601
/* Tcl is not threaded, or this is the interpreter thread. */
1602
return func(selfptr, args, flags);
1601
/* Tcl is not threaded, or this is the interpreter thread. */
1602
return func(selfptr, args, flags);
1605
1605
static PyObject *
1606
1606
SetVar(PyObject *self, PyObject *args, int flags)
1608
char *name1, *name2;
1610
PyObject *res = NULL;
1611
Tcl_Obj *newval, *ok;
1608
char *name1, *name2;
1610
PyObject *res = NULL;
1611
Tcl_Obj *newval, *ok;
1613
if (PyArg_ParseTuple(args, "O&O:setvar",
1614
varname_converter, &name1, &newValue)) {
1615
/* XXX Acquire tcl lock??? */
1616
newval = AsObj(newValue);
1620
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1624
Tkinter_Error(self);
1633
if (PyArg_ParseTuple(args, "ssO:setvar",
1634
&name1, &name2, &newValue)) {
1635
/* XXX must hold tcl lock already??? */
1636
newval = AsObj(newValue);
1638
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1641
Tkinter_Error(self);
1613
if (PyArg_ParseTuple(args, "O&O:setvar",
1614
varname_converter, &name1, &newValue)) {
1615
/* XXX Acquire tcl lock??? */
1616
newval = AsObj(newValue);
1620
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1624
Tkinter_Error(self);
1633
if (PyArg_ParseTuple(args, "ssO:setvar",
1634
&name1, &name2, &newValue)) {
1635
/* XXX must hold tcl lock already??? */
1636
newval = AsObj(newValue);
1638
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1641
Tkinter_Error(self);
1655
1655
static PyObject *
1656
1656
Tkapp_SetVar(PyObject *self, PyObject *args)
1658
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1658
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1661
1661
static PyObject *
1662
1662
Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1664
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1664
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1669
1669
static PyObject *
1670
1670
GetVar(PyObject *self, PyObject *args, int flags)
1672
char *name1, *name2=NULL;
1673
PyObject *res = NULL;
1676
if (!PyArg_ParseTuple(args, "O&|s:getvar",
1677
varname_converter, &name1, &name2))
1681
tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1684
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1686
if (((TkappObject*)self)->wantobjects) {
1687
res = FromObj(self, tres);
1690
res = PyUnicode_FromString(Tcl_GetString(tres));
1672
char *name1, *name2=NULL;
1673
PyObject *res = NULL;
1676
if (!PyArg_ParseTuple(args, "O&|s:getvar",
1677
varname_converter, &name1, &name2))
1681
tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1684
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1686
if (((TkappObject*)self)->wantobjects) {
1687
res = FromObj(self, tres);
1690
res = PyUnicode_FromString(Tcl_GetString(tres));
1697
1697
static PyObject *
1698
1698
Tkapp_GetVar(PyObject *self, PyObject *args)
1700
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1700
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1703
1703
static PyObject *
1704
1704
Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1706
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1706
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1711
1711
static PyObject *
1712
1712
UnsetVar(PyObject *self, PyObject *args, int flags)
1714
char *name1, *name2=NULL;
1716
PyObject *res = NULL;
1718
if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1722
code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1724
if (code == TCL_ERROR)
1725
res = Tkinter_Error(self);
1714
char *name1, *name2=NULL;
1716
PyObject *res = NULL;
1718
if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1722
code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1724
if (code == TCL_ERROR)
1725
res = Tkinter_Error(self);
1734
1734
static PyObject *
1735
1735
Tkapp_UnsetVar(PyObject *self, PyObject *args)
1737
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1737
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1740
1740
static PyObject *
1741
1741
Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1743
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1743
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1748
1748
/** Tcl to Python **/
1750
1750
static PyObject *
1751
1751
Tkapp_GetInt(PyObject *self, PyObject *args)
1756
if (PyTuple_Size(args) == 1) {
1757
PyObject* o = PyTuple_GetItem(args, 0);
1758
if (PyLong_Check(o)) {
1763
if (!PyArg_ParseTuple(args, "s:getint", &s))
1765
if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1766
return Tkinter_Error(self);
1767
return Py_BuildValue("i", v);
1756
if (PyTuple_Size(args) == 1) {
1757
PyObject* o = PyTuple_GetItem(args, 0);
1758
if (PyLong_Check(o)) {
1763
if (!PyArg_ParseTuple(args, "s:getint", &s))
1765
if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1766
return Tkinter_Error(self);
1767
return Py_BuildValue("i", v);
1770
1770
static PyObject *
1771
1771
Tkapp_GetDouble(PyObject *self, PyObject *args)
1776
if (PyTuple_Size(args) == 1) {
1777
PyObject *o = PyTuple_GetItem(args, 0);
1778
if (PyFloat_Check(o)) {
1783
if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1785
if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786
return Tkinter_Error(self);
1787
return Py_BuildValue("d", v);
1776
if (PyTuple_Size(args) == 1) {
1777
PyObject *o = PyTuple_GetItem(args, 0);
1778
if (PyFloat_Check(o)) {
1783
if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1785
if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786
return Tkinter_Error(self);
1787
return Py_BuildValue("d", v);
1790
1790
static PyObject *
1791
1791
Tkapp_GetBoolean(PyObject *self, PyObject *args)
1796
if (PyTuple_Size(args) == 1) {
1797
PyObject *o = PyTuple_GetItem(args, 0);
1798
if (PyLong_Check(o)) {
1803
if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1805
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1806
return Tkinter_Error(self);
1807
return PyBool_FromLong(v);
1796
if (PyTuple_Size(args) == 1) {
1797
PyObject *o = PyTuple_GetItem(args, 0);
1798
if (PyLong_Check(o)) {
1803
if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1805
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1806
return Tkinter_Error(self);
1807
return PyBool_FromLong(v);
1810
1810
static PyObject *
1811
1811
Tkapp_ExprString(PyObject *self, PyObject *args)
1814
PyObject *res = NULL;
1817
if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1820
CHECK_TCL_APPARTMENT;
1823
retval = Tcl_ExprString(Tkapp_Interp(self), s);
1825
if (retval == TCL_ERROR)
1826
res = Tkinter_Error(self);
1828
res = Py_BuildValue("s", Tkapp_Result(self));
1814
PyObject *res = NULL;
1817
if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1820
CHECK_TCL_APPARTMENT;
1823
retval = Tcl_ExprString(Tkapp_Interp(self), s);
1825
if (retval == TCL_ERROR)
1826
res = Tkinter_Error(self);
1828
res = Py_BuildValue("s", Tkapp_Result(self));
1833
1833
static PyObject *
1834
1834
Tkapp_ExprLong(PyObject *self, PyObject *args)
1837
PyObject *res = NULL;
1841
if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1844
CHECK_TCL_APPARTMENT;
1847
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1849
if (retval == TCL_ERROR)
1850
res = Tkinter_Error(self);
1852
res = Py_BuildValue("l", v);
1837
PyObject *res = NULL;
1841
if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1844
CHECK_TCL_APPARTMENT;
1847
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1849
if (retval == TCL_ERROR)
1850
res = Tkinter_Error(self);
1852
res = Py_BuildValue("l", v);
1857
1857
static PyObject *
1858
1858
Tkapp_ExprDouble(PyObject *self, PyObject *args)
1861
PyObject *res = NULL;
1861
PyObject *res = NULL;
1865
if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1867
CHECK_TCL_APPARTMENT;
1868
PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1870
retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1872
PyFPE_END_PROTECT(retval)
1873
if (retval == TCL_ERROR)
1874
res = Tkinter_Error(self);
1876
res = Py_BuildValue("d", v);
1865
if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1867
CHECK_TCL_APPARTMENT;
1868
PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1870
retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1872
PyFPE_END_PROTECT(retval)
1873
if (retval == TCL_ERROR)
1874
res = Tkinter_Error(self);
1876
res = Py_BuildValue("d", v);
1881
1881
static PyObject *
1882
1882
Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1885
PyObject *res = NULL;
1885
PyObject *res = NULL;
1889
if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1891
CHECK_TCL_APPARTMENT;
1893
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1895
if (retval == TCL_ERROR)
1896
res = Tkinter_Error(self);
1898
res = Py_BuildValue("i", v);
1889
if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1891
CHECK_TCL_APPARTMENT;
1893
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1895
if (retval == TCL_ERROR)
1896
res = Tkinter_Error(self);
1898
res = Py_BuildValue("i", v);
1905
1905
static PyObject *
1906
1906
Tkapp_SplitList(PyObject *self, PyObject *args)
1914
if (PyTuple_Size(args) == 1) {
1915
v = PyTuple_GetItem(args, 0);
1916
if (PyTuple_Check(v)) {
1921
if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1924
if (Tcl_SplitList(Tkapp_Interp(self), list,
1925
&argc, &argv) == TCL_ERROR) {
1927
return Tkinter_Error(self);
1930
if (!(v = PyTuple_New(argc)))
1933
for (i = 0; i < argc; i++) {
1934
PyObject *s = PyUnicode_FromString(argv[i]);
1935
if (!s || PyTuple_SetItem(v, i, s)) {
1914
if (PyTuple_Size(args) == 1) {
1915
v = PyTuple_GetItem(args, 0);
1916
if (PyTuple_Check(v)) {
1921
if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1924
if (Tcl_SplitList(Tkapp_Interp(self), list,
1925
&argc, &argv) == TCL_ERROR) {
1927
return Tkinter_Error(self);
1930
if (!(v = PyTuple_New(argc)))
1933
for (i = 0; i < argc; i++) {
1934
PyObject *s = PyUnicode_FromString(argv[i]);
1935
if (!s || PyTuple_SetItem(v, i, s)) {
1943
ckfree(FREECAST argv);
1943
ckfree(FREECAST argv);
1948
1948
static PyObject *
1949
1949
Tkapp_Split(PyObject *self, PyObject *args)
1954
if (PyTuple_Size(args) == 1) {
1955
PyObject* o = PyTuple_GetItem(args, 0);
1956
if (PyTuple_Check(o)) {
1961
if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1954
if (PyTuple_Size(args) == 1) {
1955
PyObject* o = PyTuple_GetItem(args, 0);
1956
if (PyTuple_Check(o)) {
1961
if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1968
1968
static PyObject *
1969
1969
Tkapp_Merge(PyObject *self, PyObject *args)
1971
char *s = Merge(args);
1972
PyObject *res = NULL;
1975
res = PyUnicode_FromString(s);
1971
char *s = Merge(args);
1972
PyObject *res = NULL;
1975
res = PyUnicode_FromString(s);
1984
1984
/** Tcl Command **/
1986
1986
/* Client data struct */
1987
1987
typedef struct {
1990
1990
} PythonCmd_ClientData;
1993
1993
PythonCmd_Error(Tcl_Interp *interp)
1996
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1996
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2001
2001
/* This is the Tcl command that acts as a wrapper for Python
2005
2005
PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2007
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2008
PyObject *self, *func, *arg, *res;
2014
/* TBD: no error checking here since we know, via the
2015
* Tkapp_CreateCommand() that the client data is a two-tuple
2020
/* Create argument list (argv1, ..., argvN) */
2021
if (!(arg = PyTuple_New(argc - 1)))
2022
return PythonCmd_Error(interp);
2024
for (i = 0; i < (argc - 1); i++) {
2025
PyObject *s = PyUnicode_FromString(argv[i + 1]);
2026
if (!s || PyTuple_SetItem(arg, i, s)) {
2028
return PythonCmd_Error(interp);
2031
res = PyEval_CallObject(func, arg);
2035
return PythonCmd_Error(interp);
2037
obj_res = AsObj(res);
2038
if (obj_res == NULL) {
2040
return PythonCmd_Error(interp);
2043
Tcl_SetObjResult(interp, obj_res);
2007
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2008
PyObject *self, *func, *arg, *res;
2014
/* TBD: no error checking here since we know, via the
2015
* Tkapp_CreateCommand() that the client data is a two-tuple
2020
/* Create argument list (argv1, ..., argvN) */
2021
if (!(arg = PyTuple_New(argc - 1)))
2022
return PythonCmd_Error(interp);
2024
for (i = 0; i < (argc - 1); i++) {
2025
PyObject *s = PyUnicode_FromString(argv[i + 1]);
2026
if (!s || PyTuple_SetItem(arg, i, s)) {
2028
return PythonCmd_Error(interp);
2031
res = PyEval_CallObject(func, arg);
2035
return PythonCmd_Error(interp);
2037
obj_res = AsObj(res);
2038
if (obj_res == NULL) {
2040
return PythonCmd_Error(interp);
2043
Tcl_SetObjResult(interp, obj_res);
2055
2055
PythonCmdDelete(ClientData clientData)
2057
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2057
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2060
Py_XDECREF(data->self);
2061
Py_XDECREF(data->func);
2060
Py_XDECREF(data->self);
2061
Py_XDECREF(data->func);
2069
2069
#ifdef WITH_THREAD
2070
2070
TCL_DECLARE_MUTEX(command_mutex)
2072
2072
typedef struct CommandEvent{
2079
Tcl_Condition *done;
2079
Tcl_Condition *done;
2080
2080
} CommandEvent;
2083
2083
Tkapp_CommandProc(CommandEvent *ev, int flags)
2086
*ev->status = Tcl_CreateCommand(
2087
ev->interp, ev->name, PythonCmd,
2088
ev->data, PythonCmdDelete) == NULL;
2090
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2091
Tcl_MutexLock(&command_mutex);
2092
Tcl_ConditionNotify(ev->done);
2093
Tcl_MutexUnlock(&command_mutex);
2086
*ev->status = Tcl_CreateCommand(
2087
ev->interp, ev->name, PythonCmd,
2088
ev->data, PythonCmdDelete) == NULL;
2090
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2091
Tcl_MutexLock(&command_mutex);
2092
Tcl_ConditionNotify(ev->done);
2093
Tcl_MutexUnlock(&command_mutex);
2098
2098
static PyObject *
2099
2099
Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2101
TkappObject *self = (TkappObject*)selfptr;
2102
PythonCmd_ClientData *data;
2107
if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2109
if (!PyCallable_Check(func)) {
2110
PyErr_SetString(PyExc_TypeError, "command not callable");
2115
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2116
!WaitForMainloop(self))
2120
data = PyMem_NEW(PythonCmd_ClientData, 1);
2122
return PyErr_NoMemory();
2125
data->self = selfptr;
2128
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2129
Tcl_Condition cond = NULL;
2130
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2131
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2132
ev->interp = self->interp;
2135
ev->data = (ClientData)data;
2138
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2139
Tcl_ConditionFinalize(&cond);
2145
err = Tcl_CreateCommand(
2146
Tkapp_Interp(self), cmdName, PythonCmd,
2147
(ClientData)data, PythonCmdDelete) == NULL;
2151
PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2101
TkappObject *self = (TkappObject*)selfptr;
2102
PythonCmd_ClientData *data;
2107
if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2109
if (!PyCallable_Check(func)) {
2110
PyErr_SetString(PyExc_TypeError, "command not callable");
2115
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2116
!WaitForMainloop(self))
2120
data = PyMem_NEW(PythonCmd_ClientData, 1);
2122
return PyErr_NoMemory();
2125
data->self = selfptr;
2128
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2129
Tcl_Condition cond = NULL;
2130
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2131
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2132
ev->interp = self->interp;
2135
ev->data = (ClientData)data;
2138
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2139
Tcl_ConditionFinalize(&cond);
2145
err = Tcl_CreateCommand(
2146
Tkapp_Interp(self), cmdName, PythonCmd,
2147
(ClientData)data, PythonCmdDelete) == NULL;
2151
PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2162
2162
static PyObject *
2163
2163
Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2165
TkappObject *self = (TkappObject*)selfptr;
2165
TkappObject *self = (TkappObject*)selfptr;
2169
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2169
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2172
2172
#ifdef WITH_THREAD
2173
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2174
Tcl_Condition cond = NULL;
2176
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2177
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2178
ev->interp = self->interp;
2183
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2185
Tcl_ConditionFinalize(&cond);
2173
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2174
Tcl_Condition cond = NULL;
2176
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2177
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2178
ev->interp = self->interp;
2183
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2185
Tcl_ConditionFinalize(&cond);
2191
err = Tcl_DeleteCommand(self->interp, cmdName);
2195
PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2191
err = Tcl_DeleteCommand(self->interp, cmdName);
2195
PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2204
2204
#ifdef HAVE_CREATEFILEHANDLER
2205
2205
/** File Handler **/
2207
2207
typedef struct _fhcdata {
2211
struct _fhcdata *next;
2211
struct _fhcdata *next;
2212
2212
} FileHandler_ClientData;
2214
2214
static FileHandler_ClientData *HeadFHCD;
2216
2216
static FileHandler_ClientData *
2217
2217
NewFHCD(PyObject *func, PyObject *file, int id)
2219
FileHandler_ClientData *p;
2220
p = PyMem_NEW(FileHandler_ClientData, 1);
2219
FileHandler_ClientData *p;
2220
p = PyMem_NEW(FileHandler_ClientData, 1);
2234
2234
DeleteFHCD(int id)
2236
FileHandler_ClientData *p, **pp;
2236
FileHandler_ClientData *p, **pp;
2239
while ((p = *pp) != NULL) {
2242
Py_XDECREF(p->func);
2243
Py_XDECREF(p->file);
2239
while ((p = *pp) != NULL) {
2242
Py_XDECREF(p->func);
2243
Py_XDECREF(p->file);
2252
2252
FileHandler(ClientData clientData, int mask)
2254
FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2255
PyObject *func, *file, *arg, *res;
2261
arg = Py_BuildValue("(Oi)", file, (long) mask);
2262
res = PyEval_CallObject(func, arg);
2267
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2254
FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2255
PyObject *func, *file, *arg, *res;
2261
arg = Py_BuildValue("(Oi)", file, (long) mask);
2262
res = PyEval_CallObject(func, arg);
2267
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2273
2273
static PyObject *
2274
2274
Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2275
2275
/* args is (file, mask, func) */
2277
FileHandler_ClientData *data;
2278
PyObject *file, *func;
2281
if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2282
&file, &mask, &func))
2285
CHECK_TCL_APPARTMENT;
2287
tfile = PyObject_AsFileDescriptor(file);
2290
if (!PyCallable_Check(func)) {
2291
PyErr_SetString(PyExc_TypeError, "bad argument list");
2295
data = NewFHCD(func, file, tfile);
2299
/* Ought to check for null Tcl_File object... */
2301
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2277
FileHandler_ClientData *data;
2278
PyObject *file, *func;
2281
if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2282
&file, &mask, &func))
2285
CHECK_TCL_APPARTMENT;
2287
tfile = PyObject_AsFileDescriptor(file);
2290
if (!PyCallable_Check(func)) {
2291
PyErr_SetString(PyExc_TypeError, "bad argument list");
2295
data = NewFHCD(func, file, tfile);
2299
/* Ought to check for null Tcl_File object... */
2301
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2307
2307
static PyObject *
2308
2308
Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2313
if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2316
CHECK_TCL_APPARTMENT;
2318
tfile = PyObject_AsFileDescriptor(file);
2324
/* Ought to check for null Tcl_File object... */
2326
Tcl_DeleteFileHandler(tfile);
2313
if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2316
CHECK_TCL_APPARTMENT;
2318
tfile = PyObject_AsFileDescriptor(file);
2324
/* Ought to check for null Tcl_File object... */
2326
Tcl_DeleteFileHandler(tfile);
2331
2331
#endif /* HAVE_CREATEFILEHANDLER */
2334
2334
/**** Tktt Object (timer token) ****/
2336
2336
static PyTypeObject Tktt_Type;
2338
2338
typedef struct {
2340
Tcl_TimerToken token;
2340
Tcl_TimerToken token;
2344
2344
static PyObject *
2345
2345
Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2347
TkttObject *v = (TkttObject *)self;
2348
PyObject *func = v->func;
2347
TkttObject *v = (TkttObject *)self;
2348
PyObject *func = v->func;
2350
if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2352
if (v->token != NULL) {
2353
Tcl_DeleteTimerHandler(v->token);
2359
Py_DECREF(v); /* See Tktt_New() */
2350
if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2352
if (v->token != NULL) {
2353
Tcl_DeleteTimerHandler(v->token);
2359
Py_DECREF(v); /* See Tktt_New() */
2365
2365
static PyMethodDef Tktt_methods[] =
2367
{"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2367
{"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2371
2371
static TkttObject *
2372
2372
Tktt_New(PyObject *func)
2376
v = PyObject_New(TkttObject, &Tktt_Type);
2384
/* Extra reference, deleted when called or when handler is deleted */
2376
v = PyObject_New(TkttObject, &Tktt_Type);
2384
/* Extra reference, deleted when called or when handler is deleted */
2390
2390
Tktt_Dealloc(PyObject *self)
2392
TkttObject *v = (TkttObject *)self;
2393
PyObject *func = v->func;
2392
TkttObject *v = (TkttObject *)self;
2393
PyObject *func = v->func;
2400
2400
static PyObject *
2401
2401
Tktt_Repr(PyObject *self)
2403
TkttObject *v = (TkttObject *)self;
2403
TkttObject *v = (TkttObject *)self;
2406
PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2407
v->func == NULL ? ", handler deleted" : "");
2408
return PyUnicode_FromString(buf);
2406
PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2407
v->func == NULL ? ", handler deleted" : "");
2408
return PyUnicode_FromString(buf);
2411
2411
static PyTypeObject Tktt_Type =
2413
PyVarObject_HEAD_INIT(NULL, 0)
2414
"tktimertoken", /*tp_name */
2415
sizeof(TkttObject), /*tp_basicsize */
2417
Tktt_Dealloc, /*tp_dealloc */
2422
Tktt_Repr, /*tp_repr */
2423
0, /*tp_as_number */
2424
0, /*tp_as_sequence */
2425
0, /*tp_as_mapping */
2432
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2436
0, /*tp_richcompare*/
2437
0, /*tp_weaklistoffset*/
2440
Tktt_methods, /*tp_methods*/
2413
PyVarObject_HEAD_INIT(NULL, 0)
2414
"tktimertoken", /*tp_name */
2415
sizeof(TkttObject), /*tp_basicsize */
2417
Tktt_Dealloc, /*tp_dealloc */
2422
Tktt_Repr, /*tp_repr */
2423
0, /*tp_as_number */
2424
0, /*tp_as_sequence */
2425
0, /*tp_as_mapping */
2432
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2436
0, /*tp_richcompare*/
2437
0, /*tp_weaklistoffset*/
2440
Tktt_methods, /*tp_methods*/
2445
2445
/** Timer Handler **/
2448
2448
TimerHandler(ClientData clientData)
2450
TkttObject *v = (TkttObject *)clientData;
2451
PyObject *func = v->func;
2461
res = PyEval_CallObject(func, NULL);
2463
Py_DECREF(v); /* See Tktt_New() */
2467
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2450
TkttObject *v = (TkttObject *)clientData;
2451
PyObject *func = v->func;
2461
res = PyEval_CallObject(func, NULL);
2463
Py_DECREF(v); /* See Tktt_New() */
2467
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2475
2475
static PyObject *
2476
2476
Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2482
if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2483
&milliseconds, &func))
2485
if (!PyCallable_Check(func)) {
2486
PyErr_SetString(PyExc_TypeError, "bad argument list");
2490
CHECK_TCL_APPARTMENT;
2494
v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2498
return (PyObject *) v;
2482
if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2483
&milliseconds, &func))
2485
if (!PyCallable_Check(func)) {
2486
PyErr_SetString(PyExc_TypeError, "bad argument list");
2490
CHECK_TCL_APPARTMENT;
2494
v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2498
return (PyObject *) v;
2502
2502
/** Event Loop **/
2504
2504
static PyObject *
2505
2505
Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2508
TkappObject *self = (TkappObject*)selfptr;
2508
TkappObject *self = (TkappObject*)selfptr;
2509
2509
#ifdef WITH_THREAD
2510
PyThreadState *tstate = PyThreadState_Get();
2510
PyThreadState *tstate = PyThreadState_Get();
2513
if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2516
CHECK_TCL_APPARTMENT;
2517
self->dispatching = 1;
2520
while (Tk_GetNumMainWindows() > threshold &&
2513
if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2516
CHECK_TCL_APPARTMENT;
2517
self->dispatching = 1;
2520
while (Tk_GetNumMainWindows() > threshold &&
2526
2526
#ifdef WITH_THREAD
2527
if (self->threaded) {
2528
/* Allow other Python threads to run. */
2530
result = Tcl_DoOneEvent(0);
2534
Py_BEGIN_ALLOW_THREADS
2535
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2536
tcl_tstate = tstate;
2537
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2539
if(tcl_lock)PyThread_release_lock(tcl_lock);
2541
Sleep(Tkinter_busywaitinterval);
2542
Py_END_ALLOW_THREADS
2527
if (self->threaded) {
2528
/* Allow other Python threads to run. */
2530
result = Tcl_DoOneEvent(0);
2534
Py_BEGIN_ALLOW_THREADS
2535
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2536
tcl_tstate = tstate;
2537
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2539
if(tcl_lock)PyThread_release_lock(tcl_lock);
2541
Sleep(Tkinter_busywaitinterval);
2542
Py_END_ALLOW_THREADS
2545
result = Tcl_DoOneEvent(0);
2545
result = Tcl_DoOneEvent(0);
2548
if (PyErr_CheckSignals() != 0) {
2549
self->dispatching = 0;
2555
self->dispatching = 0;
2548
if (PyErr_CheckSignals() != 0) {
2549
self->dispatching = 0;
2555
self->dispatching = 0;
2560
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2561
excInCmd = valInCmd = trbInCmd = NULL;
2560
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2561
excInCmd = valInCmd = trbInCmd = NULL;
2568
2568
static PyObject *
2569
2569
Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2574
if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2578
rv = Tcl_DoOneEvent(flags);
2580
return Py_BuildValue("i", rv);
2574
if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2578
rv = Tcl_DoOneEvent(flags);
2580
return Py_BuildValue("i", rv);
2583
2583
static PyObject *
2584
2584
Tkapp_Quit(PyObject *self, PyObject *args)
2587
if (!PyArg_ParseTuple(args, ":quit"))
2587
if (!PyArg_ParseTuple(args, ":quit"))
2595
2595
static PyObject *
2596
2596
Tkapp_InterpAddr(PyObject *self, PyObject *args)
2599
if (!PyArg_ParseTuple(args, ":interpaddr"))
2599
if (!PyArg_ParseTuple(args, ":interpaddr"))
2602
return PyLong_FromLong((long)Tkapp_Interp(self));
2602
return PyLong_FromLong((long)Tkapp_Interp(self));
2606
2606
Tkapp_TkInit(PyObject *self, PyObject *args)
2608
Tcl_Interp *interp = Tkapp_Interp(self);
2609
const char * _tk_exists = NULL;
2612
#ifdef TKINTER_PROTECT_LOADTK
2613
/* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2614
* first call failed.
2615
* To avoid the deadlock, we just refuse the second call through
2616
* a static variable.
2618
if (tk_load_failed) {
2619
PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2624
/* We want to guard against calling Tk_Init() multiple times */
2625
CHECK_TCL_APPARTMENT;
2627
err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2629
if (err == TCL_ERROR) {
2630
/* This sets an exception, but we cannot return right
2631
away because we need to exit the overlap first. */
2632
Tkinter_Error(self);
2634
_tk_exists = Tkapp_Result(self);
2637
if (err == TCL_ERROR) {
2640
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2641
if (Tk_Init(interp) == TCL_ERROR) {
2642
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2643
#ifdef TKINTER_PROTECT_LOADTK
2608
Tcl_Interp *interp = Tkapp_Interp(self);
2609
const char * _tk_exists = NULL;
2612
#ifdef TKINTER_PROTECT_LOADTK
2613
/* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2614
* first call failed.
2615
* To avoid the deadlock, we just refuse the second call through
2616
* a static variable.
2618
if (tk_load_failed) {
2619
PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2624
/* We want to guard against calling Tk_Init() multiple times */
2625
CHECK_TCL_APPARTMENT;
2627
err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2629
if (err == TCL_ERROR) {
2630
/* This sets an exception, but we cannot return right
2631
away because we need to exit the overlap first. */
2632
Tkinter_Error(self);
2634
_tk_exists = Tkapp_Result(self);
2637
if (err == TCL_ERROR) {
2640
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2641
if (Tk_Init(interp) == TCL_ERROR) {
2642
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2643
#ifdef TKINTER_PROTECT_LOADTK
2653
2653
static PyObject *
2654
2654
Tkapp_WantObjects(PyObject *self, PyObject *args)
2657
int wantobjects = -1;
2658
if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2660
if (wantobjects == -1)
2661
return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2662
((TkappObject*)self)->wantobjects = wantobjects;
2657
int wantobjects = -1;
2658
if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2660
if (wantobjects == -1)
2661
return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2662
((TkappObject*)self)->wantobjects = wantobjects;
2668
2668
static PyObject *
2669
2669
Tkapp_WillDispatch(PyObject *self, PyObject *args)
2672
((TkappObject*)self)->dispatching = 1;
2672
((TkappObject*)self)->dispatching = 1;
2679
2679
/**** Tkapp Method List ****/
2681
2681
static PyMethodDef Tkapp_methods[] =
2683
{"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2684
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2685
{"call", Tkapp_Call, METH_VARARGS},
2686
{"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2687
{"eval", Tkapp_Eval, METH_VARARGS},
2688
{"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2689
{"evalfile", Tkapp_EvalFile, METH_VARARGS},
2690
{"record", Tkapp_Record, METH_VARARGS},
2691
{"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2692
{"setvar", Tkapp_SetVar, METH_VARARGS},
2693
{"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2694
{"getvar", Tkapp_GetVar, METH_VARARGS},
2695
{"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2696
{"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2697
{"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2698
{"getint", Tkapp_GetInt, METH_VARARGS},
2699
{"getdouble", Tkapp_GetDouble, METH_VARARGS},
2700
{"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2701
{"exprstring", Tkapp_ExprString, METH_VARARGS},
2702
{"exprlong", Tkapp_ExprLong, METH_VARARGS},
2703
{"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2704
{"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2705
{"splitlist", Tkapp_SplitList, METH_VARARGS},
2706
{"split", Tkapp_Split, METH_VARARGS},
2707
{"merge", Tkapp_Merge, METH_VARARGS},
2708
{"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2709
{"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2683
{"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2684
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2685
{"call", Tkapp_Call, METH_VARARGS},
2686
{"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2687
{"eval", Tkapp_Eval, METH_VARARGS},
2688
{"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2689
{"evalfile", Tkapp_EvalFile, METH_VARARGS},
2690
{"record", Tkapp_Record, METH_VARARGS},
2691
{"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2692
{"setvar", Tkapp_SetVar, METH_VARARGS},
2693
{"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2694
{"getvar", Tkapp_GetVar, METH_VARARGS},
2695
{"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2696
{"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2697
{"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2698
{"getint", Tkapp_GetInt, METH_VARARGS},
2699
{"getdouble", Tkapp_GetDouble, METH_VARARGS},
2700
{"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2701
{"exprstring", Tkapp_ExprString, METH_VARARGS},
2702
{"exprlong", Tkapp_ExprLong, METH_VARARGS},
2703
{"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2704
{"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2705
{"splitlist", Tkapp_SplitList, METH_VARARGS},
2706
{"split", Tkapp_Split, METH_VARARGS},
2707
{"merge", Tkapp_Merge, METH_VARARGS},
2708
{"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2709
{"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2710
2710
#ifdef HAVE_CREATEFILEHANDLER
2711
{"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2712
{"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2711
{"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2712
{"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2714
{"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2715
{"mainloop", Tkapp_MainLoop, METH_VARARGS},
2716
{"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2717
{"quit", Tkapp_Quit, METH_VARARGS},
2718
{"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2719
{"loadtk", Tkapp_TkInit, METH_NOARGS},
2714
{"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2715
{"mainloop", Tkapp_MainLoop, METH_VARARGS},
2716
{"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2717
{"quit", Tkapp_Quit, METH_VARARGS},
2718
{"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2719
{"loadtk", Tkapp_TkInit, METH_NOARGS},
2725
2725
/**** Tkapp Type Methods ****/
2728
2728
Tkapp_Dealloc(PyObject *self)
2730
/*CHECK_TCL_APPARTMENT;*/
2732
Tcl_DeleteInterp(Tkapp_Interp(self));
2730
/*CHECK_TCL_APPARTMENT;*/
2732
Tcl_DeleteInterp(Tkapp_Interp(self));
2738
2738
static PyTypeObject Tkapp_Type =
2740
PyVarObject_HEAD_INIT(NULL, 0)
2741
"tkapp", /*tp_name */
2742
sizeof(TkappObject), /*tp_basicsize */
2744
Tkapp_Dealloc, /*tp_dealloc */
2750
0, /*tp_as_number */
2751
0, /*tp_as_sequence */
2752
0, /*tp_as_mapping */
2759
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2763
0, /*tp_richcompare*/
2764
0, /*tp_weaklistoffset*/
2767
Tkapp_methods, /*tp_methods*/
2740
PyVarObject_HEAD_INIT(NULL, 0)
2741
"tkapp", /*tp_name */
2742
sizeof(TkappObject), /*tp_basicsize */
2744
Tkapp_Dealloc, /*tp_dealloc */
2750
0, /*tp_as_number */
2751
0, /*tp_as_sequence */
2752
0, /*tp_as_mapping */
2759
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2763
0, /*tp_richcompare*/
2764
0, /*tp_weaklistoffset*/
2767
Tkapp_methods, /*tp_methods*/
2772
2772
/**** Tkinter Module ****/
2774
2774
typedef struct {
2776
int size; /* current size */
2777
int maxsize; /* allocated size */
2776
int size; /* current size */
2777
int maxsize; /* allocated size */
2778
2778
} FlattenContext;
2781
2781
_bump(FlattenContext* context, int size)
2783
/* expand tuple to hold (at least) size new items.
2784
return true if successful, false if an exception was raised */
2786
int maxsize = context->maxsize * 2;
2788
if (maxsize < context->size + size)
2789
maxsize = context->size + size;
2791
context->maxsize = maxsize;
2793
return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2783
/* expand tuple to hold (at least) size new items.
2784
return true if successful, false if an exception was raised */
2786
int maxsize = context->maxsize * 2;
2788
if (maxsize < context->size + size)
2789
maxsize = context->size + size;
2791
context->maxsize = maxsize;
2793
return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2797
2797
_flatten1(FlattenContext* context, PyObject* item, int depth)
2799
/* add tuple or list to argument tuple (recursively) */
2804
PyErr_SetString(PyExc_ValueError,
2805
"nesting too deep in _flatten");
2807
} else if (PyList_Check(item)) {
2808
size = PyList_GET_SIZE(item);
2809
/* preallocate (assume no nesting) */
2810
if (context->size + size > context->maxsize &&
2811
!_bump(context, size))
2813
/* copy items to output tuple */
2814
for (i = 0; i < size; i++) {
2815
PyObject *o = PyList_GET_ITEM(item, i);
2816
if (PyList_Check(o) || PyTuple_Check(o)) {
2817
if (!_flatten1(context, o, depth + 1))
2819
} else if (o != Py_None) {
2820
if (context->size + 1 > context->maxsize &&
2824
PyTuple_SET_ITEM(context->tuple,
2825
context->size++, o);
2828
} else if (PyTuple_Check(item)) {
2829
/* same, for tuples */
2830
size = PyTuple_GET_SIZE(item);
2831
if (context->size + size > context->maxsize &&
2832
!_bump(context, size))
2834
for (i = 0; i < size; i++) {
2835
PyObject *o = PyTuple_GET_ITEM(item, i);
2836
if (PyList_Check(o) || PyTuple_Check(o)) {
2837
if (!_flatten1(context, o, depth + 1))
2839
} else if (o != Py_None) {
2840
if (context->size + 1 > context->maxsize &&
2844
PyTuple_SET_ITEM(context->tuple,
2845
context->size++, o);
2849
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2799
/* add tuple or list to argument tuple (recursively) */
2804
PyErr_SetString(PyExc_ValueError,
2805
"nesting too deep in _flatten");
2807
} else if (PyList_Check(item)) {
2808
size = PyList_GET_SIZE(item);
2809
/* preallocate (assume no nesting) */
2810
if (context->size + size > context->maxsize &&
2811
!_bump(context, size))
2813
/* copy items to output tuple */
2814
for (i = 0; i < size; i++) {
2815
PyObject *o = PyList_GET_ITEM(item, i);
2816
if (PyList_Check(o) || PyTuple_Check(o)) {
2817
if (!_flatten1(context, o, depth + 1))
2819
} else if (o != Py_None) {
2820
if (context->size + 1 > context->maxsize &&
2824
PyTuple_SET_ITEM(context->tuple,
2825
context->size++, o);
2828
} else if (PyTuple_Check(item)) {
2829
/* same, for tuples */
2830
size = PyTuple_GET_SIZE(item);
2831
if (context->size + size > context->maxsize &&
2832
!_bump(context, size))
2834
for (i = 0; i < size; i++) {
2835
PyObject *o = PyTuple_GET_ITEM(item, i);
2836
if (PyList_Check(o) || PyTuple_Check(o)) {
2837
if (!_flatten1(context, o, depth + 1))
2839
} else if (o != Py_None) {
2840
if (context->size + 1 > context->maxsize &&
2844
PyTuple_SET_ITEM(context->tuple,
2845
context->size++, o);
2849
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2855
2855
static PyObject *
2856
2856
Tkinter_Flatten(PyObject* self, PyObject* args)
2858
FlattenContext context;
2861
if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2864
context.maxsize = PySequence_Size(item);
2865
if (context.maxsize < 0)
2867
if (context.maxsize == 0)
2868
return PyTuple_New(0);
2870
context.tuple = PyTuple_New(context.maxsize);
2876
if (!_flatten1(&context, item,0))
2879
if (_PyTuple_Resize(&context.tuple, context.size))
2882
return context.tuple;
2858
FlattenContext context;
2861
if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2864
context.maxsize = PySequence_Size(item);
2865
if (context.maxsize < 0)
2867
if (context.maxsize == 0)
2868
return PyTuple_New(0);
2870
context.tuple = PyTuple_New(context.maxsize);
2876
if (!_flatten1(&context, item,0))
2879
if (_PyTuple_Resize(&context.tuple, context.size))
2882
return context.tuple;
2885
2885
static PyObject *
2886
2886
Tkinter_Create(PyObject *self, PyObject *args)
2888
char *screenName = NULL;
2889
char *baseName = NULL; /* XXX this is not used anymore;
2890
try getting rid of it. */
2891
char *className = NULL;
2892
int interactive = 0;
2893
int wantobjects = 0;
2894
int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2895
int sync = 0; /* pass -sync to wish */
2896
char *use = NULL; /* pass -use to wish */
2900
if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2901
&screenName, &baseName, &className,
2902
&interactive, &wantobjects, &wantTk,
2906
return (PyObject *) Tkapp_New(screenName, className,
2907
interactive, wantobjects, wantTk,
2888
char *screenName = NULL;
2889
char *baseName = NULL; /* XXX this is not used anymore;
2890
try getting rid of it. */
2891
char *className = NULL;
2892
int interactive = 0;
2893
int wantobjects = 0;
2894
int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2895
int sync = 0; /* pass -sync to wish */
2896
char *use = NULL; /* pass -use to wish */
2900
if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2901
&screenName, &baseName, &className,
2902
&interactive, &wantobjects, &wantTk,
2906
return (PyObject *) Tkapp_New(screenName, className,
2907
interactive, wantobjects, wantTk,
2911
2911
static PyObject *
2912
2912
Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2915
if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2918
PyErr_SetString(PyExc_ValueError,
2919
"busywaitinterval must be >= 0");
2922
Tkinter_busywaitinterval = new_val;
2915
if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2918
PyErr_SetString(PyExc_ValueError,
2919
"busywaitinterval must be >= 0");
2922
Tkinter_busywaitinterval = new_val;
2927
2927
static char setbusywaitinterval_doc[] =
3059
3059
ins_long(PyObject *d, char *name, long val)
3061
PyObject *v = PyLong_FromLong(val);
3063
PyDict_SetItemString(d, name, v);
3061
PyObject *v = PyLong_FromLong(val);
3063
PyDict_SetItemString(d, name, v);
3068
3068
ins_string(PyObject *d, char *name, char *val)
3070
PyObject *v = PyUnicode_FromString(val);
3072
PyDict_SetItemString(d, name, v);
3070
PyObject *v = PyUnicode_FromString(val);
3072
PyDict_SetItemString(d, name, v);
3078
3078
static struct PyModuleDef _tkintermodule = {
3079
PyModuleDef_HEAD_INIT,
3079
PyModuleDef_HEAD_INIT,
3091
3091
PyInit__tkinter(void)
3093
PyObject *m, *d, *uexe, *cexe;
3093
PyObject *m, *d, *uexe, *cexe;
3095
if (PyType_Ready(&Tkapp_Type) < 0)
3095
if (PyType_Ready(&Tkapp_Type) < 0)
3098
3098
#ifdef WITH_THREAD
3099
tcl_lock = PyThread_allocate_lock();
3099
tcl_lock = PyThread_allocate_lock();
3102
m = PyModule_Create(&_tkintermodule);
3106
d = PyModule_GetDict(m);
3107
Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3108
PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3110
ins_long(d, "READABLE", TCL_READABLE);
3111
ins_long(d, "WRITABLE", TCL_WRITABLE);
3112
ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3113
ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3114
ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3115
ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3116
ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3117
ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3118
ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3119
ins_string(d, "TK_VERSION", TK_VERSION);
3120
ins_string(d, "TCL_VERSION", TCL_VERSION);
3122
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3124
if (PyType_Ready(&Tktt_Type) < 0)
3126
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3128
Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3129
PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3102
m = PyModule_Create(&_tkintermodule);
3106
d = PyModule_GetDict(m);
3107
Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3108
PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3110
ins_long(d, "READABLE", TCL_READABLE);
3111
ins_long(d, "WRITABLE", TCL_WRITABLE);
3112
ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3113
ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3114
ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3115
ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3116
ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3117
ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3118
ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3119
ins_string(d, "TK_VERSION", TK_VERSION);
3120
ins_string(d, "TCL_VERSION", TCL_VERSION);
3122
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3124
if (PyType_Ready(&Tktt_Type) < 0)
3126
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3128
Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3129
PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3132
/* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3133
* start waking up. Note that Tcl_FindExecutable will do this, this
3134
* code must be above it! The original warning from
3135
* tkMacOSXAppInit.c is copied below.
3137
* NB - You have to swap in the Tk Notifier BEFORE you start up the
3138
* Tcl interpreter for now. It probably should work to do this
3139
* in the other order, but for now it doesn't seem to.
3142
Tk_MacOSXSetupTkNotifier();
3132
/* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3133
* start waking up. Note that Tcl_FindExecutable will do this, this
3134
* code must be above it! The original warning from
3135
* tkMacOSXAppInit.c is copied below.
3137
* NB - You have to swap in the Tk Notifier BEFORE you start up the
3138
* Tcl interpreter for now. It probably should work to do this
3139
* in the other order, but for now it doesn't seem to.
3142
Tk_MacOSXSetupTkNotifier();
3146
/* This helps the dynamic loader; in Unicode aware Tcl versions
3147
it also helps Tcl find its encodings. */
3148
uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3150
cexe = PyUnicode_AsEncodedString(uexe,
3151
Py_FileSystemDefaultEncoding,
3154
Tcl_FindExecutable(PyBytes_AsString(cexe));
3146
/* This helps the dynamic loader; in Unicode aware Tcl versions
3147
it also helps Tcl find its encodings. */
3148
uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3150
cexe = PyUnicode_AsEncodedString(uexe,
3151
Py_FileSystemDefaultEncoding,
3154
Tcl_FindExecutable(PyBytes_AsString(cexe));
3159
if (PyErr_Occurred()) {
3159
if (PyErr_Occurred()) {
3165
/* This was not a good idea; through <Destroy> bindings,
3166
Tcl_Finalize() may invoke Python code but at that point the
3167
interpreter and thread state have already been destroyed! */
3168
Py_AtExit(Tcl_Finalize);
3165
/* This was not a good idea; through <Destroy> bindings,
3166
Tcl_Finalize() may invoke Python code but at that point the
3167
interpreter and thread state have already been destroyed! */
3168
Py_AtExit(Tcl_Finalize);