Skip to content

Commit dcc4e52

Browse files
authored
gh-156951: Do not truncate the color pair in curses.slk_color() (GH-156952)
slk_color() cast its color pair to a short, so pairs of 32768 and above were rejected or silently applied as a different pair. Use extended_slk_color() when it is available, like slk_attr_set() does.
1 parent 5d24802 commit dcc4e52

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

Lib/test/test_curses.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3482,10 +3482,10 @@ class SLKTests(NewtermTestBase):
34823482
# slk_init() must run before newterm()/initscr(), so each test sets up its
34833483
# own screen rather than reusing the one TestCurses builds in setUp().
34843484

3485-
def make_slk_screen(self, fmt=0):
3485+
def make_slk_screen(self, fmt=0, term='xterm'):
34863486
s = self.make_pty()
34873487
curses.slk_init(fmt)
3488-
return curses.newterm('xterm', s, s)
3488+
return curses.newterm(term, s, s)
34893489

34903490
def test_init_reserves_a_line(self):
34913491
# Every layout takes the bottom line for the labels; the index-line
@@ -3568,6 +3568,26 @@ def test_color(self):
35683568
curses.slk_attr_set(curses.A_BOLD, 0)
35693569
curses.slk_color(0)
35703570

3571+
def test_color_wide_pair(self):
3572+
# Drive a terminal with enough color pairs to reach past a short,
3573+
# rather than relying on whatever $TERM happens to be.
3574+
try:
3575+
self.make_slk_screen(term='xterm-256color')
3576+
except curses.error:
3577+
self.skipTest('no xterm-256color terminfo entry')
3578+
if not curses.has_colors():
3579+
self.skipTest('requires colors support')
3580+
curses.start_color()
3581+
if not (curses.has_extended_color_support()
3582+
and curses.COLOR_PAIRS > SHORT_MAX + 1):
3583+
self.skipTest('requires extended color support')
3584+
# A pair that does not fit in a short is still a valid pair here.
3585+
curses.slk_color(SHORT_MAX + 1)
3586+
# The low 16 bits of this are pair 5, but the pair itself is out of
3587+
# range, so it must raise instead of selecting pair 5.
3588+
self.assertRaises(curses.error, curses.slk_color,
3589+
curses.COLOR_PAIRS * 2 + 5)
3590+
35713591

35723592
@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()')
35733593
@unittest.skipIf(BROKEN_NEWTERM, 'ncurses < 6.5 mishandles repeated newterm()')

Modules/_cursesmodule.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8866,7 +8866,13 @@ _curses_slk_color_impl(PyObject *module, int pair)
88668866
/*[clinic end generated code: output=ffe4de805f9c65f5 input=b1e691a9cc6177ee]*/
88678867
{
88688868
PyCursesStatefulInitialised(module);
8869-
return curses_check_err(module, slk_color((short)pair), "slk_color", NULL);
8869+
int rtn;
8870+
#if _NCURSES_EXTENDED_COLOR_FUNCS
8871+
rtn = extended_slk_color(pair);
8872+
#else
8873+
rtn = slk_color((short)pair);
8874+
#endif
8875+
return curses_check_err(module, rtn, "slk_color", NULL);
88708876
}
88718877
#endif /* HAVE_CURSES_SLK_COLOR */
88728878

0 commit comments

Comments
 (0)