Merge branch 'ars3niy-curses256' into NetHack-5.0

Closes #1561
This commit is contained in:
Patric Mueller
2026-06-19 16:36:53 +02:00
8 changed files with 64 additions and 49 deletions
-9
View File
@@ -128,14 +128,6 @@ extern void curses_refresh_nethack_windows(void);
extern void curses_del_nhwin(winid wid); extern void curses_del_nhwin(winid wid);
extern void curses_del_wid(winid wid); extern void curses_del_wid(winid wid);
extern void curs_destroy_all_wins(void); extern void curs_destroy_all_wins(void);
#ifdef ENHANCED_SYMBOLS
extern void curses_putch(winid wid, int x, int y, int ch,
struct unicode_representation *u, int color,
int framecolor, int attrs);
#else
extern void curses_putch(winid wid, int x, int y, int ch, int color,
int framecolor, int attrs);
#endif
extern void curses_get_window_size(winid wid, int *height, int *width); extern void curses_get_window_size(winid wid, int *height, int *width);
extern boolean curses_window_has_border(winid wid); extern boolean curses_window_has_border(winid wid);
extern boolean curses_window_exists(winid wid); extern boolean curses_window_exists(winid wid);
@@ -145,7 +137,6 @@ extern void curses_puts(winid wid, int attr, const char *text);
extern void curses_clear_nhwin(winid wid); extern void curses_clear_nhwin(winid wid);
extern void curses_alert_win_border(winid wid, boolean onoff); extern void curses_alert_win_border(winid wid, boolean onoff);
extern void curses_alert_main_borders(boolean onoff); extern void curses_alert_main_borders(boolean onoff);
extern int get_framecolor(int nhcolor, int framecolor);
extern void curses_draw_map(int sx, int sy, int ex, int ey); extern void curses_draw_map(int sx, int sy, int ex, int ey);
extern boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey, extern boolean curses_map_borders(int *sx, int *sy, int *ex, int *ey,
int ux, int uy); int ux, int uy);
+2 -1
View File
@@ -886,7 +886,8 @@ static struct {
int index; int index;
uint32 value; uint32 value;
} color_256_definitions[] = { } color_256_definitions[] = {
/* color values are from unnethack */ /* from unnethack - these are the colors used by xterm
when $TERM is set to xterm-256color */
{ 16, 0x000000 }, { 17, 0x00005f }, { 18, 0x000087 }, { 16, 0x000000 }, { 17, 0x00005f }, { 18, 0x000087 },
{ 19, 0x0000af }, { 20, 0x0000d7 }, { 21, 0x0000ff }, { 19, 0x0000af }, { 20, 0x0000d7 }, { 21, 0x0000ff },
{ 22, 0x005f00 }, { 23, 0x005f5f }, { 24, 0x005f87 }, { 22, 0x005f00 }, { 23, 0x005f5f }, { 24, 0x005f87 },
+7 -5
View File
@@ -7,6 +7,7 @@
#include "hack.h" #include "hack.h"
#include "wincurs.h" #include "wincurs.h"
#include "cursinit.h" #include "cursinit.h"
#include "cursmisc.h"
/* Initialization and startup functions for curses interface */ /* Initialization and startup functions for curses interface */
@@ -334,18 +335,18 @@ curses_init_nhcolors(void)
/* COLOR_foo + 8 means COLOR | A_BOLD when COLORS < 16 */ /* COLOR_foo + 8 means COLOR | A_BOLD when COLORS < 16 */
/* otherwise assume the terminal has least 16 different colors */ /* otherwise assume the terminal has least 16 different colors */
/* these map to the NetHack CLR_ defines */ /* these map to the NetHack CLR_ defines */
static const int fg_clr[16] = { static const int basic_fg_clr[16] = {
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE,
-1, COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8, -1, COLOR_RED + 8, COLOR_GREEN + 8, COLOR_YELLOW + 8,
COLOR_BLUE + 8, COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8 COLOR_BLUE + 8, COLOR_MAGENTA + 8, COLOR_CYAN + 8, COLOR_WHITE + 8
}; };
static const int bg_clr[8] = { static const int bg_clr[CURSES_NUM_BACKGROUND_COLORS] = {
-1, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, -1, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
}; };
int bg, nhclr; int bg, nhclr;
int maxc = (COLORS >= 16) ? 16 : 8; int maxc = curses_has_256color() ? 256 : (COLORS >= 16) ? 16 : 8;
if (!has_colors()) if (!has_colors())
return; return;
@@ -353,8 +354,9 @@ curses_init_nhcolors(void)
use_default_colors(); use_default_colors();
for (nhclr = CLR_BLACK; nhclr < maxc; nhclr++) { for (nhclr = CLR_BLACK; nhclr < maxc; nhclr++) {
for (bg = 0; bg < 8; bg++) { for (bg = 0; bg < CURSES_NUM_BACKGROUND_COLORS; bg++) {
init_pair((maxc * bg) + nhclr + 1, fg_clr[nhclr], bg_clr[bg]); int fg_color = (nhclr < 16) ? basic_fg_clr[nhclr] : nhclr;
init_pair((maxc * bg) + nhclr + 1, fg_color, bg_clr[bg]);
} }
} }
+15 -16
View File
@@ -7,6 +7,7 @@
#include "hack.h" #include "hack.h"
#include "color.h" #include "color.h"
#include "wincurs.h" #include "wincurs.h"
#include "curswins.h"
#ifdef CURSES_UNICODE #ifdef CURSES_UNICODE
#include <locale.h> #include <locale.h>
#endif #endif
@@ -939,15 +940,16 @@ curses_print_glyph(
{ {
int glyph; int glyph;
int ch; int ch;
int color; struct glyph_attributes attr;
int nhcolor = 0;
unsigned int special; unsigned int special;
int attr = -1;
attr.attribute_flags = -1;
glyph = glyphinfo->glyph; glyph = glyphinfo->glyph;
special = glyphinfo->gm.glyphflags; special = glyphinfo->gm.glyphflags;
ch = glyphinfo->ttychar; ch = glyphinfo->ttychar;
color = glyphinfo->gm.sym.color; attr.basic_color = glyphinfo->gm.sym.color;
attr.color256 = 0;
attr.framecolor = bkglyphinfo->framecolor;
/* Extra color handling /* Extra color handling
* FIQ: The curses library does not support truecolor, only the more limited 256 * FIQ: The curses library does not support truecolor, only the more limited 256
* color mode. On top of this, the windowport only supports 16 color mode. * color mode. On top of this, the windowport only supports 16 color mode.
@@ -956,19 +958,17 @@ curses_print_glyph(
if (glyphinfo->gm.customcolor != 0 if (glyphinfo->gm.customcolor != 0
&& (curses_procs.wincap2 & WC2_EXTRACOLORS) != 0) { && (curses_procs.wincap2 & WC2_EXTRACOLORS) != 0) {
if ((glyphinfo->gm.customcolor & NH_BASIC_COLOR) != 0) { if ((glyphinfo->gm.customcolor & NH_BASIC_COLOR) != 0) {
color = COLORVAL(glyphinfo->gm.customcolor); attr.basic_color = COLORVAL(glyphinfo->gm.customcolor);
#if 0
} else { } else {
/* 24-bit color, NH_BASIC_COLOR == 0 */ /* 24-bit color, NH_BASIC_COLOR == 0 */
nhcolor = COLORVAL(glyphinfo->gm.customcolor); attr.color256 = glyphinfo->gm.color256idx;
#endif
} }
} }
if ((special & MG_PET) && iflags.hilite_pet) { if ((special & MG_PET) && iflags.hilite_pet) {
attr = curses_convert_attr(iflags.wc2_petattr); attr.attribute_flags = curses_convert_attr(iflags.wc2_petattr);
} }
if ((special & MG_DETECT) && iflags.use_inverse) { if ((special & MG_DETECT) && iflags.use_inverse) {
attr = A_REVERSE; attr.attribute_flags = A_REVERSE;
} }
if (SYMHANDLING(H_DEC)) if (SYMHANDLING(H_DEC))
ch = curses_convert_glyph(ch, glyph); ch = curses_convert_glyph(ch, glyph);
@@ -981,9 +981,9 @@ curses_print_glyph(
*/ */
if ((special & MG_OBJPILE) && iflags.hilite_pile) { if ((special & MG_OBJPILE) && iflags.hilite_pile) {
if (iflags.wc_color) if (iflags.wc_color)
color = get_framecolor(color, CLR_BLUE); attr.framecolor = CLR_BLUE;
else /* if (iflags.use_inverse) */ else /* if (iflags.use_inverse) */
attr = A_REVERSE; attr.attribute_flags = A_REVERSE;
} }
/* water and lava look the same except for color; when color is off /* water and lava look the same except for color; when color is off
(checked by core), render lava in inverse video so that it looks (checked by core), render lava in inverse video so that it looks
@@ -992,11 +992,11 @@ curses_print_glyph(
if ((special & (MG_BW_LAVA | MG_BW_ICE | MG_BW_SINK | MG_BW_ENGR)) if ((special & (MG_BW_LAVA | MG_BW_ICE | MG_BW_SINK | MG_BW_ENGR))
!= 0 && iflags.use_inverse) { != 0 && iflags.use_inverse) {
/* reset_glyphmap() only sets MG_BW_foo if color is off */ /* reset_glyphmap() only sets MG_BW_foo if color is off */
attr = A_REVERSE; attr.attribute_flags = A_REVERSE;
} }
/* highlight female monsters (wizard mode option) */ /* highlight female monsters (wizard mode option) */
if ((special & MG_FEMALE) && wizard && iflags.wizmgender) { if ((special & MG_FEMALE) && wizard && iflags.wizmgender) {
attr = A_REVERSE; attr.attribute_flags = A_REVERSE;
} }
} }
@@ -1006,8 +1006,7 @@ curses_print_glyph(
&& glyphinfo->gm.u && glyphinfo->gm.u->utf8str) && glyphinfo->gm.u && glyphinfo->gm.u->utf8str)
? glyphinfo->gm.u : NULL, ? glyphinfo->gm.u : NULL,
#endif #endif
(nhcolor != 0) ? nhcolor : color, &attr);
bkglyphinfo->framecolor, attr);
} }
+7 -1
View File
@@ -91,6 +91,12 @@ curses_read_char(void)
return ch; return ch;
} }
boolean
curses_has_256color(void)
{
return (COLORS >= 256) && (COLOR_PAIRS >= 256 * CURSES_NUM_BACKGROUND_COLORS);
}
/* Turn on or off the specified color and / or attribute */ /* Turn on or off the specified color and / or attribute */
void void
@@ -147,7 +153,7 @@ curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff)
if (use_bold) { if (use_bold) {
wattron(win, A_BOLD); wattron(win, A_BOLD);
} }
wattron(win, COLOR_PAIR(curses_color)); wcolor_set(win, curses_color, &curses_color);
} }
if (attr != NONE) { if (attr != NONE) {
+3
View File
@@ -8,8 +8,11 @@
/* Global declarations */ /* Global declarations */
#define CURSES_NUM_BACKGROUND_COLORS 8
int curses_getch(void); int curses_getch(void);
int curses_read_char(void); int curses_read_char(void);
boolean curses_has_256color(void);
void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff); void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff);
void curses_menu_color_attr(WINDOW *win, int color, int attr, int onoff); void curses_menu_color_attr(WINDOW *win, int color, int attr, int onoff);
void curses_bail(const char *mesg); void curses_bail(const char *mesg);
+20 -13
View File
@@ -40,7 +40,8 @@ typedef struct nhwd {
typedef struct nhchar { typedef struct nhchar {
int ch; /* character */ int ch; /* character */
int color; /* color info for character */ int color; /* basic color info for character */
int color256; /* extended color for the character, 0 if none */
int framecolor; /* background color info for character */ int framecolor; /* background color info for character */
int attr; /* attributes of character */ int attr; /* attributes of character */
struct unicode_representation *unicode_representation; struct unicode_representation *unicode_representation;
@@ -532,7 +533,7 @@ curses_putch(winid wid, int x, int y, int ch,
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
struct unicode_representation *unicode_representation, struct unicode_representation *unicode_representation,
#endif #endif
int color, int framecolor, int attr) const struct glyph_attributes *attr)
{ {
static boolean map_initted = FALSE; static boolean map_initted = FALSE;
int sx, sy, ex, ey; int sx, sy, ex, ey;
@@ -554,9 +555,10 @@ curses_putch(winid wid, int x, int y, int ch,
--x; /* map column [0] is not used; draw column [1] in first screen col */ --x; /* map column [0] is not used; draw column [1] in first screen col */
map[y][x].ch = ch; map[y][x].ch = ch;
map[y][x].color = color; map[y][x].color = attr->basic_color;
map[y][x].framecolor = framecolor; map[y][x].color256 = attr->color256;
map[y][x].attr = attr; map[y][x].framecolor = attr->framecolor;
map[y][x].attr = attr->attribute_flags;
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
map[y][x].unicode_representation = unicode_representation; map[y][x].unicode_representation = unicode_representation;
#endif #endif
@@ -763,22 +765,27 @@ is_main_window(winid wid)
coordinates without a refresh. Currently only used for the map. */ coordinates without a refresh. Currently only used for the map. */
/* convert nhcolor (fg) and framecolor (bg) to curses colorpair */ /* convert nhcolor (fg) and framecolor (bg) to curses colorpair */
int static int
get_framecolor(int nhcolor, int framecolor) get_framecolor(const nethack_char *nch)
{ {
int bgcolor = (nch->framecolor != NO_COLOR) ? nch->framecolor : 0;
/* curses_toggle_color_attr() adds the +1 and takes care of COLORS < 16 */ /* curses_toggle_color_attr() adds the +1 and takes care of COLORS < 16 */
return (16 * (framecolor % 8)) + (nhcolor % 16); if (curses_has_256color()) {
int color = nch->color256 ? nch->color256 : nch->color;
return (256 * (bgcolor % CURSES_NUM_BACKGROUND_COLORS)) + (color % 256);
} else
return (16 * (bgcolor % CURSES_NUM_BACKGROUND_COLORS)) + (nch->color % 16);
} }
static void static void
write_char(WINDOW * win, int x, int y, nethack_char nch) write_char(WINDOW * win, int x, int y, nethack_char nch)
{ {
int curscolor = nch.color, cursattr = nch.attr; int curscolor;
int cursattr = nch.attr;
if (nch.framecolor != NO_COLOR) { curscolor = get_framecolor(&nch);
curscolor = get_framecolor(nch.color, nch.framecolor); if ((nch.framecolor != NO_COLOR) && (nch.attr == A_REVERSE)) {
if (nch.attr == A_REVERSE) cursattr = A_NORMAL; /* hilited pet looks odd otherwise */
cursattr = A_NORMAL; /* hilited pet looks odd otherwise */
} }
curses_toggle_color_attr(win, curscolor, cursattr, ON); curses_toggle_color_attr(win, curscolor, cursattr, ON);
#if defined(CURSES_UNICODE) && defined(ENHANCED_SYMBOLS) #if defined(CURSES_UNICODE) && defined(ENHANCED_SYMBOLS)
+10 -4
View File
@@ -6,6 +6,12 @@
#ifndef CURSWIN_H #ifndef CURSWIN_H
# define CURSWIN_H # define CURSWIN_H
struct glyph_attributes {
int basic_color; // basic color
int color256; // extended color (0 if not defined), used when supported
int framecolor;
int attribute_flags;
};
/* Global declarations */ /* Global declarations */
@@ -27,11 +33,11 @@ void curses_del_wid(winid wid);
void curs_destroy_all_wins(void); void curs_destroy_all_wins(void);
#ifdef ENHANCED_SYMBOLS #ifdef ENHANCED_SYMBOLS
void curses_putch(winid wid, int x, int y, int ch, void curses_putch(winid wid, int x, int y, int ch,
struct unicode_representation *ur, int color, struct unicode_representation *ur,
int framecolor, int attrs); const struct glyph_attributes *attr);
#else #else
void curses_putch(winid wid, int x, int y, int ch, int color, void curses_putch(winid wid, int x, int y, int ch,
int framecolor, int attrs); const struct glyph_attributes *attr);
#endif #endif
void curses_get_window_xy(winid wid, int *x, int *y); void curses_get_window_xy(winid wid, int *x, int *y);
boolean curses_window_has_border(winid wid); boolean curses_window_has_border(winid wid);