From cad3106c9112b81ce241992817d03e062598bcba Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 23 Jul 2026 08:43:16 +0300 Subject: [PATCH 1/2] gh-154525: Fix curses getcchar() failure on ncurses older than 6.3 getcchar() rejected a non-NULL opts argument before ncurses 6.3, so read the color pair through the short slot instead. Co-Authored-By: Claude Opus 4.8 (1M context) --- Modules/_cursesmodule.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 6df593001b8a1cb..6d1cd48cf9d481a 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -151,6 +151,16 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ +/* getcchar() returned ERR for a non-NULL opts before ncurses 6.3 (patch + 20210116, https://invisible-island.net/ncurses/), so read a cchar_t's color + pair through the plain short slot rather than the extended-color opts slot on + older libraries. setcchar() is unaffected: it accepts opts on every version. */ +#if _NCURSES_EXTENDED_COLOR_FUNCS && NCURSES_VERSION_PATCH+0 >= 20210116 +#define _NCURSES_GETCCHAR_EXTENDED_PAIR 1 +#else +#define _NCURSES_GETCCHAR_EXTENDED_PAIR 0 +#endif + typedef struct { PyObject *error; // curses exception type PyTypeObject *window_type; // exposed by PyCursesWindow_Type @@ -763,7 +773,7 @@ curses_getcchar(const cchar_t *wcval, wchar_t *wstr, attr_t *attrs, int *pair) /* getcchar() is not guaranteed to write the text of an empty cell, so make the output an empty string by default. */ wstr[0] = L'\0'; -#if _NCURSES_EXTENDED_COLOR_FUNCS +#if _NCURSES_GETCCHAR_EXTENDED_PAIR int rtn = getcchar(wcval, wstr, attrs, &spair, pair); #else int rtn = getcchar(wcval, wstr, attrs, &spair, NULL); From 9de6a48ce5c1f9ff8677b06ab67cd3346ce1ee06 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 23 Jul 2026 09:26:43 +0300 Subject: [PATCH 2/2] Inline the single-use getcchar() extended-pair condition _NCURSES_GETCCHAR_EXTENDED_PAIR was referenced in only one place; move the version condition and its comment to that call site. Co-Authored-By: Claude Opus 4.8 (1M context) --- Modules/_cursesmodule.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 6d1cd48cf9d481a..f893c2080fc3f33 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -151,16 +151,6 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ -/* getcchar() returned ERR for a non-NULL opts before ncurses 6.3 (patch - 20210116, https://invisible-island.net/ncurses/), so read a cchar_t's color - pair through the plain short slot rather than the extended-color opts slot on - older libraries. setcchar() is unaffected: it accepts opts on every version. */ -#if _NCURSES_EXTENDED_COLOR_FUNCS && NCURSES_VERSION_PATCH+0 >= 20210116 -#define _NCURSES_GETCCHAR_EXTENDED_PAIR 1 -#else -#define _NCURSES_GETCCHAR_EXTENDED_PAIR 0 -#endif - typedef struct { PyObject *error; // curses exception type PyTypeObject *window_type; // exposed by PyCursesWindow_Type @@ -773,7 +763,9 @@ curses_getcchar(const cchar_t *wcval, wchar_t *wstr, attr_t *attrs, int *pair) /* getcchar() is not guaranteed to write the text of an empty cell, so make the output an empty string by default. */ wstr[0] = L'\0'; -#if _NCURSES_GETCCHAR_EXTENDED_PAIR + /* getcchar()'s opts slot returns the extended color pair, but ncurses + returned ERR for a non-NULL opts until 6.3 (patch 20210116). */ +#if _NCURSES_EXTENDED_COLOR_FUNCS && NCURSES_VERSION_PATCH+0 >= 20210116 int rtn = getcchar(wcval, wstr, attrs, &spair, pair); #else int rtn = getcchar(wcval, wstr, attrs, &spair, NULL);