Skip to content

Commit 6de2a16

Browse files
Adapt the NUL cell and long line reads to PDCurses
PDCursesMod's setcchar() reads uninitialized memory for an empty string (PDCursesMod issue #388), so build a cell without text directly. Its winnstr() reads at most 512 bytes, and a NUL is written in its ^@ form.
1 parent 6bc6735 commit 6de2a16

2 files changed

Lines changed: 23 additions & 7 deletions

File tree

Lib/test/test_curses.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,11 @@ def test_cell_null_char(self):
11761176
# A cell holding a NUL reads back as the cell that writes it.
11771177
win = curses.newwin(3, 8, 0, 0)
11781178
win.insch(0, 0, '\0')
1179-
self.assertEqual(win.in_wch(0, 0), cell)
1179+
if is_pdcurses:
1180+
# PDCurses writes a NUL as "^@".
1181+
self.assertEqual(str(win.in_wch(0, 0)), '^')
1182+
else:
1183+
self.assertEqual(win.in_wch(0, 0), cell)
11801184
# A string of cells cannot hold a NUL: it would end a batch write.
11811185
self.assertRaises(ValueError, curses.complexstr, 'a\0b')
11821186
self.assertRaises(ValueError, curses.complexstr, '\0')
@@ -1293,7 +1297,9 @@ def test_read_long_line(self):
12931297
with self.subTest(ch=ch):
12941298
line = ch * (width - 1) + ' ' # the last cell is left blank
12951299
pad.addstr(0, 0, line[:-1])
1296-
self.assertEqual(pad.instr(0, 0), line.encode(pad.encoding))
1300+
if not is_pdcurses:
1301+
# PDCurses reads at most 512 bytes.
1302+
self.assertEqual(pad.instr(0, 0), line.encode(pad.encoding))
12971303
self.assertEqual(pad.in_wstr(0, 0), line)
12981304
self.assertEqual(str(pad.in_wchstr(0, 0)), line)
12991305

Modules/_cursesmodule.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -832,18 +832,28 @@ typedef struct {
832832
static int
833833
curses_setcchar(cchar_t *wcval, const wchar_t *wstr, attr_t attrs, int pair)
834834
{
835+
#if !_NCURSES_EXTENDED_COLOR_FUNCS
836+
if (pair > SHRT_MAX) {
837+
PyErr_Format(PyExc_OverflowError,
838+
"color pair %d does not fit in a short", pair);
839+
return ERR;
840+
}
841+
#endif
842+
#ifdef PDCURSES
843+
/* PDCursesMod's setcchar() does not handle an empty string
844+
(PDCursesMod issue #388). */
845+
if (wstr[0] == L'\0') {
846+
*wcval = (cchar_t)attrs | COLOR_PAIR(pair);
847+
return OK;
848+
}
849+
#endif
835850
#if _NCURSES_EXTENDED_COLOR_FUNCS
836851
/* The pair passed through the opts slot is authoritative and may exceed
837852
a short; ncurses then ignores the short argument, but clamp it into
838853
range so the int-to-short narrowing stays well-defined. */
839854
short spair = pair <= SHRT_MAX ? (short)pair : SHRT_MAX;
840855
return setcchar(wcval, wstr, attrs, spair, &pair);
841856
#else
842-
if (pair > SHRT_MAX) {
843-
PyErr_Format(PyExc_OverflowError,
844-
"color pair %d does not fit in a short", pair);
845-
return ERR;
846-
}
847857
return setcchar(wcval, wstr, attrs, (short)pair, NULL);
848858
#endif
849859
}

0 commit comments

Comments
 (0)