Feature or enhancement
gh-151757 added wide and combining character support to the curses character-cell write methods (they now accept a str cell), but the module still has no representation for a styled wide cell — a curses cchar_t: a spacing character plus combining marks together with its attributes and color pair. As a result none of the wide-character (*_wch) functions, which take or return a cchar_t or a cchar_t array, are exposed.
The gap is most visible on the read side: window.inch() and window.getbkgd() return a packed chtype integer (8-bit character + A_* attributes + a color pair clamped to COLOR_PAIR()), which cannot represent a wide or combining character and clamps the color pair. There is currently no way to read back a styled wide cell at all. This is the long-standing request in gh-83395 ("Add curses.window.in_wch", with the now-stale PR #17825).
This issue tracks adding the full cchar_t API to the curses module. All of it requires building against a wide-character version of the curses library (ncursesw). The work will land step by step.
1. The cchar_t wrapper and the functions that take/return a single cell
A new immutable curses.complexchar(text, attr=0, pair=0) type. str(cc) is the cell's text; cc.attr and cc.pair are its rendition (read-only). The color pair is stored separately, not packed via COLOR_PAIR(), so it is not limited to the value that fits in a chtype.
Methods that take or return one cell:
- read (return a
complexchar):window.in_wch([y, x])(wideinch),window.getbkgrnd()(widegetbkgd). These are the only genuinely new entry points needed -- the existinginch/getbkgdreturn a packedchtypeint that cannot represent a wide/combining cell or an unclamped color pair. (This mirrors the existinggetchvsget_wchsplit, justified by the different return type.) - write: no new methods. Every existing single-cell method simply also accepts a
complexchar(its rendition then comes from the cell, and the method's ownattrargument, if any, is ignored):addch,insch,echochar,bkgd,bkgdset,border,box,hline,vline. Acomplexcharis built explicitly withcomplexchar(text, attr, pair). This is also how the widecchar_tform of the line-drawing functions (border_set/box_set/hline_set/vline_set) is reached, without adding*_setmethods. Dedicatedadd_wch/ins_wch/echo_wchar/bkgrnd/bkgrndsetare deliberately not added: once the chtype method accepts acomplexchar, a parallel wide writer carries no extra capability.
(setcchar/getcchar need not be exposed separately: the complexchar object already packs/unpacks a cell.)
2. Arrays of cells (cchar_t array functions)
The same split applies one level up:
- read (new entry point):
window.in_wchstr([y, x,] n)(a single method with an optional count, likeinstr/in_wstr), returning the run of styled cells. There is no existing method that returns an array of styled cells (instrreturnsbytes,in_wstrreturnsstr, both stripping rendition), so it is needed. It returns an immutablecurses.complexstr-- the "complex character string" of the X/Open spec, the string counterpart ofcomplexchar(asstris to a single character). It is a dedicated packed type owning the contiguouscchar_tbuffer thatwin_wchnstr()fills directly (no per-cell object allocation on read): it decodes acomplexcharlazily on indexing (arr[i]),len(arr)is the cell count,str(arr)joins the cells' text, and slicing/concatenation produce newcomplexstrinstances. Immutable likestr, so it is hashable and its raw buffer can be handed straight back toadd_wchnstr()-- an array read and re-written is a zero-copy round-trip. - write: no new methods. Extend the existing
addstr/addnstr/insstr/insnstrto also accept a sequence of cells, in addition to a plainstr. A plainstrkeeps its current meaning; a sequence of cells is written viaadd_wchnstr-- acomplexstrvia its raw buffer (zero-copy), or any generic sequence (each item acomplexcharor astr) packed into a temporarycchar_tarray. Soadd_wchstr/add_wchnstrare not added, for the same reasonadd_wchwas not. (To build or edit a run, use an ordinarylistofcomplexchar; the packedcomplexstris the immutable form you get back from a read.)
Notes
- This resolves Add curses.window.in_wch #83395 (
in_wch). - The existing single-cell methods (
addch/insch/echochar/bkgd/bkgdset/border/box/hline/vline) already accept astrcell (Add wide-character (cchar_t) support to the curses module #151757); they now also accept acomplexchar, which is the styledcchar_tform carrying attributes and a color pair.