From 207db14301fe3374da7fefc0f891a2a450392e53 Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Sat, 30 May 2026 13:53:13 +0200 Subject: [PATCH] tty: handle indexed colors separately from RGB color space The terminfo entries from the standard ncurses distribution have peculiar settings for entries supporting 24 bit colors. The direct entries mix indexed and RGB values into an incompatible mess. This commit adds a simple workaround for the tty port. Colors are initialised as if only 8 ANSI colors are available. This does not affect color customisation from the symsets. The curses port is affected as well. But I am not yet comfortable to refactor a large part of the code for an absolute edge case. --- win/tty/termcap.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/win/tty/termcap.c b/win/tty/termcap.c index d5fb0f755..ff8c4c2bf 100644 --- a/win/tty/termcap.c +++ b/win/tty/termcap.c @@ -31,6 +31,7 @@ static void analyze_seq(char *, int *, int *); #if (defined(TERMLIB) || defined(ANSI_DEFAULT)) static void init_hilite(void); static void kill_hilite(void); +static int indexed_color_count(void); #endif /* (see tcap.h) -- nh_CM, nh_ND, nh_CD, nh_HI,nh_HE, nh_US,nh_UE, ul_hack */ @@ -947,6 +948,15 @@ init_hilite(void) colors = tgetnum(nhStr("Co")); iflags.colorcount = colors; +#ifdef NCURSES_VERSION + /* The standard ncurses terminfo entries that support 24-bit colors + (*-direct) map the standard 8/16/256 colors onto the beginning + of the 24-bit color range. For example, rgb(0,0,1) appears as red + instead of nearly black. iflags.colorcount should retain the actual + supported color count, while for default color initialization we + take the available indexed colors into consieration. */ + colors = indexed_color_count(); +#endif int md_len = 0; if (colors < 8 || !MD || !*MD @@ -1054,7 +1064,7 @@ kill_hilite(void) if (hilites[CLR_BLACK] != hilites[CLR_BLUE]) free(hilites[CLR_BLACK]), hilites[CLR_BLACK] = NULL; } - if (tgetnum(nhStr("Co")) >= 16) { + if (indexed_color_count() >= 16) { if (hilites[CLR_BLUE]) free(hilites[CLR_BLUE]); if (hilites[CLR_GREEN]) @@ -1096,6 +1106,21 @@ kill_hilite(void) hilites[c] = NULL; } +static int +indexed_color_count(void) +{ +#ifdef NCURSES_VERSION + /* ncurses adds the non-standard attribute CO for "number of indexed + colors overlaying RGB space". */ + int idx_colors = tgetnum(nhStr("CO")); + if (idx_colors > 0) { + return idx_colors; + } +#endif + + return tgetnum(nhStr("Co")); +} + #else /* UNIX && TERMINFO */ #ifndef TOS