Skip to content

curses.window.inch() returns the wrong byte for a non-ASCII character on a wide build #153862

Description

@serhiy-storchaka

Bug report

On a wide (ncursesw) build, window.inch() and window.mvinch() return the low 8 bits of a character's code point instead of its locale-encoded byte, so they disagree with instr() for the same cell. It is invisible for ASCII/Latin-1 (where the byte equals the low byte of the code point) and only shows for other single-byte characters.

Under an ISO-8859-15 locale ( U+20AC encodes to 0xA4):

import curses, locale
locale.setlocale(locale.LC_ALL, '')   # run under e.g. LANG=en_US.ISO-8859-15
def main(stdscr):
    stdscr.addstr(0, 0, '€')
    print(hex(stdscr.instr(0, 0, 1)[0]))                 # 0xa4  — correct
    print(hex(stdscr.inch(0, 0) & curses.A_CHARTEXT))    # 0xac  — wrong
curses.wrapper(main)

Cause: ncurses' winch() returns the raw cell character with no locale conversion, unlike instr() and getbkgd(). getbkgd() is not affected. Reported upstream (bug-ncurses), where the 8-bit behavior is considered documented, so this should be worked around on the CPython side by re-encoding the cell to its locale byte when the character has a single-byte form.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13bugs and security fixes3.14bugs and security fixes3.15pre-release feature fixes, bugs and security fixes3.16new features, bugs and security fixestype-bugAn unexpected behavior, bug, or error

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions