bpo-13153: Use OS native encoding for converting between Python and Tcl. (GH-16545)
On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the "surrogatepass" error handler for converting to/from Tcl Unicode objects. On Linux use UTF-8 with the "surrogateescape" error handler for converting to/from Tcl String objects. Converting strings from Tcl to Python and back now never fails (except MemoryError).
This commit is contained in:
parent
2290b23dfc
commit
06cb94bc84
|
@ -358,21 +358,6 @@ class EditorWindow(object):
|
|||
Font(text, font=text.cget('font')).measure('0')
|
||||
self.width = pixel_width // zero_char_width
|
||||
|
||||
def _filename_to_unicode(self, filename):
|
||||
"""Return filename as BMP unicode so displayable in Tk."""
|
||||
# Decode bytes to unicode.
|
||||
if isinstance(filename, bytes):
|
||||
try:
|
||||
filename = filename.decode(self.filesystemencoding)
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
filename = filename.decode(self.encoding)
|
||||
except UnicodeDecodeError:
|
||||
# byte-to-byte conversion
|
||||
filename = filename.decode('iso8859-1')
|
||||
# Replace non-BMP char with diamond questionmark.
|
||||
return re.sub('[\U00010000-\U0010FFFF]', '\ufffd', filename)
|
||||
|
||||
def new_callback(self, event):
|
||||
dirname, basename = self.io.defaultfilename()
|
||||
self.flist.new(dirname)
|
||||
|
@ -963,10 +948,8 @@ class EditorWindow(object):
|
|||
menu.delete(0, END) # clear, and rebuild:
|
||||
for i, file_name in enumerate(rf_list):
|
||||
file_name = file_name.rstrip() # zap \n
|
||||
# make unicode string to display non-ASCII chars correctly
|
||||
ufile_name = self._filename_to_unicode(file_name)
|
||||
callback = instance.__recent_file_callback(file_name)
|
||||
menu.add_command(label=ulchars[i] + " " + ufile_name,
|
||||
menu.add_command(label=ulchars[i] + " " + file_name,
|
||||
command=callback,
|
||||
underline=0)
|
||||
|
||||
|
@ -1004,16 +987,10 @@ class EditorWindow(object):
|
|||
|
||||
def short_title(self):
|
||||
filename = self.io.filename
|
||||
if filename:
|
||||
filename = os.path.basename(filename)
|
||||
else:
|
||||
filename = "untitled"
|
||||
# return unicode string to display non-ASCII chars correctly
|
||||
return self._filename_to_unicode(filename)
|
||||
return os.path.basename(filename) if filename else "untitled"
|
||||
|
||||
def long_title(self):
|
||||
# return unicode string to display non-ASCII chars correctly
|
||||
return self._filename_to_unicode(self.io.filename or "")
|
||||
return self.io.filename or ""
|
||||
|
||||
def center_insert_event(self, event):
|
||||
self.center()
|
||||
|
|
|
@ -30,18 +30,6 @@ class EditorWindowTest(unittest.TestCase):
|
|||
e._close()
|
||||
|
||||
|
||||
class EditorFunctionTest(unittest.TestCase):
|
||||
|
||||
def test_filename_to_unicode(self):
|
||||
func = Editor._filename_to_unicode
|
||||
class dummy():
|
||||
filesystemencoding = 'utf-8'
|
||||
pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'),
|
||||
(b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc'))
|
||||
for inp, out in pairs:
|
||||
self.assertEqual(func(dummy, inp), out)
|
||||
|
||||
|
||||
class TestGetLineIndent(unittest.TestCase):
|
||||
def test_empty_lines(self):
|
||||
for tabwidth in [1, 2, 4, 6, 8]:
|
||||
|
|
|
@ -679,14 +679,6 @@ class ModifiedInterpreter(InteractiveInterpreter):
|
|||
self.more = 0
|
||||
# at the moment, InteractiveInterpreter expects str
|
||||
assert isinstance(source, str)
|
||||
#if isinstance(source, str):
|
||||
# from idlelib import iomenu
|
||||
# try:
|
||||
# source = source.encode(iomenu.encoding)
|
||||
# except UnicodeError:
|
||||
# self.tkconsole.resetoutput()
|
||||
# self.write("Unsupported characters in input\n")
|
||||
# return
|
||||
# InteractiveInterpreter.runsource() calls its runcode() method,
|
||||
# which is overridden (see below)
|
||||
return InteractiveInterpreter.runsource(self, source, filename)
|
||||
|
@ -1298,16 +1290,6 @@ class PyShell(OutputWindow):
|
|||
self.set_line_and_column()
|
||||
|
||||
def write(self, s, tags=()):
|
||||
if isinstance(s, str) and len(s) and max(s) > '\uffff':
|
||||
# Tk doesn't support outputting non-BMP characters
|
||||
# Let's assume what printed string is not very long,
|
||||
# find first non-BMP character and construct informative
|
||||
# UnicodeEncodeError exception.
|
||||
for start, char in enumerate(s):
|
||||
if char > '\uffff':
|
||||
break
|
||||
raise UnicodeEncodeError("UCS-2", char, start, start+1,
|
||||
'Non-BMP character not supported in Tk')
|
||||
try:
|
||||
self.text.mark_gravity("iomark", "right")
|
||||
count = OutputWindow.write(self, s, tags, "iomark")
|
||||
|
|
|
@ -147,8 +147,7 @@ class ScriptBinding:
|
|||
interp = self.shell.interp
|
||||
if pyshell.use_subprocess and restart:
|
||||
interp.restart_subprocess(
|
||||
with_cwd=False, filename=
|
||||
self.editwin._filename_to_unicode(filename))
|
||||
with_cwd=False, filename=filename)
|
||||
dirname = os.path.dirname(filename)
|
||||
argv = [filename]
|
||||
if self.cli_args:
|
||||
|
|
|
@ -429,9 +429,12 @@ class TclTest(unittest.TestCase):
|
|||
self.assertEqual(passValue(False), False if self.wantobjects else '0')
|
||||
self.assertEqual(passValue('string'), 'string')
|
||||
self.assertEqual(passValue('string\u20ac'), 'string\u20ac')
|
||||
self.assertEqual(passValue('string\U0001f4bb'), 'string\U0001f4bb')
|
||||
self.assertEqual(passValue('str\x00ing'), 'str\x00ing')
|
||||
self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd')
|
||||
self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
|
||||
self.assertEqual(passValue('str\x00ing\U0001f4bb'),
|
||||
'str\x00ing\U0001f4bb')
|
||||
self.assertEqual(passValue(b'str\x00ing'),
|
||||
b'str\x00ing' if self.wantobjects else 'str\x00ing')
|
||||
self.assertEqual(passValue(b'str\xc0\x80ing'),
|
||||
|
@ -490,6 +493,7 @@ class TclTest(unittest.TestCase):
|
|||
check('string')
|
||||
check('string\xbd')
|
||||
check('string\u20ac')
|
||||
check('string\U0001f4bb')
|
||||
check('')
|
||||
check(b'string', 'string')
|
||||
check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
|
||||
|
@ -531,6 +535,7 @@ class TclTest(unittest.TestCase):
|
|||
('a\n b\t\r c\n ', ('a', 'b', 'c')),
|
||||
(b'a\n b\t\r c\n ', ('a', 'b', 'c')),
|
||||
('a \u20ac', ('a', '\u20ac')),
|
||||
('a \U0001f4bb', ('a', '\U0001f4bb')),
|
||||
(b'a \xe2\x82\xac', ('a', '\u20ac')),
|
||||
(b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
|
||||
('a {b c}', ('a', 'b c')),
|
||||
|
|
|
@ -170,6 +170,28 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
|
|||
with self.assertRaises(tkinter.TclError):
|
||||
root.tk.call('after', 'info', idle1)
|
||||
|
||||
def test_clipboard(self):
|
||||
root = self.root
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append('Ùñî')
|
||||
self.assertEqual(root.clipboard_get(), 'Ùñî')
|
||||
root.clipboard_append('çōđě')
|
||||
self.assertEqual(root.clipboard_get(), 'Ùñîçōđě')
|
||||
root.clipboard_clear()
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
root.clipboard_get()
|
||||
|
||||
def test_clipboard_astral(self):
|
||||
root = self.root
|
||||
root.clipboard_clear()
|
||||
root.clipboard_append('𝔘𝔫𝔦')
|
||||
self.assertEqual(root.clipboard_get(), '𝔘𝔫𝔦')
|
||||
root.clipboard_append('𝔠𝔬𝔡𝔢')
|
||||
self.assertEqual(root.clipboard_get(), '𝔘𝔫𝔦𝔠𝔬𝔡𝔢')
|
||||
root.clipboard_clear()
|
||||
with self.assertRaises(tkinter.TclError):
|
||||
root.clipboard_get()
|
||||
|
||||
|
||||
tests_gui = (MiscTest, )
|
||||
|
||||
|
|
|
@ -489,8 +489,7 @@ class ComboboxTest(EntryTest, unittest.TestCase):
|
|||
expected=('mon', 'tue', 'wed', 'thur'))
|
||||
self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur'))
|
||||
self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string'))
|
||||
self.checkParam(self.combo, 'values', '',
|
||||
expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
|
||||
self.checkParam(self.combo, 'values', '')
|
||||
|
||||
self.combo['values'] = ['a', 1, 'c']
|
||||
|
||||
|
@ -1245,12 +1244,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
|
|||
expected=('mon', 'tue', 'wed', 'thur'))
|
||||
self.checkParam(self.spin, 'values', ('mon', 'tue', 'wed', 'thur'))
|
||||
self.checkParam(self.spin, 'values', (42, 3.14, '', 'any string'))
|
||||
self.checkParam(
|
||||
self.spin,
|
||||
'values',
|
||||
'',
|
||||
expected='' if get_tk_patchlevel() < (8, 5, 10) else ()
|
||||
)
|
||||
self.checkParam(self.spin, 'values', '')
|
||||
|
||||
self.spin['values'] = ['a', 1, 'c']
|
||||
|
||||
|
@ -1308,8 +1302,7 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
|
|||
self.checkParam(widget, 'columns', 'a b c',
|
||||
expected=('a', 'b', 'c'))
|
||||
self.checkParam(widget, 'columns', ('a', 'b', 'c'))
|
||||
self.checkParam(widget, 'columns', (),
|
||||
expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
|
||||
self.checkParam(widget, 'columns', '')
|
||||
|
||||
def test_displaycolumns(self):
|
||||
widget = self.create()
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
OS native encoding is now used for converting between Python strings and
|
||||
Tcl objects. This allows to display, copy and paste to clipboard emoji and
|
||||
other non-BMP characters. Converting strings from Tcl to Python and back
|
||||
now never fails (except MemoryError).
|
|
@ -96,6 +96,24 @@ Copyright (C) 1994 Steen Lumholt.
|
|||
|
||||
#endif /* HAVE_CREATEFILEHANDLER */
|
||||
|
||||
/* Use OS native encoding for converting between Python strings and
|
||||
Tcl objects.
|
||||
On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
|
||||
"surrogatepass" error handler for converting to/from Tcl Unicode objects.
|
||||
On Linux use UTF-8 with the "surrogateescape" error handler for converting
|
||||
to/from Tcl String objects. */
|
||||
#ifdef MS_WINDOWS
|
||||
#define USE_TCL_UNICODE 1
|
||||
#else
|
||||
#define USE_TCL_UNICODE 0
|
||||
#endif
|
||||
|
||||
#if PY_LITTLE_ENDIAN
|
||||
#define NATIVE_BYTEORDER -1
|
||||
#else
|
||||
#define NATIVE_BYTEORDER 1
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#include <conio.h>
|
||||
#define WAIT_FOR_STDIN
|
||||
|
@ -290,7 +308,6 @@ typedef struct {
|
|||
} TkappObject;
|
||||
|
||||
#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
|
||||
#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
|
||||
|
||||
#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
|
||||
(void *) v, Py_REFCNT(v)))
|
||||
|
@ -311,10 +328,16 @@ static int tk_load_failed = 0;
|
|||
#endif
|
||||
|
||||
|
||||
static PyObject *Tkapp_UnicodeResult(TkappObject *);
|
||||
|
||||
static PyObject *
|
||||
Tkinter_Error(PyObject *v)
|
||||
Tkinter_Error(TkappObject *self)
|
||||
{
|
||||
PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
|
||||
PyObject *res = Tkapp_UnicodeResult(self);
|
||||
if (res != NULL) {
|
||||
PyErr_SetObject(Tkinter_TclError, res);
|
||||
Py_DECREF(res);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -368,30 +391,35 @@ static PyObject *
|
|||
unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
|
||||
{
|
||||
PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
|
||||
if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
|
||||
/* Tcl encodes null character as \xc0\x80 */
|
||||
if (memchr(s, '\xc0', size)) {
|
||||
char *buf, *q;
|
||||
const char *e = s + size;
|
||||
PyErr_Clear();
|
||||
q = buf = (char *)PyMem_Malloc(size);
|
||||
if (buf == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
while (s != e) {
|
||||
if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
|
||||
*q++ = '\0';
|
||||
s += 2;
|
||||
}
|
||||
else
|
||||
*q++ = *s++;
|
||||
}
|
||||
s = buf;
|
||||
size = q - s;
|
||||
r = PyUnicode_DecodeUTF8(s, size, NULL);
|
||||
PyMem_Free(buf);
|
||||
if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
|
||||
return r;
|
||||
}
|
||||
|
||||
char *buf = NULL;
|
||||
PyErr_Clear();
|
||||
/* Tcl encodes null character as \xc0\x80 */
|
||||
if (memchr(s, '\xc0', size)) {
|
||||
char *q;
|
||||
const char *e = s + size;
|
||||
q = buf = (char *)PyMem_Malloc(size);
|
||||
if (buf == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
while (s != e) {
|
||||
if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
|
||||
*q++ = '\0';
|
||||
s += 2;
|
||||
}
|
||||
else
|
||||
*q++ = *s++;
|
||||
}
|
||||
s = buf;
|
||||
size = q - s;
|
||||
}
|
||||
r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
|
||||
if (buf != NULL) {
|
||||
PyMem_Free(buf);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -406,8 +434,21 @@ static PyObject *
|
|||
unicodeFromTclObj(Tcl_Obj *value)
|
||||
{
|
||||
int len;
|
||||
char *s = Tcl_GetStringFromObj(value, &len);
|
||||
#if USE_TCL_UNICODE
|
||||
int byteorder = NATIVE_BYTEORDER;
|
||||
const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
|
||||
if (sizeof(Tcl_UniChar) == 2)
|
||||
return PyUnicode_DecodeUTF16((const char *)u, len * 2,
|
||||
"surrogatepass", &byteorder);
|
||||
else if (sizeof(Tcl_UniChar) == 4)
|
||||
return PyUnicode_DecodeUTF32((const char *)u, len * 4,
|
||||
"surrogatepass", &byteorder);
|
||||
else
|
||||
Py_UNREACHABLE();
|
||||
#else
|
||||
const char *s = Tcl_GetStringFromObj(value, &len);
|
||||
return unicodeFromTclStringAndSize(s, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -746,7 +787,7 @@ Tkapp_New(const char *screenName, const char *className,
|
|||
#endif
|
||||
|
||||
if (Tcl_AppInit(v->interp) != TCL_OK) {
|
||||
PyObject *result = Tkinter_Error((PyObject *)v);
|
||||
PyObject *result = Tkinter_Error(v);
|
||||
#ifdef TKINTER_PROTECT_LOADTK
|
||||
if (wantTk) {
|
||||
const char *_tkinter_tk_failed;
|
||||
|
@ -817,12 +858,6 @@ PyTclObject_dealloc(PyTclObject *self)
|
|||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static const char *
|
||||
PyTclObject_TclString(PyObject *self)
|
||||
{
|
||||
return Tcl_GetString(((PyTclObject*)self)->value);
|
||||
}
|
||||
|
||||
/* Like _str, but create Unicode if necessary. */
|
||||
PyDoc_STRVAR(PyTclObject_string__doc__,
|
||||
"the string representation of this object, either as str or bytes");
|
||||
|
@ -1048,53 +1083,51 @@ AsObj(PyObject *value)
|
|||
}
|
||||
|
||||
if (PyUnicode_Check(value)) {
|
||||
void *inbuf;
|
||||
Py_ssize_t size;
|
||||
int kind;
|
||||
Tcl_UniChar *outbuf = NULL;
|
||||
Py_ssize_t i;
|
||||
size_t allocsize;
|
||||
|
||||
if (PyUnicode_READY(value) == -1)
|
||||
return NULL;
|
||||
|
||||
inbuf = PyUnicode_DATA(value);
|
||||
size = PyUnicode_GET_LENGTH(value);
|
||||
if (size == 0)
|
||||
return Tcl_NewUnicodeObj((const void *)"", 0);
|
||||
Py_ssize_t size = PyUnicode_GET_LENGTH(value);
|
||||
if (size == 0) {
|
||||
return Tcl_NewStringObj("", 0);
|
||||
}
|
||||
if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
|
||||
PyErr_SetString(PyExc_OverflowError, "string is too long");
|
||||
return NULL;
|
||||
}
|
||||
kind = PyUnicode_KIND(value);
|
||||
if (kind == sizeof(Tcl_UniChar))
|
||||
return Tcl_NewUnicodeObj(inbuf, (int)size);
|
||||
allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
|
||||
outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
|
||||
/* Else overflow occurred, and we take the next exit */
|
||||
if (!outbuf) {
|
||||
PyErr_NoMemory();
|
||||
if (PyUnicode_IS_ASCII(value)) {
|
||||
return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
|
||||
(int)size);
|
||||
}
|
||||
|
||||
PyObject *encoded;
|
||||
#if USE_TCL_UNICODE
|
||||
if (sizeof(Tcl_UniChar) == 2)
|
||||
encoded = _PyUnicode_EncodeUTF16(value,
|
||||
"surrogatepass", NATIVE_BYTEORDER);
|
||||
else if (sizeof(Tcl_UniChar) == 4)
|
||||
encoded = _PyUnicode_EncodeUTF32(value,
|
||||
"surrogatepass", NATIVE_BYTEORDER);
|
||||
else
|
||||
Py_UNREACHABLE();
|
||||
#else
|
||||
encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
|
||||
#endif
|
||||
if (!encoded) {
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < size; i++) {
|
||||
Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
|
||||
/* We cannot test for sizeof(Tcl_UniChar) directly,
|
||||
so we test for UTF-8 size instead. */
|
||||
#if TCL_UTF_MAX == 3
|
||||
if (ch >= 0x10000) {
|
||||
/* Tcl doesn't do UTF-16, yet. */
|
||||
PyErr_Format(Tkinter_TclError,
|
||||
"character U+%x is above the range "
|
||||
"(U+0000-U+FFFF) allowed by Tcl",
|
||||
ch);
|
||||
PyMem_Free(outbuf);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
outbuf[i] = ch;
|
||||
size = PyBytes_GET_SIZE(encoded);
|
||||
if (size > INT_MAX) {
|
||||
Py_DECREF(encoded);
|
||||
PyErr_SetString(PyExc_OverflowError, "string is too long");
|
||||
return NULL;
|
||||
}
|
||||
result = Tcl_NewUnicodeObj(outbuf, (int)size);
|
||||
PyMem_Free(outbuf);
|
||||
#if USE_TCL_UNICODE
|
||||
result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
|
||||
(int)(size / sizeof(Tcl_UniChar)));
|
||||
#else
|
||||
result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
|
||||
#endif
|
||||
Py_DECREF(encoded);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1113,7 +1146,7 @@ AsObj(PyObject *value)
|
|||
}
|
||||
|
||||
static PyObject *
|
||||
fromBoolean(PyObject* tkapp, Tcl_Obj *value)
|
||||
fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
|
||||
{
|
||||
int boolValue;
|
||||
if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
|
||||
|
@ -1122,7 +1155,7 @@ fromBoolean(PyObject* tkapp, Tcl_Obj *value)
|
|||
}
|
||||
|
||||
static PyObject*
|
||||
fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
|
||||
fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
|
||||
{
|
||||
Tcl_WideInt wideValue;
|
||||
if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
|
||||
|
@ -1138,7 +1171,7 @@ fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
|
|||
|
||||
#ifdef HAVE_LIBTOMMAMTH
|
||||
static PyObject*
|
||||
fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
|
||||
fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
|
||||
{
|
||||
mp_int bigValue;
|
||||
unsigned long numBytes;
|
||||
|
@ -1174,32 +1207,31 @@ fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
|
|||
#endif
|
||||
|
||||
static PyObject*
|
||||
FromObj(PyObject* tkapp, Tcl_Obj *value)
|
||||
FromObj(TkappObject *tkapp, Tcl_Obj *value)
|
||||
{
|
||||
PyObject *result = NULL;
|
||||
TkappObject *app = (TkappObject*)tkapp;
|
||||
Tcl_Interp *interp = Tkapp_Interp(tkapp);
|
||||
|
||||
if (value->typePtr == NULL) {
|
||||
return unicodeFromTclStringAndSize(value->bytes, value->length);
|
||||
return unicodeFromTclObj(value);
|
||||
}
|
||||
|
||||
if (value->typePtr == app->BooleanType ||
|
||||
value->typePtr == app->OldBooleanType) {
|
||||
if (value->typePtr == tkapp->BooleanType ||
|
||||
value->typePtr == tkapp->OldBooleanType) {
|
||||
return fromBoolean(tkapp, value);
|
||||
}
|
||||
|
||||
if (value->typePtr == app->ByteArrayType) {
|
||||
if (value->typePtr == tkapp->ByteArrayType) {
|
||||
int size;
|
||||
char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
|
||||
return PyBytes_FromStringAndSize(data, size);
|
||||
}
|
||||
|
||||
if (value->typePtr == app->DoubleType) {
|
||||
if (value->typePtr == tkapp->DoubleType) {
|
||||
return PyFloat_FromDouble(value->internalRep.doubleValue);
|
||||
}
|
||||
|
||||
if (value->typePtr == app->IntType) {
|
||||
if (value->typePtr == tkapp->IntType) {
|
||||
long longValue;
|
||||
if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
|
||||
return PyLong_FromLong(longValue);
|
||||
|
@ -1207,8 +1239,8 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
|
|||
fall through to wideInt handling. */
|
||||
}
|
||||
|
||||
if (value->typePtr == app->IntType ||
|
||||
value->typePtr == app->WideIntType) {
|
||||
if (value->typePtr == tkapp->IntType ||
|
||||
value->typePtr == tkapp->WideIntType) {
|
||||
result = fromWideIntObj(tkapp, value);
|
||||
if (result != NULL || PyErr_Occurred())
|
||||
return result;
|
||||
|
@ -1218,14 +1250,14 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
|
|||
}
|
||||
|
||||
#ifdef HAVE_LIBTOMMAMTH
|
||||
if (value->typePtr == app->IntType ||
|
||||
value->typePtr == app->WideIntType ||
|
||||
value->typePtr == app->BignumType) {
|
||||
if (value->typePtr == tkapp->IntType ||
|
||||
value->typePtr == tkapp->WideIntType ||
|
||||
value->typePtr == tkapp->BignumType) {
|
||||
return fromBignumObj(tkapp, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (value->typePtr == app->ListType) {
|
||||
if (value->typePtr == tkapp->ListType) {
|
||||
int size;
|
||||
int i, status;
|
||||
PyObject *elem;
|
||||
|
@ -1253,30 +1285,28 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
|
|||
return result;
|
||||
}
|
||||
|
||||
if (value->typePtr == app->ProcBodyType) {
|
||||
if (value->typePtr == tkapp->ProcBodyType) {
|
||||
/* fall through: return tcl object. */
|
||||
}
|
||||
|
||||
if (value->typePtr == app->StringType) {
|
||||
return PyUnicode_FromKindAndData(
|
||||
sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
|
||||
Tcl_GetCharLength(value));
|
||||
if (value->typePtr == tkapp->StringType) {
|
||||
return unicodeFromTclObj(value);
|
||||
}
|
||||
|
||||
#if TK_HEX_VERSION >= 0x08050000
|
||||
if (app->BooleanType == NULL &&
|
||||
if (tkapp->BooleanType == NULL &&
|
||||
strcmp(value->typePtr->name, "booleanString") == 0) {
|
||||
/* booleanString type is not registered in Tcl */
|
||||
app->BooleanType = value->typePtr;
|
||||
tkapp->BooleanType = value->typePtr;
|
||||
return fromBoolean(tkapp, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBTOMMAMTH
|
||||
if (app->BignumType == NULL &&
|
||||
if (tkapp->BignumType == NULL &&
|
||||
strcmp(value->typePtr->name, "bignum") == 0) {
|
||||
/* bignum type is not registered in Tcl */
|
||||
app->BignumType = value->typePtr;
|
||||
tkapp->BignumType = value->typePtr;
|
||||
return fromBignumObj(tkapp, value);
|
||||
}
|
||||
#endif
|
||||
|
@ -1366,19 +1396,28 @@ finally:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert the results of a command call into a Python string. */
|
||||
|
||||
static PyObject *
|
||||
Tkapp_UnicodeResult(TkappObject *self)
|
||||
{
|
||||
return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
|
||||
}
|
||||
|
||||
|
||||
/* Convert the results of a command call into a Python objects. */
|
||||
|
||||
static PyObject*
|
||||
Tkapp_CallResult(TkappObject *self)
|
||||
static PyObject *
|
||||
Tkapp_ObjectResult(TkappObject *self)
|
||||
{
|
||||
PyObject *res = NULL;
|
||||
Tcl_Obj *value = Tcl_GetObjResult(self->interp);
|
||||
if(self->wantobjects) {
|
||||
if (self->wantobjects) {
|
||||
/* Not sure whether the IncrRef is necessary, but something
|
||||
may overwrite the interpreter result while we are
|
||||
converting it. */
|
||||
Tcl_IncrRefCount(value);
|
||||
res = FromObj((PyObject*)self, value);
|
||||
res = FromObj(self, value);
|
||||
Tcl_DecrRefCount(value);
|
||||
} else {
|
||||
res = unicodeFromTclObj(value);
|
||||
|
@ -1410,15 +1449,13 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
|
|||
i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
|
||||
ENTER_PYTHON
|
||||
if (i == TCL_ERROR) {
|
||||
*(e->res) = NULL;
|
||||
*(e->exc_type) = NULL;
|
||||
*(e->exc_tb) = NULL;
|
||||
*(e->exc_value) = PyObject_CallFunction(
|
||||
Tkinter_TclError, "s",
|
||||
Tcl_GetStringResult(e->self->interp));
|
||||
*(e->res) = Tkinter_Error(e->self);
|
||||
}
|
||||
else {
|
||||
*(e->res) = Tkapp_CallResult(e->self);
|
||||
*(e->res) = Tkapp_ObjectResult(e->self);
|
||||
}
|
||||
if (*(e->res) == NULL) {
|
||||
PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
|
||||
}
|
||||
LEAVE_PYTHON
|
||||
|
||||
|
@ -1506,9 +1543,9 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
|
|||
ENTER_OVERLAP
|
||||
|
||||
if (i == TCL_ERROR)
|
||||
Tkinter_Error(selfptr);
|
||||
Tkinter_Error(self);
|
||||
else
|
||||
res = Tkapp_CallResult(self);
|
||||
res = Tkapp_ObjectResult(self);
|
||||
|
||||
LEAVE_OVERLAP_TCL
|
||||
|
||||
|
@ -1540,9 +1577,9 @@ _tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
|
|||
err = Tcl_Eval(Tkapp_Interp(self), script);
|
||||
ENTER_OVERLAP
|
||||
if (err == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = unicodeFromTclString(Tkapp_Result(self));
|
||||
res = Tkapp_UnicodeResult(self);
|
||||
LEAVE_OVERLAP_TCL
|
||||
return res;
|
||||
}
|
||||
|
@ -1569,9 +1606,9 @@ _tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
|
|||
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
|
||||
ENTER_OVERLAP
|
||||
if (err == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = unicodeFromTclString(Tkapp_Result(self));
|
||||
res = Tkapp_UnicodeResult(self);
|
||||
LEAVE_OVERLAP_TCL
|
||||
return res;
|
||||
}
|
||||
|
@ -1598,9 +1635,9 @@ _tkinter_tkapp_record_impl(TkappObject *self, const char *script)
|
|||
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
|
||||
ENTER_OVERLAP
|
||||
if (err == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = unicodeFromTclString(Tkapp_Result(self));
|
||||
res = Tkapp_UnicodeResult(self);
|
||||
LEAVE_OVERLAP_TCL
|
||||
return res;
|
||||
}
|
||||
|
@ -1631,13 +1668,13 @@ _tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
|
|||
|
||||
/** Tcl Variable **/
|
||||
|
||||
typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
|
||||
typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
|
||||
|
||||
TCL_DECLARE_MUTEX(var_mutex)
|
||||
|
||||
typedef struct VarEvent {
|
||||
Tcl_Event ev; /* must be first */
|
||||
PyObject *self;
|
||||
TkappObject *self;
|
||||
PyObject *args;
|
||||
int flags;
|
||||
EventFunc func;
|
||||
|
@ -1692,7 +1729,7 @@ varname_converter(PyObject *in, void *_out)
|
|||
return 1;
|
||||
}
|
||||
if (PyTclObject_Check(in)) {
|
||||
*out = PyTclObject_TclString(in);
|
||||
*out = Tcl_GetString(((PyTclObject *)in)->value);
|
||||
return 1;
|
||||
}
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
|
@ -1750,7 +1787,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
|
|||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
ev->self = selfptr;
|
||||
ev->self = self;
|
||||
ev->args = args;
|
||||
ev->flags = flags;
|
||||
ev->func = func;
|
||||
|
@ -1770,11 +1807,11 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
|
|||
return res;
|
||||
}
|
||||
/* Tcl is not threaded, or this is the interpreter thread. */
|
||||
return func(selfptr, args, flags);
|
||||
return func(self, args, flags);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
SetVar(PyObject *self, PyObject *args, int flags)
|
||||
SetVar(TkappObject *self, PyObject *args, int flags)
|
||||
{
|
||||
const char *name1, *name2;
|
||||
PyObject *newValue;
|
||||
|
@ -1843,7 +1880,7 @@ Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
|
|||
|
||||
|
||||
static PyObject *
|
||||
GetVar(PyObject *self, PyObject *args, int flags)
|
||||
GetVar(TkappObject *self, PyObject *args, int flags)
|
||||
{
|
||||
const char *name1, *name2=NULL;
|
||||
PyObject *res = NULL;
|
||||
|
@ -1858,10 +1895,9 @@ GetVar(PyObject *self, PyObject *args, int flags)
|
|||
tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
|
||||
ENTER_OVERLAP
|
||||
if (tres == NULL) {
|
||||
PyErr_SetString(Tkinter_TclError,
|
||||
Tcl_GetStringResult(Tkapp_Interp(self)));
|
||||
Tkinter_Error(self);
|
||||
} else {
|
||||
if (((TkappObject*)self)->wantobjects) {
|
||||
if (self->wantobjects) {
|
||||
res = FromObj(self, tres);
|
||||
}
|
||||
else {
|
||||
|
@ -1887,7 +1923,7 @@ Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
|
|||
|
||||
|
||||
static PyObject *
|
||||
UnsetVar(PyObject *self, PyObject *args, int flags)
|
||||
UnsetVar(TkappObject *self, PyObject *args, int flags)
|
||||
{
|
||||
char *name1, *name2=NULL;
|
||||
int code;
|
||||
|
@ -1959,7 +1995,7 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
|
|||
CHECK_STRING_LENGTH(s);
|
||||
value = Tcl_NewStringObj(s, -1);
|
||||
if (value == NULL)
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
}
|
||||
/* Don't use Tcl_GetInt() because it returns ambiguous result for value
|
||||
in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
|
||||
|
@ -1968,14 +2004,14 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
|
|||
value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
|
||||
*/
|
||||
#ifdef HAVE_LIBTOMMAMTH
|
||||
result = fromBignumObj((PyObject *)self, value);
|
||||
result = fromBignumObj(self, value);
|
||||
#else
|
||||
result = fromWideIntObj((PyObject *)self, value);
|
||||
result = fromWideIntObj(self, value);
|
||||
#endif
|
||||
Tcl_DecrRefCount(value);
|
||||
if (result != NULL || PyErr_Occurred())
|
||||
return result;
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -2006,7 +2042,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
|
|||
if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
|
||||
((PyTclObject*)arg)->value,
|
||||
&v) == TCL_ERROR)
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
return PyFloat_FromDouble(v);
|
||||
}
|
||||
|
||||
|
@ -2014,7 +2050,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
|
|||
return NULL;
|
||||
CHECK_STRING_LENGTH(s);
|
||||
if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
return PyFloat_FromDouble(v);
|
||||
}
|
||||
|
||||
|
@ -2041,7 +2077,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
|
|||
if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
|
||||
((PyTclObject*)arg)->value,
|
||||
&v) == TCL_ERROR)
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
return PyBool_FromLong(v);
|
||||
}
|
||||
|
||||
|
@ -2049,7 +2085,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
|
|||
return NULL;
|
||||
CHECK_STRING_LENGTH(s);
|
||||
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
return PyBool_FromLong(v);
|
||||
}
|
||||
|
||||
|
@ -2075,9 +2111,9 @@ _tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
|
|||
retval = Tcl_ExprString(Tkapp_Interp(self), s);
|
||||
ENTER_OVERLAP
|
||||
if (retval == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = unicodeFromTclString(Tkapp_Result(self));
|
||||
res = Tkapp_UnicodeResult(self);
|
||||
LEAVE_OVERLAP_TCL
|
||||
return res;
|
||||
}
|
||||
|
@ -2105,7 +2141,7 @@ _tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
|
|||
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
|
||||
ENTER_OVERLAP
|
||||
if (retval == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = PyLong_FromLong(v);
|
||||
LEAVE_OVERLAP_TCL
|
||||
|
@ -2136,7 +2172,7 @@ _tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
|
|||
ENTER_OVERLAP
|
||||
PyFPE_END_PROTECT(retval)
|
||||
if (retval == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = PyFloat_FromDouble(v);
|
||||
LEAVE_OVERLAP_TCL
|
||||
|
@ -2165,7 +2201,7 @@ _tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
|
|||
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
|
||||
ENTER_OVERLAP
|
||||
if (retval == TCL_ERROR)
|
||||
res = Tkinter_Error((PyObject *)self);
|
||||
res = Tkinter_Error(self);
|
||||
else
|
||||
res = PyLong_FromLong(v);
|
||||
LEAVE_OVERLAP_TCL
|
||||
|
@ -2198,12 +2234,12 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
|
|||
if (Tcl_ListObjGetElements(Tkapp_Interp(self),
|
||||
((PyTclObject*)arg)->value,
|
||||
&objc, &objv) == TCL_ERROR) {
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
}
|
||||
if (!(v = PyTuple_New(objc)))
|
||||
return NULL;
|
||||
for (i = 0; i < objc; i++) {
|
||||
PyObject *s = FromObj((PyObject*)self, objv[i]);
|
||||
PyObject *s = FromObj(self, objv[i]);
|
||||
if (!s) {
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
|
@ -2231,7 +2267,7 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
|
|||
if (Tcl_SplitList(Tkapp_Interp(self), list,
|
||||
&argc, &argv) == TCL_ERROR) {
|
||||
PyMem_Free(list);
|
||||
return Tkinter_Error((PyObject *)self);
|
||||
return Tkinter_Error(self);
|
||||
}
|
||||
|
||||
if (!(v = PyTuple_New(argc)))
|
||||
|
@ -2275,16 +2311,16 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
|
|||
int i;
|
||||
if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
|
||||
&objc, &objv) == TCL_ERROR) {
|
||||
return FromObj((PyObject*)self, value);
|
||||
return FromObj(self, value);
|
||||
}
|
||||
if (objc == 0)
|
||||
return PyUnicode_FromString("");
|
||||
if (objc == 1)
|
||||
return FromObj((PyObject*)self, objv[0]);
|
||||
return FromObj(self, objv[0]);
|
||||
if (!(v = PyTuple_New(objc)))
|
||||
return NULL;
|
||||
for (i = 0; i < objc; i++) {
|
||||
PyObject *s = FromObj((PyObject*)self, objv[i]);
|
||||
PyObject *s = FromObj(self, objv[i]);
|
||||
if (!s) {
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
|
@ -2331,34 +2367,31 @@ PythonCmd_Error(Tcl_Interp *interp)
|
|||
* function or method.
|
||||
*/
|
||||
static int
|
||||
PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
|
||||
PythonCmd(ClientData clientData, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const objv[])
|
||||
{
|
||||
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
|
||||
PyObject *func, *arg, *res;
|
||||
int i, rv;
|
||||
PyObject *args, *res;
|
||||
int i;
|
||||
Tcl_Obj *obj_res;
|
||||
|
||||
ENTER_PYTHON
|
||||
|
||||
/* TBD: no error checking here since we know, via the
|
||||
* Tkapp_CreateCommand() that the client data is a two-tuple
|
||||
*/
|
||||
func = data->func;
|
||||
|
||||
/* Create argument list (argv1, ..., argvN) */
|
||||
if (!(arg = PyTuple_New(argc - 1)))
|
||||
/* Create argument tuple (objv1, ..., objvN) */
|
||||
if (!(args = PyTuple_New(objc - 1)))
|
||||
return PythonCmd_Error(interp);
|
||||
|
||||
for (i = 0; i < (argc - 1); i++) {
|
||||
PyObject *s = unicodeFromTclString(argv[i + 1]);
|
||||
for (i = 0; i < (objc - 1); i++) {
|
||||
PyObject *s = unicodeFromTclObj(objv[i + 1]);
|
||||
if (!s) {
|
||||
Py_DECREF(arg);
|
||||
Py_DECREF(args);
|
||||
return PythonCmd_Error(interp);
|
||||
}
|
||||
PyTuple_SET_ITEM(arg, i, s);
|
||||
PyTuple_SET_ITEM(args, i, s);
|
||||
}
|
||||
res = PyObject_Call(func, arg, NULL);
|
||||
Py_DECREF(arg);
|
||||
|
||||
res = PyObject_Call(data->func, args, NULL);
|
||||
Py_DECREF(args);
|
||||
|
||||
if (res == NULL)
|
||||
return PythonCmd_Error(interp);
|
||||
|
@ -2368,18 +2401,15 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[
|
|||
Py_DECREF(res);
|
||||
return PythonCmd_Error(interp);
|
||||
}
|
||||
else {
|
||||
Tcl_SetObjResult(interp, obj_res);
|
||||
rv = TCL_OK;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, obj_res);
|
||||
Py_DECREF(res);
|
||||
|
||||
LEAVE_PYTHON
|
||||
|
||||
return rv;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
PythonCmdDelete(ClientData clientData)
|
||||
{
|
||||
|
@ -2411,7 +2441,7 @@ static int
|
|||
Tkapp_CommandProc(CommandEvent *ev, int flags)
|
||||
{
|
||||
if (ev->create)
|
||||
*ev->status = Tcl_CreateCommand(
|
||||
*ev->status = Tcl_CreateObjCommand(
|
||||
ev->interp, ev->name, PythonCmd,
|
||||
ev->data, PythonCmdDelete) == NULL;
|
||||
else
|
||||
|
@ -2477,7 +2507,7 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
|
|||
else
|
||||
{
|
||||
ENTER_TCL
|
||||
err = Tcl_CreateCommand(
|
||||
err = Tcl_CreateObjCommand(
|
||||
Tkapp_Interp(self), name, PythonCmd,
|
||||
(ClientData)data, PythonCmdDelete) == NULL;
|
||||
LEAVE_TCL
|
||||
|
@ -2953,9 +2983,9 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
|
|||
if (err == TCL_ERROR) {
|
||||
/* This sets an exception, but we cannot return right
|
||||
away because we need to exit the overlap first. */
|
||||
Tkinter_Error((PyObject *)self);
|
||||
Tkinter_Error(self);
|
||||
} else {
|
||||
_tk_exists = Tkapp_Result(self);
|
||||
_tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
|
||||
}
|
||||
LEAVE_OVERLAP_TCL
|
||||
if (err == TCL_ERROR) {
|
||||
|
@ -2963,8 +2993,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
|
|||
}
|
||||
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
|
||||
if (Tk_Init(interp) == TCL_ERROR) {
|
||||
PyErr_SetString(Tkinter_TclError,
|
||||
Tcl_GetStringResult(Tkapp_Interp(self)));
|
||||
Tkinter_Error(self);
|
||||
#ifdef TKINTER_PROTECT_LOADTK
|
||||
tk_load_failed = 1;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue