diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-26 00:13:12 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-26 00:13:12 (GMT) |
commit | c366117820eb34e14f4bf2b1f82a47b7a9cbc04a (patch) | |
tree | a9a703511caf473574a2d312c5143fa2c8486beb /Modules | |
parent | f0effe637988e936b5a6ece2da789b67723d675c (diff) | |
parent | 0fdfceb782424dcddca848357736f24ef40c91be (diff) | |
download | cpython-c366117820eb34e14f4bf2b1f82a47b7a9cbc04a.zip cpython-c366117820eb34e14f4bf2b1f82a47b7a9cbc04a.tar.gz cpython-c366117820eb34e14f4bf2b1f82a47b7a9cbc04a.tar.bz2 |
Merge heads
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_cursesmodule.c | 576 |
1 files changed, 468 insertions, 108 deletions
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index cfa5b7a..166a93a 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -121,6 +121,10 @@ extern int setupterm(char *,int,int *); #include <term.h> #endif +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif + #if !defined(HAVE_NCURSES_H) && (defined(sgi) || defined(__sun) || defined(SCO5)) #define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ typedef chtype attr_t; /* No attr_t type is available */ @@ -143,6 +147,8 @@ static int initialised = FALSE; /* Tells whether start_color() has been called to initialise color usage. */ static int initialisedcolors = FALSE; +static char *screen_encoding = NULL; + /* Utility Macros */ #define PyCursesSetupTermCalled \ if (initialised_setupterm != TRUE) { \ @@ -175,7 +181,7 @@ static int initialisedcolors = FALSE; */ static PyObject * -PyCursesCheckERR(int code, char *fname) +PyCursesCheckERR(int code, const char *fname) { if (code != ERR) { Py_INCREF(Py_None); @@ -190,28 +196,193 @@ PyCursesCheckERR(int code, char *fname) } } +/* Convert an object to a byte (an integer of type chtype): + + - int + - bytes of length 1 + - str of length 1 + + Return 1 on success, 0 on error (invalid type or integer overflow). */ static int -PyCurses_ConvertToChtype(PyObject *obj, chtype *ch) +PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch) { - if (PyLong_CheckExact(obj)) { - int overflow; - /* XXX should the truncation by the cast also be reported - as an error? */ - *ch = (chtype) PyLong_AsLongAndOverflow(obj, &overflow); - if (overflow) + long value; + if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { + value = (unsigned char)PyBytes_AsString(obj)[0]; + } + else if (PyUnicode_Check(obj)) { + if (PyUnicode_GetLength(obj) != 1) { + PyErr_Format(PyExc_TypeError, + "expect bytes or str of length 1, or int, " + "got a str of length %zi", + PyUnicode_GET_LENGTH(obj)); return 0; - } else if(PyBytes_Check(obj) - && (PyBytes_Size(obj) == 1)) { - *ch = (chtype) *PyBytes_AsString(obj); - } else if (PyUnicode_Check(obj) && PyUnicode_GET_LENGTH(obj) == 1) { - Py_UCS4 ucs = PyUnicode_READ(PyUnicode_KIND(obj), - PyUnicode_DATA(obj), - 0); - *ch = (chtype)ucs; - } else { + } + value = PyUnicode_READ_CHAR(obj, 0); + if (128 < value) { + PyObject *bytes; + const char *encoding; + if (win) + encoding = win->encoding; + else + encoding = screen_encoding; + bytes = PyUnicode_AsEncodedObject(obj, encoding, NULL); + if (bytes == NULL) + return 0; + if (PyBytes_GET_SIZE(bytes) == 1) + value = (unsigned char)PyBytes_AS_STRING(bytes)[0]; + else + value = -1; + Py_DECREF(bytes); + if (value < 0) + goto overflow; + } + } + else if (PyLong_CheckExact(obj)) { + int long_overflow; + value = PyLong_AsLongAndOverflow(obj, &long_overflow); + if (long_overflow) + goto overflow; + } + else { + PyErr_Format(PyExc_TypeError, + "expect bytes or str of length 1, or int, got %s", + Py_TYPE(obj)->tp_name); return 0; } + *ch = (chtype)value; + if ((long)*ch != value) + goto overflow; return 1; + +overflow: + PyErr_SetString(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; +} + +/* Convert an object to a byte (chtype) or a character (cchar_t): + + - int + - bytes of length 1 + - str of length 1 + + Return: + + - 2 if obj is a character (written into *wch) + - 1 if obj is a byte (written into *ch) + - 0 on error: raise an exception */ +static int +PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj, + chtype *ch +#ifdef HAVE_NCURSESW + , cchar_t *wch +#endif + ) +{ + int ret = 0; + long value; +#ifdef HAVE_NCURSESW + wchar_t buffer[2]; +#endif + + if (PyUnicode_Check(obj)) { +#ifdef HAVE_NCURSESW + if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { + PyErr_Format(PyExc_TypeError, + "expect bytes or str of length 1, or int, " + "got a str of length %zi", + PyUnicode_GET_LENGTH(obj)); + return 0; + } + memset(wch->chars, 0, sizeof(wch->chars)); + wch->chars[0] = buffer[0]; + return 2; +#else + return PyCurses_ConvertToChtype(win, obj, ch); +#endif + } + else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { + value = (unsigned char)PyBytes_AsString(obj)[0]; + ret = 1; + } + else if (PyLong_CheckExact(obj)) { + int overflow; + value = PyLong_AsLongAndOverflow(obj, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, + "int doesn't fit in long"); + return 0; + } +#ifdef HAVE_NCURSESW + ret = 2; +#else + ret = 1; +#endif + } + else { + PyErr_Format(PyExc_TypeError, + "expect bytes or str of length 1, or int, got %s", + Py_TYPE(obj)->tp_name); + return 0; + } +#ifdef HAVE_NCURSESW + if (ret == 2) { + memset(wch->chars, 0, sizeof(wch->chars)); + wch->chars[0] = (wchar_t)value; + if ((long)wch->chars[0] != value) { + PyErr_Format(PyExc_OverflowError, + "character doesn't fit in wchar_t"); + return 0; + } + } + else +#endif + { + *ch = (chtype)value; + if ((long)*ch != value || value < 0 || value > 255) { + PyErr_Format(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; + } + } + return ret; +} + +/* Convert an object to a byte string (char*) or a wide character string + (wchar_t*). Return: + + - 2 if obj is a character string (written into *wch) + - 1 if obj is a byte string (written into *bytes) + - 0 on error: raise an exception */ +static int +PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj, + PyObject **bytes, wchar_t **wstr) +{ + if (PyUnicode_Check(obj)) { +#ifdef HAVE_NCURSESW + assert (wstr != NULL); + *wstr = PyUnicode_AsWideCharString(obj, NULL); + if (*wstr == NULL) + return 0; + return 2; +#else + assert (wstr == NULL); + *bytes = PyUnicode_AsEncodedObject(obj, win->encoding, NULL); + if (*bytes == NULL) + return 0; + return 1; +#endif + } + else if (PyBytes_Check(obj)) { + Py_INCREF(obj); + *bytes = obj; + return 1; + } + + PyErr_Format(PyExc_TypeError, "expect bytes or str, got %s", + Py_TYPE(obj)->tp_name); + return 0; } /* Function versions of the 3 functions for testing whether curses has been @@ -357,13 +528,37 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") /* Allocation and deallocation of Window Objects */ static PyObject * -PyCursesWindow_New(WINDOW *win) +PyCursesWindow_New(WINDOW *win, const char *encoding) { PyCursesWindowObject *wo; + if (encoding == NULL) { +#if defined(MS_WINDOWS) + char *buffer[100]; + UINT cp; + cp = GetConsoleOutputCP(); + if (cp != 0) { + PyOS_snprintf(buffer, sizeof(buffer), "cp%u", cp); + encoding = buffer; + } +#elif defined(CODESET) + const char *codeset = nl_langinfo(CODESET); + if (codeset != NULL && codeset[0] != 0) + encoding = codeset; +#endif + if (encoding == NULL) + encoding = "utf-8"; + } + wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type); if (wo == NULL) return NULL; wo->win = win; + wo->encoding = strdup(encoding); + if (wo->encoding == NULL) { + Py_DECREF(wo); + PyErr_NoMemory(); + return NULL; + } return (PyObject *)wo; } @@ -371,6 +566,8 @@ static void PyCursesWindow_Dealloc(PyCursesWindowObject *wo) { if (wo->win != stdscr) delwin(wo->win); + if (wo->encoding != NULL) + free(wo->encoding); PyObject_DEL(wo); } @@ -380,29 +577,34 @@ static PyObject * PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args) { int rtn, x, y, use_xy = FALSE; - PyObject *temp; - chtype ch = 0; + PyObject *chobj; + int type; + chtype ch; +#ifdef HAVE_NCURSESW + cchar_t wch; +#endif attr_t attr = A_NORMAL; long lattr; + const char *funcname; switch (PyTuple_Size(args)) { case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) + if (!PyArg_ParseTuple(args, "O;ch or int", &chobj)) return NULL; break; case 2: - if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr)) + if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &chobj, &lattr)) return NULL; attr = lattr; break; case 3: - if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp)) + if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &chobj)) return NULL; use_xy = TRUE; break; case 4: if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", - &y, &x, &temp, &lattr)) + &y, &x, &chobj, &lattr)) return NULL; attr = lattr; use_xy = TRUE; @@ -412,17 +614,33 @@ PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args) return NULL; } - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, "argument 1 or 3 must be a ch or an int"); - return NULL; +#ifdef HAVE_NCURSESW + type = PyCurses_ConvertToCchar_t(self, chobj, &ch, &wch); + if (type == 2) { + funcname = "add_wch"; + wch.attr = attr; + if (use_xy == TRUE) + rtn = mvwadd_wch(self->win,y,x, &wch); + else { + rtn = wadd_wch(self->win, &wch); + } + } + else +#else + type = PyCurses_ConvertToCchar_t(self, chobj, &ch); +#endif + if (type == 1) { + funcname = "addch"; + if (use_xy == TRUE) + rtn = mvwaddch(self->win,y,x, ch | attr); + else { + rtn = waddch(self->win, ch | attr); + } } - - if (use_xy == TRUE) - rtn = mvwaddch(self->win,y,x, ch | attr); else { - rtn = waddch(self->win, ch | attr); + return NULL; } - return PyCursesCheckERR(rtn, "addch"); + return PyCursesCheckERR(rtn, funcname); } static PyObject * @@ -430,29 +648,34 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) { int rtn; int x, y; - char *str; + int strtype; + PyObject *strobj, *bytesobj; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif attr_t attr = A_NORMAL , attr_old = A_NORMAL; long lattr; int use_xy = FALSE, use_attr = FALSE; + const char *funcname; switch (PyTuple_Size(args)) { case 1: - if (!PyArg_ParseTuple(args,"s;str", &str)) + if (!PyArg_ParseTuple(args,"O;str", &strobj)) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &lattr)) + if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) return NULL; attr = lattr; use_attr = TRUE; break; case 3: - if (!PyArg_ParseTuple(args,"iis;int,int,str", &y, &x, &str)) + if (!PyArg_ParseTuple(args,"iiO;int,int,str", &y, &x, &strobj)) return NULL; use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisl;int,int,str,attr", &y, &x, &str, &lattr)) + if (!PyArg_ParseTuple(args,"iiOl;int,int,str,attr", &y, &x, &strobj, &lattr)) return NULL; attr = lattr; use_xy = use_attr = TRUE; @@ -461,47 +684,74 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) PyErr_SetString(PyExc_TypeError, "addstr requires 1 to 4 arguments"); return NULL; } - +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; if (use_attr == TRUE) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } - if (use_xy == TRUE) - rtn = mvwaddstr(self->win,y,x,str); +#ifdef HAVE_NCURSESW + if (strtype == 2) { + funcname = "addwstr"; + if (use_xy == TRUE) + rtn = mvwaddwstr(self->win,y,x,wstr); + else + rtn = waddwstr(self->win,wstr); + PyMem_Free(wstr); + } else - rtn = waddstr(self->win,str); +#endif + { + char *str = PyBytes_AS_STRING(bytesobj); + funcname = "addstr"; + if (use_xy == TRUE) + rtn = mvwaddstr(self->win,y,x,str); + else + rtn = waddstr(self->win,str); + Py_DECREF(bytesobj); + } if (use_attr == TRUE) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, "addstr"); + return PyCursesCheckERR(rtn, funcname); } static PyObject * PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) { int rtn, x, y, n; - char *str; + int strtype; + PyObject *strobj, *bytesobj; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif attr_t attr = A_NORMAL , attr_old = A_NORMAL; long lattr; int use_xy = FALSE, use_attr = FALSE; + const char *funcname; switch (PyTuple_Size(args)) { case 2: - if (!PyArg_ParseTuple(args,"si;str,n", &str, &n)) + if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) return NULL; break; case 3: - if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &lattr)) + if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) return NULL; attr = lattr; use_attr = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisi;y,x,str,n", &y, &x, &str, &n)) + if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) return NULL; use_xy = TRUE; break; case 5: - if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &lattr)) + if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) return NULL; attr = lattr; use_xy = use_attr = TRUE; @@ -510,18 +760,41 @@ PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) PyErr_SetString(PyExc_TypeError, "addnstr requires 2 to 5 arguments"); return NULL; } +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; if (use_attr == TRUE) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } - if (use_xy == TRUE) - rtn = mvwaddnstr(self->win,y,x,str,n); +#ifdef HAVE_NCURSESW + if (strtype == 2) { + funcname = "addnwstr"; + if (use_xy == TRUE) + rtn = mvwaddnwstr(self->win,y,x,wstr,n); + else + rtn = waddnwstr(self->win,wstr,n); + PyMem_Free(wstr); + } else - rtn = waddnstr(self->win,str,n); +#endif + { + char *str = PyBytes_AS_STRING(bytesobj); + funcname = "addnstr"; + if (use_xy == TRUE) + rtn = mvwaddnstr(self->win,y,x,str,n); + else + rtn = waddnstr(self->win,str,n); + Py_DECREF(bytesobj); + } if (use_attr == TRUE) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, "addnstr"); + return PyCursesCheckERR(rtn, funcname); } static PyObject * @@ -547,10 +820,8 @@ PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) return NULL; } - if (!PyCurses_ConvertToChtype(temp, &bkgd)) { - PyErr_SetString(PyExc_TypeError, "argument 1 or 3 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) return NULL; - } return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); } @@ -605,10 +876,8 @@ PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args) return NULL; } - if (!PyCurses_ConvertToChtype(temp, &bkgd)) { - PyErr_SetString(PyExc_TypeError, "argument 1 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) return NULL; - } wbkgdset(self->win, bkgd | attr); return PyCursesCheckERR(0, "bkgdset"); @@ -633,11 +902,8 @@ PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args) return NULL; for(i=0; i<8; i++) { - if (temp[i] != NULL && !PyCurses_ConvertToChtype(temp[i], &ch[i])) { - PyErr_Format(PyExc_TypeError, - "argument %i must be a ch or an int", i+1); + if (temp[i] != NULL && !PyCurses_ConvertToChtype(self, temp[i], &ch[i])) return NULL; - } } wborder(self->win, @@ -782,7 +1048,7 @@ PyCursesWindow_DerWin(PyCursesWindowObject *self, PyObject *args) return NULL; } - return (PyObject *)PyCursesWindow_New(win); + return (PyObject *)PyCursesWindow_New(win, NULL); } static PyObject * @@ -810,10 +1076,8 @@ PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) return NULL; } - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, "argument 1 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &ch)) return NULL; - } #ifdef WINDOW_HAS_FLAGS if (self->win->_flags & _ISPAD) @@ -1034,11 +1298,8 @@ PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) } if (code != ERR) { - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, - "argument 1 or 3 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &ch)) return NULL; - } return PyCursesCheckERR(whline(self->win, ch | attr, n), "hline"); } else return PyCursesCheckERR(code, "wmove"); @@ -1079,11 +1340,8 @@ PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) return NULL; } - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, - "argument 1 or 3 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &ch)) return NULL; - } if (use_xy == TRUE) rtn = mvwinsch(self->win,y,x, ch | attr); @@ -1154,29 +1412,34 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) { int rtn; int x, y; - char *str; + int strtype; + PyObject *strobj, *bytesobj; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif attr_t attr = A_NORMAL , attr_old = A_NORMAL; long lattr; int use_xy = FALSE, use_attr = FALSE; + const char *funcname; switch (PyTuple_Size(args)) { case 1: - if (!PyArg_ParseTuple(args,"s;str", &str)) + if (!PyArg_ParseTuple(args,"O;str", &strobj)) return NULL; break; case 2: - if (!PyArg_ParseTuple(args,"sl;str,attr", &str, &lattr)) + if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) return NULL; attr = lattr; use_attr = TRUE; break; case 3: - if (!PyArg_ParseTuple(args,"iis;y,x,str", &y, &x, &str)) + if (!PyArg_ParseTuple(args,"iiO;y,x,str", &y, &x, &strobj)) return NULL; use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisl;y,x,str,attr", &y, &x, &str, &lattr)) + if (!PyArg_ParseTuple(args,"iiOl;y,x,str,attr", &y, &x, &strobj, &lattr)) return NULL; attr = lattr; use_xy = use_attr = TRUE; @@ -1186,46 +1449,75 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) return NULL; } +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; + if (use_attr == TRUE) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } - if (use_xy == TRUE) - rtn = mvwinsstr(self->win,y,x,str); +#ifdef HAVE_NCURSESW + if (strtype == 2) { + funcname = "inswstr"; + if (use_xy == TRUE) + rtn = mvwins_wstr(self->win,y,x,wstr); + else + rtn = wins_wstr(self->win,wstr); + PyMem_Free(wstr); + } else - rtn = winsstr(self->win,str); +#endif + { + char *str = PyBytes_AS_STRING(bytesobj); + funcname = "insstr"; + if (use_xy == TRUE) + rtn = mvwinsstr(self->win,y,x,str); + else + rtn = winsstr(self->win,str); + Py_DECREF(bytesobj); + } if (use_attr == TRUE) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, "insstr"); + return PyCursesCheckERR(rtn, funcname); } static PyObject * PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) { int rtn, x, y, n; - char *str; + int strtype; + PyObject *strobj, *bytesobj; +#ifdef HAVE_NCURSESW + wchar_t *wstr = NULL; +#endif attr_t attr = A_NORMAL , attr_old = A_NORMAL; long lattr; int use_xy = FALSE, use_attr = FALSE; + const char *funcname; switch (PyTuple_Size(args)) { case 2: - if (!PyArg_ParseTuple(args,"si;str,n", &str, &n)) + if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) return NULL; break; case 3: - if (!PyArg_ParseTuple(args,"sil;str,n,attr", &str, &n, &lattr)) + if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) return NULL; attr = lattr; use_attr = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iisi;y,x,str,n", &y, &x, &str, &n)) + if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) return NULL; use_xy = TRUE; break; case 5: - if (!PyArg_ParseTuple(args,"iisil;y,x,str,n,attr", &y, &x, &str, &n, &lattr)) + if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) return NULL; attr = lattr; use_xy = use_attr = TRUE; @@ -1235,17 +1527,41 @@ PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) return NULL; } +#ifdef HAVE_NCURSESW + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); +#else + strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); +#endif + if (strtype == 0) + return NULL; + if (use_attr == TRUE) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } - if (use_xy == TRUE) - rtn = mvwinsnstr(self->win,y,x,str,n); +#ifdef HAVE_NCURSESW + if (strtype == 2) { + funcname = "insn_wstr"; + if (use_xy == TRUE) + rtn = mvwins_nwstr(self->win,y,x,wstr,n); + else + rtn = wins_nwstr(self->win,wstr,n); + PyMem_Free(wstr); + } else - rtn = winsnstr(self->win,str,n); +#endif + { + char *str = PyBytes_AS_STRING(bytesobj); + funcname = "insnstr"; + if (use_xy == TRUE) + rtn = mvwinsnstr(self->win,y,x,str,n); + else + rtn = winsnstr(self->win,str,n); + Py_DECREF(bytesobj); + } if (use_attr == TRUE) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, "insnstr"); + return PyCursesCheckERR(rtn, funcname); } static PyObject * @@ -1528,7 +1844,7 @@ PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args) return NULL; } - return (PyObject *)PyCursesWindow_New(win); + return (PyObject *)PyCursesWindow_New(win, self->encoding); } static PyObject * @@ -1604,16 +1920,51 @@ PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) } if (code != ERR) { - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, - "argument 1 or 3 must be a ch or an int"); + if (!PyCurses_ConvertToChtype(self, temp, &ch)) return NULL; - } return PyCursesCheckERR(wvline(self->win, ch | attr, n), "vline"); } else return PyCursesCheckERR(code, "wmove"); } +static PyObject * +PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure) +{ + return PyUnicode_FromString(self->encoding); +} + +static int +PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value) +{ + PyObject *ascii; + char *encoding; + + /* It is illegal to del win.encoding */ + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "encoding may not be deleted"); + return -1; + } + + if (!PyUnicode_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "setting encoding to a non-string"); + return -1; + } + ascii = PyUnicode_AsASCIIString(value); + if (ascii == NULL) + return -1; + encoding = strdup(PyBytes_AS_STRING(ascii)); + if (encoding == NULL) { + PyErr_NoMemory(); + return -1; + } + free(self->encoding); + self->encoding = encoding; + return 0; +} + + static PyMethodDef PyCursesWindow_Methods[] = { {"addch", (PyCFunction)PyCursesWindow_AddCh, METH_VARARGS}, {"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS}, @@ -1701,6 +2052,13 @@ static PyMethodDef PyCursesWindow_Methods[] = { {NULL, NULL} /* sentinel */ }; +static PyGetSetDef PyCursesWindow_getsets[] = { + {"encoding", + (getter)PyCursesWindow_get_encoding, + (setter)PyCursesWindow_set_encoding, + "the typecode character used to create the array"} +}; + /* -------------------------------------------------------*/ PyTypeObject PyCursesWindow_Type = { @@ -1733,6 +2091,8 @@ PyTypeObject PyCursesWindow_Type = { 0, /*tp_iter*/ 0, /*tp_iternext*/ PyCursesWindow_Methods, /*tp_methods*/ + 0, /* tp_members */ + PyCursesWindow_getsets, /* tp_getset */ }; /********************************************************************* @@ -1956,7 +2316,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) PyErr_SetString(PyCursesError, catchall_NULL); return NULL; } - return PyCursesWindow_New(win); + return PyCursesWindow_New(win, NULL); } static PyObject * @@ -2034,10 +2394,11 @@ static PyObject * PyCurses_InitScr(PyObject *self) { WINDOW *win; + PyCursesWindowObject *winobj; if (initialised == TRUE) { wrefresh(stdscr); - return (PyObject *)PyCursesWindow_New(stdscr); + return (PyObject *)PyCursesWindow_New(stdscr, NULL); } win = initscr(); @@ -2129,7 +2490,9 @@ PyCurses_InitScr(PyObject *self) SetDictInt("LINES", LINES); SetDictInt("COLS", COLS); - return (PyObject *)PyCursesWindow_New(win); + winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); + screen_encoding = winobj->encoding; + return (PyObject *)winobj; } static PyObject * @@ -2331,7 +2694,7 @@ PyCurses_NewPad(PyObject *self, PyObject *args) return NULL; } - return (PyObject *)PyCursesWindow_New(win); + return (PyObject *)PyCursesWindow_New(win, NULL); } static PyObject * @@ -2363,7 +2726,7 @@ PyCurses_NewWindow(PyObject *self, PyObject *args) return NULL; } - return (PyObject *)PyCursesWindow_New(win); + return (PyObject *)PyCursesWindow_New(win, NULL); } static PyObject * @@ -2680,10 +3043,8 @@ PyCurses_UnCtrl(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL; - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, "argument must be a ch or an int"); + if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) return NULL; - } return PyBytes_FromString(unctrl(ch)); } @@ -2696,12 +3057,11 @@ PyCurses_UngetCh(PyObject *self, PyObject *args) PyCursesInitialised; - if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL; + if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) + return NULL; - if (!PyCurses_ConvertToChtype(temp, &ch)) { - PyErr_SetString(PyExc_TypeError, "argument must be a ch or an int"); + if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) return NULL; - } return PyCursesCheckERR(ungetch(ch), "ungetch"); } |