Re: curses inch()/mvinch() mangle non-ASCII characters of an 8-bit locale on a wide build
Serhiy Storchaka <[email protected]> Mon, 3 Aug 2026 14:38:10 +0300
| Newsgroups | gmane.comp.lib.ncurses.bugs |
|---|---|
| Message-ID | <[email protected]> |
One more thing about this, separate from whether the 8-bit limit is intended: winch() does not do what curs_inch.3x says. The page says these functions "extract only the low-order eight bits of the character code from the cell". On a wide build they extract all of it -- the bits above the eighth are not discarded, they are OR-ed into the attribute and colour fields. setlocale(LC_ALL, ""); initscr(); start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); attrset(COLOR_PAIR(1)); mvaddstr(0, 0, "€"); /* EURO SIGN, in a UTF-8 locale */ chtype c = mvinch(0, 0); gives, for a cell that was written with colour pair 1: winch() = 0x000021ac & A_CHARTEXT = 0xac & A_COLOR = 0x00002100 PAIR_NUMBER() = 33 0x20 is the high byte of U+20AC; it lands in A_COLOR, so the pair reads back as 33 rather than 1. lib_winch.c: returnChtype((chtype) CharOf(win->_line[win->_cury].text[win->_ | AttrOf(win->_line[win->_cury].text[win->_curx])) and on a wide build CharOf() is the raw wchar_t (curses.priv.h:1464), while the narrow ChCharOf() masks with A_CHARTEXT (curses.priv.h:1427). the wide one the same way would make the code agree with the manual would leave the rendition bits usable. This is not about 8-bit locales -- the example above is UTF-8. Eve that wants nothing but the rendition from inch() gets a wrong answe We have worked around it in Python's curses binding, so nothing is blocked on our side; I am only reporting that the behaviour and the documentation disagree. https://github.com/python/cpython/issues/153862