https://github.com/python/cpython/commit/ca79981cc08f23990e2f00d78d84681e40f369bd
commit: ca79981cc08f23990e2f00d78d84681e40f369bd
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-23T19:53:59+03:00
summary:
gh-156230: Bound a curses window read by the window, not by 2047 (GH-156282)
instr(), in_wstr() and in_wchstr() clamped the count to 2047 and silently
truncated a longer line, which a pad can have. A window read cannot return
more than the columns left on the line, in the unit each method counts: cells,
characters, or bytes at CCHARW_MAX characters of MB_CUR_MAX bytes per cell.
Cap the count by that, and read the rest of the line when the count is
omitted, which it now can be.
getstr() and get_wstr() read the keyboard rather than the window, so their
limit stays.
files:
A Misc/NEWS.d/next/Library/2026-08-22-14-12-40.gh-issue-156230.Lt9wQd.rst
M Doc/library/curses.rst
M Lib/test/test_curses.py
M Modules/_cursesmodule.c
M Modules/clinic/_cursesmodule.c.h
diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
index d6bccbb730f8b4..858371f927f4fa 100644
--- a/Doc/library/curses.rst
+++ b/Doc/library/curses.rst
@@ -1404,26 +1404,29 @@ Reading window contents
window.instr(y, x[, n])
Read the text of the window from the current cursor position,
- or from *y*, *x* if specified, to the end of the line,
+ or from *y*, *x* if specified, to the end of the line
+ or at most *n* bytes if *n* is specified,
and return it as a bytes object, in the encoding of the current locale.
Attributes and color pairs are stripped;
use :meth:`in_wchstr` to read them too.
- At most *n* bytes are read; *n* defaults to and cannot exceed 2047.
A character not representable in the encoding cannot be returned;
use :meth:`in_wstr` for those.
.. versionchanged:: 3.14
The maximum value for *n* was increased from 1023 to 2047.
+ .. versionchanged:: next
+ *n* is no longer limited to 2047.
+
.. method:: window.in_wstr([n])
window.in_wstr(y, x[, n])
Read the text of the window from the current cursor position,
- or from *y*, *x* if specified, to the end of the line,
+ or from *y*, *x* if specified, to the end of the line
+ or at most *n* characters if *n* is specified,
and return it as a :class:`str`.
Attributes and color pairs are stripped;
use :meth:`in_wchstr` to read them too.
- At most *n* characters are read; *n* defaults to and cannot exceed 2047.
This is the wide-character variant of :meth:`instr`.
@@ -1433,12 +1436,12 @@ Reading window contents
window.in_wchstr(y, x[, n])
Read the styled cells of the window from the current cursor position,
- or from *y*, *x* if specified, to the end of the line,
+ or from *y*, *x* if specified, to the end of the line
+ or at most *n* cells if *n* is specified,
and return them as a :class:`complexstr`.
Unlike :meth:`instr` and :meth:`in_wstr`, each cell keeps its attributes
and color pair, so the result can be written back unchanged
with :meth:`addstr`.
- At most *n* cells are read; *n* defaults to and cannot exceed 2047.
.. versionadded:: next
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index ea2dcd76b585a9..630de544a457f4 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -672,6 +672,11 @@ def test_in_wstr(self):
stdscr.addstr(0, 0, 'abz')
self.assertEqual(stdscr.in_wstr(0, 0, 0), '')
self.assertEqual(stdscr.in_wstr(0), '')
+ self.assertEqual(stdscr.in_wstr(0, 0, 2**31), stdscr.in_wstr(0, 0))
+ self.assertRaises(OverflowError, stdscr.in_wstr, 2**1000)
+ self.assertRaises(ValueError, stdscr.in_wstr, -2)
+ self.assertRaises(ValueError, stdscr.in_wstr, 0, 2, -2)
+ self.assertRaises(ValueError, stdscr.in_wstr, -2**1000)
def test_complexchar(self):
# A complexchar is a styled wide-character cell: str() is its text,
@@ -871,6 +876,11 @@ def test_in_wchstr(self):
# The count is optional and reads to the end of the line by default.
stdscr.move(0, 0)
self.assertEqual(str(stdscr.in_wchstr())[:3], 'AbC')
+ self.assertEqual(stdscr.in_wchstr(0, 0, 2**31), stdscr.in_wchstr(0, 0))
+ self.assertRaises(OverflowError, stdscr.in_wchstr, 2**1000)
+ self.assertRaises(ValueError, stdscr.in_wchstr, -2)
+ self.assertRaises(ValueError, stdscr.in_wchstr, 0, 2, -2)
+ self.assertRaises(ValueError, stdscr.in_wchstr, -2**1000)
def test_complexstr_in_write_methods(self):
# addstr/addnstr/insstr/insnstr also accept a complexstr, written via
@@ -1188,8 +1198,13 @@ def test_read_from_window(self):
self.assertEqual(stdscr.instr(3)[:6], b' AB')
self.assertEqual(stdscr.instr(0, 2)[:4], b'BCD ')
self.assertEqual(stdscr.instr(0, 2, 4), b'BCD ')
+ # A huge count is bounded by the line, and is not used to size the
+ # read buffer.
+ self.assertEqual(stdscr.instr(0, 0, 2**31), stdscr.instr(0, 0))
+ self.assertRaises(OverflowError, stdscr.instr, 2**1000)
self.assertRaises(ValueError, stdscr.instr, -2)
self.assertRaises(ValueError, stdscr.instr, 0, 2, -2)
+ self.assertRaises(ValueError, stdscr.instr, -2**1000)
# instr(y, x, 1) reads a single cell byte, so only a character that the
# window encoding maps to one byte is checked. inch() returns the cell
# value, which is the locale byte.
@@ -1206,6 +1221,25 @@ def test_read_from_window(self):
self.assertEqual(stdscr.instr(2, 0, 1), b)
self.assertEqual(stdscr.inch(2, 0), v)
+ def test_read_long_line(self):
+ # A pad line can be longer than a window, and a character can be
+ # encoded with several bytes, so instr() can read more bytes than
+ # there are cells. See _encodable for the character set.
+ width = 3000
+ pad = curses.newpad(1, width)
+ for ch in ['z', '\u00e9', '\u20ac', '\u0434', '\uff71']:
+ if not self._storable(ch):
+ continue
+ pad.addstr(0, 0, ch)
+ if pad.getyx()[1] != 1:
+ continue # a wide character occupies two cells
+ with self.subTest(ch=ch):
+ line = ch * (width - 1) + ' ' # the last cell is left blank
+ pad.addstr(0, 0, line[:-1])
+ self.assertEqual(pad.instr(0, 0), line.encode(pad.encoding))
+ self.assertEqual(pad.in_wstr(0, 0), line)
+ self.assertEqual(str(pad.in_wchstr(0, 0)), line)
+
def test_coordinate_errors(self):
# Addressing a cell outside the window raises curses.error.
win = curses.newwin(5, 10, 0, 0)
diff --git
a/Misc/NEWS.d/next/Library/2026-08-22-14-12-40.gh-issue-156230.Lt9wQd.rst
b/Misc/NEWS.d/next/Library/2026-08-22-14-12-40.gh-issue-156230.Lt9wQd.rst
new file mode 100644
index 00000000000000..3b9b41c389580e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-22-14-12-40.gh-issue-156230.Lt9wQd.rst
@@ -0,0 +1,3 @@
+:meth:`curses.window.instr`, :meth:`~curses.window.in_wstr` and
+:meth:`~curses.window.in_wchstr` no longer limit the count to 2047, which
+silently truncated a longer line.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 45ba6476bbc4a6..12d7664b395967 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -3535,6 +3535,29 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self,
int group_right_1,
#endif
}
+/* Characters one cell can hold. */
+#ifdef HAVE_NCURSESW
+#define CURSES_CELL_CHARS CCHARW_MAX
+#else
+#define CURSES_CELL_CHARS 1
+#endif
+
+/* The columns left on the line, in the unit the caller counts. */
+static unsigned int
+curses_window_read_limit(PyCursesWindowObject *self, int use_xy, int x,
+ unsigned int per_cell)
+{
+ int col = use_xy ? x : getcurx(self->win);
+ int maxx = getmaxx(self->win);
+ if (col < 0) {
+ col = 0;
+ }
+ if (col > maxx) {
+ return 0;
+ }
+ return ((unsigned int)(maxx - col) + 1) * per_cell;
+}
+
/* Read user input into a new bytes object (empty on ERR), with primitive line
editing. Shared by getstr() and, without the wide library, by get_wstr().
*/
static PyObject *
@@ -3828,15 +3851,15 @@ _curses_window_inch_impl(PyCursesWindowObject *self,
int group_right_1,
with attributes and color stripped. Shared by instr() and, without the wide
library, by in_wstr(). */
static PyObject *
-curses_window_instr_bytes(PyCursesWindowObject *self, int use_xy,
+curses_window_instr_bytes(PyCursesWindowObject *self, int use_xy, int use_n,
int y, int x, unsigned int n)
{
int rtn;
- unsigned int max_buf_size = 2048;
-
- n = Py_MIN(n, max_buf_size - 1 - CURSES_STR_EXTRA);
- n += CURSES_STR_EXTRA;
- PyBytesWriter *writer = PyBytesWriter_Create(n + 1);
+ unsigned int limit = curses_window_read_limit(self, use_xy, x,
+ CURSES_CELL_CHARS
+ * (unsigned int)MB_CUR_MAX);
+ unsigned int nread = use_n ? Py_MIN(n, limit) : limit;
+ PyBytesWriter *writer = PyBytesWriter_Create(nread + CURSES_STR_EXTRA + 1);
if (writer == NULL) {
return NULL;
}
@@ -3844,14 +3867,14 @@ curses_window_instr_bytes(PyCursesWindowObject *self,
int use_xy,
/* Read again if the library stored more than asked: truncating could
split a multibyte character. */
- for (unsigned int want = n - CURSES_STR_EXTRA; ; n = want) {
+ for (unsigned int ask = nread + CURSES_STR_EXTRA; ; ask = nread) {
if (use_xy) {
- rtn = mvwinnstr(self->win, y, x, buf, n);
+ rtn = mvwinnstr(self->win, y, x, buf, ask);
}
else {
- rtn = winnstr(self->win, buf, n);
+ rtn = winnstr(self->win, buf, ask);
}
- if (rtn == ERR || (unsigned int)rtn <= want) {
+ if (rtn == ERR || (unsigned int)rtn <= nread) {
break;
}
}
@@ -3872,24 +3895,27 @@ _curses.window.instr
x: int
X-coordinate.
]
- n: unsigned_int = 2047
- Maximal number of bytes.
+ [
+ n: unsigned_int
+ Maximal number of bytes. The rest of the line by default.
+ ]
/
Return the text of the window as a bytes object.
Read from the current cursor position, or from y, x if specified, to
-the end of the line, and return the text in the encoding of the
-current locale, with attributes and color pairs stripped. At most n
-bytes are read.
+the end of the line or at most n bytes if n is specified, and return
+the text in the encoding of the current locale, with attributes and
+color pairs stripped.
[clinic start generated code]*/
static PyObject *
-_curses_window_instr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n)
-/*[clinic end generated code: output=40081f67070132da input=4ece6af75b09346f]*/
+_curses_window_instr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2, unsigned int n)
+/*[clinic end generated code: output=2428948b44ad10c7 input=9307eca4bd576899]*/
{
- return curses_window_instr_bytes(self, group_left_1, y, x, n);
+ return curses_window_instr_bytes(self, group_right_1, group_right_2,
+ y, x, n);
}
/*[clinic input]
@@ -3987,44 +4013,45 @@ _curses.window.in_wstr
x: int
X-coordinate.
]
- n: unsigned_int = 2047
- Maximal number of characters.
+ [
+ n: unsigned_int
+ Maximal number of characters. The rest of the line by default.
+ ]
/
Return the text of the window as a str.
This is the wide-character variant of instr(). Read from the
current cursor position, or from y, x if specified, to the end of
-the line, with attributes and color pairs stripped. At most n
-characters are read.
+the line or at most n characters if n is specified, with attributes
+and color pairs stripped.
[clinic start generated code]*/
static PyObject *
-_curses_window_in_wstr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n)
-/*[clinic end generated code: output=e3db72a1f10b9875 input=436737264c54d8d3]*/
+_curses_window_in_wstr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2, unsigned int n)
+/*[clinic end generated code: output=d8c8bcfe8a26f519 input=5ba908338a94bfc8]*/
{
#ifdef HAVE_NCURSESW
int rtn;
- unsigned int max_buf_size = 2048;
-
- n = Py_MIN(n, max_buf_size - 1 - CURSES_STR_EXTRA);
- n += CURSES_STR_EXTRA;
- wchar_t *buf = PyMem_New(wchar_t, n + 1);
+ unsigned int limit = curses_window_read_limit(self, group_right_1, x,
+ CURSES_CELL_CHARS);
+ unsigned int nread = group_right_2 ? Py_MIN(n, limit) : limit;
+ wchar_t *buf = PyMem_New(wchar_t, nread + CURSES_STR_EXTRA + 1);
if (buf == NULL) {
return PyErr_NoMemory();
}
/* Read again if the library stored more than asked: truncating could
separate a combining character from its base. */
- for (unsigned int want = n - CURSES_STR_EXTRA; ; n = want) {
- if (group_left_1) {
- rtn = mvwinnwstr(self->win, y, x, buf, n);
+ for (unsigned int ask = nread + CURSES_STR_EXTRA; ; ask = nread) {
+ if (group_right_1) {
+ rtn = mvwinnwstr(self->win, y, x, buf, ask);
}
else {
- rtn = winnwstr(self->win, buf, n);
+ rtn = winnwstr(self->win, buf, ask);
}
- if (rtn == ERR || (unsigned int)rtn <= want) {
+ if (rtn == ERR || (unsigned int)rtn <= nread) {
break;
}
}
@@ -4039,7 +4066,8 @@ _curses_window_in_wstr_impl(PyCursesWindowObject *self,
int group_left_1,
#else
/* Without the wide library, read the bytes as instr() does and decode them
with the window's encoding. */
- PyObject *bytes = curses_window_instr_bytes(self, group_left_1, y, x, n);
+ PyObject *bytes = curses_window_instr_bytes(self, group_right_1,
+ group_right_2, y, x, n);
if (bytes == NULL) {
return NULL;
}
@@ -4060,43 +4088,46 @@ _curses.window.in_wchstr
x: int
X-coordinate.
]
- n: unsigned_int = 2047
- Maximal number of cells.
+ [
+ n: unsigned_int
+ Maximal number of cells. The rest of the line by default.
+ ]
/
Return the styled cells of the window as a complexstr.
-Read from the current cursor position, or from y, x if specified, to
-the end of the line. Unlike instr() and in_wstr(), each cell keeps
-its attributes and color pair, so the result can be written back
-unchanged with addstr(). At most n cells are read.
+Read from the current cursor position, or from y, x if specified,
+to the end of the line or at most n cells if n is specified.
+Unlike instr() and in_wstr(), each cell keeps its attributes and
+color pair, so the result can be written back unchanged with
+addstr().
[clinic start generated code]*/
static PyObject *
-_curses_window_in_wchstr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n)
-/*[clinic end generated code: output=7fb5216f2088835b input=8104e661c3cb7fea]*/
+_curses_window_in_wchstr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2,
+ unsigned int n)
+/*[clinic end generated code: output=3807a62d51efd44f input=50400321de1db1da]*/
{
int rtn;
- unsigned int max_buf_size = 2048;
-
- n = Py_MIN(n, max_buf_size - 1 - CURSES_STR_EXTRA);
- n += CURSES_STR_EXTRA;
+ unsigned int limit = curses_window_read_limit(self, group_right_1, x, 1);
+ unsigned int nread = group_right_2 ? Py_MIN(n, limit) : limit;
+ unsigned int ask = nread + CURSES_STR_EXTRA;
cursesmodule_state *state = get_cursesmodule_state_by_win(self);
/* Zero the cells: reading a cell back through getcchar() relies on the
cchar_t text array being NUL-terminated, which some curses libraries
only guarantee for the characters they actually write. */
- curses_cell_t *buf = PyMem_Calloc(n + 1, sizeof(curses_cell_t));
+ curses_cell_t *buf = PyMem_Calloc(ask + 1, sizeof(curses_cell_t));
if (buf == NULL) {
return PyErr_NoMemory();
}
#ifdef HAVE_NCURSESW
- if (group_left_1) {
- rtn = mvwin_wchnstr(self->win, y, x, buf, n);
+ if (group_right_1) {
+ rtn = mvwin_wchnstr(self->win, y, x, buf, ask);
}
else {
- rtn = win_wchnstr(self->win, buf, n);
+ rtn = win_wchnstr(self->win, buf, ask);
}
if (rtn == ERR) {
@@ -4104,12 +4135,11 @@ _curses_window_in_wchstr_impl(PyCursesWindowObject
*self, int group_left_1,
return PyCursesComplexStr_New(state, NULL, 0);
}
- n -= CURSES_STR_EXTRA;
- /* win_wchnstr() stores at most n cells and zero-terminates the array at
- the actual count; every real cell holds at least a space, so the first
+ /* win_wchnstr() stores at most nread cells and zero-terminates the array
+ at the actual count; every real cell holds at least a space, so the
first
empty cell marks the end of the run. */
Py_ssize_t count = 0;
- while (count < (Py_ssize_t)n) {
+ while (count < (Py_ssize_t)nread) {
wchar_t wstr[CCHARW_MAX + 1];
attr_t attrs;
int pair;
@@ -4124,12 +4154,12 @@ _curses_window_in_wchstr_impl(PyCursesWindowObject
*self, int group_left_1,
/* winchnstr() is not guaranteed (SVr4) to terminate the array, so pre-zero
it and stop at the first empty cell; a painted cell always holds at
least
a space, never 0. */
- memset(buf, 0, ((size_t)n + 1) * sizeof(curses_cell_t));
- if (group_left_1) {
- rtn = mvwinchnstr(self->win, y, x, buf, n);
+ memset(buf, 0, ((size_t)ask + 1) * sizeof(curses_cell_t));
+ if (group_right_1) {
+ rtn = mvwinchnstr(self->win, y, x, buf, ask);
}
else {
- rtn = winchnstr(self->win, buf, n);
+ rtn = winchnstr(self->win, buf, ask);
}
if (rtn == ERR) {
@@ -4137,9 +4167,8 @@ _curses_window_in_wchstr_impl(PyCursesWindowObject *self,
int group_left_1,
return PyCursesComplexStr_New(state, NULL, 0);
}
- n -= CURSES_STR_EXTRA;
Py_ssize_t count = 0;
- while (count < (Py_ssize_t)n && buf[count] != 0) {
+ while (count < (Py_ssize_t)nread && buf[count] != 0) {
count++;
}
#endif
diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h
index 61c324e04c5bdc..44cb16d55fa330 100644
--- a/Modules/clinic/_cursesmodule.c.h
+++ b/Modules/clinic/_cursesmodule.c.h
@@ -1721,7 +1721,7 @@ _curses_window_inch(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(_curses_window_instr__doc__,
-"instr([y, x,] n=2047)\n"
+"instr([y, x,] [n])\n"
"Return the text of the window as a bytes object.\n"
"\n"
" y\n"
@@ -1729,48 +1729,57 @@ PyDoc_STRVAR(_curses_window_instr__doc__,
" x\n"
" X-coordinate.\n"
" n\n"
-" Maximal number of bytes.\n"
+" Maximal number of bytes. The rest of the line by default.\n"
"\n"
"Read from the current cursor position, or from y, x if specified, to\n"
-"the end of the line, and return the text in the encoding of the\n"
-"current locale, with attributes and color pairs stripped. At most n\n"
-"bytes are read.");
+"the end of the line or at most n bytes if n is specified, and return\n"
+"the text in the encoding of the current locale, with attributes and\n"
+"color pairs stripped.");
#define _CURSES_WINDOW_INSTR_METHODDEF \
{"instr", (PyCFunction)_curses_window_instr, METH_VARARGS,
_curses_window_instr__doc__},
static PyObject *
-_curses_window_instr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n);
+_curses_window_instr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2, unsigned int n);
static PyObject *
_curses_window_instr(PyObject *self, PyObject *args)
{
PyObject *return_value = NULL;
- int group_left_1 = 0;
+ int group_right_1 = 0;
int y = 0;
int x = 0;
- unsigned int n = 2047;
+ int group_right_2 = 0;
+ unsigned int n = 0;
switch (PyTuple_GET_SIZE(args)) {
case 0:
+ break;
case 1:
- if (!PyArg_ParseTuple(args, "|O&:instr",
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "O&:instr",
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
+ group_right_2 = 1;
break;
case 2:
+ if (!PyArg_ParseTuple(args, "ii:instr", &y, &x)) {
+ goto exit;
+ }
+ group_right_1 = 1;
+ break;
case 3:
- if (!PyArg_ParseTuple(args, "ii|O&:instr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "iiO&:instr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
- group_left_1 = 1;
+ group_right_1 = 1;
+ group_right_2 = 1;
break;
default:
PyErr_SetString(PyExc_TypeError, "_curses.window.instr requires 0
to 3 arguments");
goto exit;
}
- return_value = _curses_window_instr_impl((PyCursesWindowObject *)self,
group_left_1, y, x, n);
+ return_value = _curses_window_instr_impl((PyCursesWindowObject *)self,
group_right_1, y, x, group_right_2, n);
exit:
return return_value;
@@ -1832,7 +1841,7 @@ _curses_window_get_wstr(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(_curses_window_in_wstr__doc__,
-"in_wstr([y, x,] n=2047)\n"
+"in_wstr([y, x,] [n])\n"
"Return the text of the window as a str.\n"
"\n"
" y\n"
@@ -1840,55 +1849,64 @@ PyDoc_STRVAR(_curses_window_in_wstr__doc__,
" x\n"
" X-coordinate.\n"
" n\n"
-" Maximal number of characters.\n"
+" Maximal number of characters. The rest of the line by default.\n"
"\n"
"This is the wide-character variant of instr(). Read from the\n"
"current cursor position, or from y, x if specified, to the end of\n"
-"the line, with attributes and color pairs stripped. At most n\n"
-"characters are read.");
+"the line or at most n characters if n is specified, with attributes\n"
+"and color pairs stripped.");
#define _CURSES_WINDOW_IN_WSTR_METHODDEF \
{"in_wstr", (PyCFunction)_curses_window_in_wstr, METH_VARARGS,
_curses_window_in_wstr__doc__},
static PyObject *
-_curses_window_in_wstr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n);
+_curses_window_in_wstr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2, unsigned int n);
static PyObject *
_curses_window_in_wstr(PyObject *self, PyObject *args)
{
PyObject *return_value = NULL;
- int group_left_1 = 0;
+ int group_right_1 = 0;
int y = 0;
int x = 0;
- unsigned int n = 2047;
+ int group_right_2 = 0;
+ unsigned int n = 0;
switch (PyTuple_GET_SIZE(args)) {
case 0:
+ break;
case 1:
- if (!PyArg_ParseTuple(args, "|O&:in_wstr",
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "O&:in_wstr",
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
+ group_right_2 = 1;
break;
case 2:
+ if (!PyArg_ParseTuple(args, "ii:in_wstr", &y, &x)) {
+ goto exit;
+ }
+ group_right_1 = 1;
+ break;
case 3:
- if (!PyArg_ParseTuple(args, "ii|O&:in_wstr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "iiO&:in_wstr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
- group_left_1 = 1;
+ group_right_1 = 1;
+ group_right_2 = 1;
break;
default:
PyErr_SetString(PyExc_TypeError, "_curses.window.in_wstr requires
0 to 3 arguments");
goto exit;
}
- return_value = _curses_window_in_wstr_impl((PyCursesWindowObject *)self,
group_left_1, y, x, n);
+ return_value = _curses_window_in_wstr_impl((PyCursesWindowObject *)self,
group_right_1, y, x, group_right_2, n);
exit:
return return_value;
}
PyDoc_STRVAR(_curses_window_in_wchstr__doc__,
-"in_wchstr([y, x,] n=2047)\n"
+"in_wchstr([y, x,] [n])\n"
"Return the styled cells of the window as a complexstr.\n"
"\n"
" y\n"
@@ -1896,48 +1914,59 @@ PyDoc_STRVAR(_curses_window_in_wchstr__doc__,
" x\n"
" X-coordinate.\n"
" n\n"
-" Maximal number of cells.\n"
+" Maximal number of cells. The rest of the line by default.\n"
"\n"
-"Read from the current cursor position, or from y, x if specified, to\n"
-"the end of the line. Unlike instr() and in_wstr(), each cell keeps\n"
-"its attributes and color pair, so the result can be written back\n"
-"unchanged with addstr(). At most n cells are read.");
+"Read from the current cursor position, or from y, x if specified,\n"
+"to the end of the line or at most n cells if n is specified.\n"
+"Unlike instr() and in_wstr(), each cell keeps its attributes and\n"
+"color pair, so the result can be written back unchanged with\n"
+"addstr().");
#define _CURSES_WINDOW_IN_WCHSTR_METHODDEF \
{"in_wchstr", (PyCFunction)_curses_window_in_wchstr, METH_VARARGS,
_curses_window_in_wchstr__doc__},
static PyObject *
-_curses_window_in_wchstr_impl(PyCursesWindowObject *self, int group_left_1,
- int y, int x, unsigned int n);
+_curses_window_in_wchstr_impl(PyCursesWindowObject *self, int group_right_1,
+ int y, int x, int group_right_2,
+ unsigned int n);
static PyObject *
_curses_window_in_wchstr(PyObject *self, PyObject *args)
{
PyObject *return_value = NULL;
- int group_left_1 = 0;
+ int group_right_1 = 0;
int y = 0;
int x = 0;
- unsigned int n = 2047;
+ int group_right_2 = 0;
+ unsigned int n = 0;
switch (PyTuple_GET_SIZE(args)) {
case 0:
+ break;
case 1:
- if (!PyArg_ParseTuple(args, "|O&:in_wchstr",
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "O&:in_wchstr",
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
+ group_right_2 = 1;
break;
case 2:
+ if (!PyArg_ParseTuple(args, "ii:in_wchstr", &y, &x)) {
+ goto exit;
+ }
+ group_right_1 = 1;
+ break;
case 3:
- if (!PyArg_ParseTuple(args, "ii|O&:in_wchstr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
+ if (!PyArg_ParseTuple(args, "iiO&:in_wchstr", &y, &x,
_PyLong_UnsignedInt_Converter, &n)) {
goto exit;
}
- group_left_1 = 1;
+ group_right_1 = 1;
+ group_right_2 = 1;
break;
default:
PyErr_SetString(PyExc_TypeError, "_curses.window.in_wchstr
requires 0 to 3 arguments");
goto exit;
}
- return_value = _curses_window_in_wchstr_impl((PyCursesWindowObject *)self,
group_left_1, y, x, n);
+ return_value = _curses_window_in_wchstr_impl((PyCursesWindowObject *)self,
group_right_1, y, x, group_right_2, n);
exit:
return return_value;
@@ -6603,4 +6632,4 @@ _curses_has_extended_color_support(PyObject *module,
PyObject *Py_UNUSED(ignored
#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=5616d0371c2240be input=a9049054013a1b77]*/
+/*[clinic end generated code: output=81cb3f7a7225f920 input=a9049054013a1b77]*/
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]