The curses character-cell window methods currently accept only a single narrow character -- an int, a one-byte bytes, or a one-character str -- and most of the wide-character (cchar_t) part of the X/Open Curses API is unwrapped. A character cell can actually hold a full complex character: one spacing character optionally followed by combining characters. There is also no way to read text back as str rather than bytes, nor to query the wide erase/kill characters or get a printable representation of a wide character.
I propose to wrap the wide-character API, available when CPython is built against the wide-character ncursesw library.
The character-cell methods addch(), bkgd(), bkgdset(), border(), box(), echochar(), hline(), insch() and vline() additionally accept a str of a spacing character optionally followed by combining characters, dispatching to the ncursesw wide-character functions (wadd_wch(), wbkgrnd(), wborder_set(), wecho_wchar(), whline_set(), wins_wch(), wvline_set(), ...). border() and box() cannot mix integer or byte characters with wide-string characters in a single call. A cell is exactly one spacing character plus zero or more combining characters, so any extra spacing or control character (for example "ab", an emoji ZWJ sequence, or an emoji with a skin-tone modifier) is rejected with ValueError instead of being silently truncated by setcchar().
The new read methods window.get_wstr() and window.in_wstr() are the wide-character counterparts of window.getstr() and window.instr(), returning a str rather than a bytes object.
The new module functions curses.erasewchar(), curses.killwchar() and curses.wunctrl() are the wide-character counterparts of curses.erasechar(), curses.killchar() and curses.unctrl(), returning a str rather than a bytes object.
Linked PRs
The
cursescharacter-cell window methods currently accept only a single narrow character -- anint, a one-bytebytes, or a one-characterstr-- and most of the wide-character (cchar_t) part of the X/Open Curses API is unwrapped. A character cell can actually hold a full complex character: one spacing character optionally followed by combining characters. There is also no way to read text back asstrrather thanbytes, nor to query the wide erase/kill characters or get a printable representation of a wide character.I propose to wrap the wide-character API, available when CPython is built against the wide-character
ncurseswlibrary.The character-cell methods
addch(),bkgd(),bkgdset(),border(),box(),echochar(),hline(),insch()andvline()additionally accept astrof a spacing character optionally followed by combining characters, dispatching to thencurseswwide-character functions (wadd_wch(),wbkgrnd(),wborder_set(),wecho_wchar(),whline_set(),wins_wch(),wvline_set(), ...).border()andbox()cannot mix integer or byte characters with wide-string characters in a single call. A cell is exactly one spacing character plus zero or more combining characters, so any extra spacing or control character (for example"ab", an emoji ZWJ sequence, or an emoji with a skin-tone modifier) is rejected withValueErrorinstead of being silently truncated bysetcchar().The new read methods
window.get_wstr()andwindow.in_wstr()are the wide-character counterparts ofwindow.getstr()andwindow.instr(), returning astrrather than abytesobject.The new module functions
curses.erasewchar(),curses.killwchar()andcurses.wunctrl()are the wide-character counterparts ofcurses.erasechar(),curses.killchar()andcurses.unctrl(), returning astrrather than abytesobject.Linked PRs