Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Doc/library/curses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,10 @@ the following methods and attributes:
window.getstr(y, x, n)

Read a bytes object from the user, with primitive line editing capacity.
The maximum value for *n* is 2047.

.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.


.. method:: window.getyx()
Expand Down Expand Up @@ -1079,6 +1083,10 @@ the following methods and attributes:
current cursor position, or at *y*, *x* if specified. Attributes are stripped
from the characters. If *n* is specified, :meth:`instr` returns a string
at most *n* characters long (exclusive of the trailing NUL).
The maximum value for *n* is 2047.

.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.


.. method:: window.is_linetouched(line)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:mod:`curses`: The :meth:`curses.window.instr` and :meth:`curses.window.getstr`
methods now allocate their internal buffer on the heap instead of the stack;
in addition, the max buffer size is increased from 1023 to 2047.
102 changes: 69 additions & 33 deletions Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1687,7 +1687,7 @@ _curses.window.getstr
x: int
X-coordinate.
]
n: int = 1023
n: int = 2047
Maximal number of characters.
/

Expand All @@ -1700,62 +1700,80 @@ PyCursesWindow_GetStr(PyObject *op, PyObject *args)
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);

int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
int rtn;

/* could make the buffer size larger/dynamic */
Py_ssize_t max_buf_size = 2048;
PyObject *result = PyBytes_FromStringAndSize(NULL, max_buf_size);
if (result == NULL)
return NULL;
char *buf = PyBytes_AS_STRING(result);

switch (PyTuple_Size(args)) {
case 0:
Py_BEGIN_ALLOW_THREADS
rtn2 = wgetnstr(self->win,rtn, 1023);
rtn = wgetnstr(self->win, buf, max_buf_size - 1);
Py_END_ALLOW_THREADS
break;
case 1:
if (!PyArg_ParseTuple(args,"i;n", &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
Py_BEGIN_ALLOW_THREADS
rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = wgetnstr(self->win, buf, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
break;
case 2:
if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
return NULL;
goto error;
Py_BEGIN_ALLOW_THREADS
#ifdef STRICT_SYSV_CURSES
rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023);
rtn = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, max_buf_size - 1);
#else
rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023);
rtn = mvwgetnstr(self->win,y,x,buf, max_buf_size - 1);
#endif
Py_END_ALLOW_THREADS
break;
case 3:
if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
#ifdef STRICT_SYSV_CURSES
Py_BEGIN_ALLOW_THREADS
rtn2 = wmove(self->win,y,x)==ERR ? ERR :
wgetnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = wmove(self->win,y,x)==ERR ? ERR :
wgetnstr(self->win, rtn, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
#else
Py_BEGIN_ALLOW_THREADS
rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023));
rtn = mvwgetnstr(self->win, y, x, buf, Py_MIN(n, max_buf_size - 1));
Py_END_ALLOW_THREADS
#endif
break;
default:
PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments");
goto error;
}

if (rtn == ERR) {
Py_DECREF(result);
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}

if (_PyBytes_Resize(&result, strlen(buf)) < 0) {
return NULL;
}
if (rtn2 == ERR)
rtn[0] = 0;
return PyBytes_FromString(rtn);

return result;

error:
Py_DECREF(result);
return NULL;
}

/*[clinic input]
Expand Down Expand Up @@ -1889,7 +1907,7 @@ _curses.window.instr
x: int
X-coordinate.
]
n: int = 1023
n: int = 2047
Maximal number of characters.
/

Expand All @@ -1906,43 +1924,61 @@ PyCursesWindow_InStr(PyObject *op, PyObject *args)
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);

int x, y, n;
char rtn[1024]; /* This should be big enough.. I hope */
int rtn2;
int rtn;

/* could make the buffer size larger/dynamic */
Py_ssize_t max_buf_size = 2048;
PyObject *result = PyBytes_FromStringAndSize(NULL, max_buf_size);
if (result == NULL)
return NULL;
char *buf = PyBytes_AS_STRING(result);

switch (PyTuple_Size(args)) {
case 0:
rtn2 = winnstr(self->win,rtn, 1023);
rtn = winnstr(self->win, buf, max_buf_size - 1);
break;
case 1:
if (!PyArg_ParseTuple(args,"i;n", &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023));
rtn = winnstr(self->win, buf, Py_MIN(n, max_buf_size - 1));
break;
case 2:
if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
return NULL;
rtn2 = mvwinnstr(self->win,y,x,rtn,1023);
goto error;
rtn = mvwinnstr(self->win, y, x, buf, max_buf_size - 1);
break;
case 3:
if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n))
return NULL;
goto error;
if (n < 0) {
PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
return NULL;
goto error;
}
rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023));
rtn = mvwinnstr(self->win, y, x, buf, Py_MIN(n, max_buf_size - 1));
break;
default:
PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments");
goto error;
}

if (rtn == ERR) {
Py_DECREF(result);
return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}

if (_PyBytes_Resize(&result, strlen(buf)) < 0) {
return NULL;
}
if (rtn2 == ERR)
rtn[0] = 0;
return PyBytes_FromString(rtn);

return result;

error:
Py_DECREF(result);
return NULL;
}

/*[clinic input]
Expand Down
Loading