sever extracolors from utf8map and ENHANCED_SYMBOLS

move the custom color data into its own field in the glyphmap
and disassociate it from the unicode/utf8 stuff.

move the glyphcache stuff during options processing and parsing
into new file glyphs.c and out of utf8map.c, and make it
general, and not part of ENHANCED_SYMBOLS.

Do the groundwork for allowing glyph color customizations to
work when any symset is loaded and not restrict it only to
the enhanced1 H_UTF8 symsets.

The customizations in effect are still affiliated with a particular
symset.

Also closes #1224, but the PR itself references a data structure
made obsolete by this commit. The curses comment from the PR was
added into the code.

The PR also made several suggestions, but only the first
one has been included in this commit (and no longer based on
the handler), that being:
"allow defining colors if other symbol handling modes are used
(possibly limited to the standard 16 colors)."

FredrIQ also wrote the following suggestions in PR#1224:

Something I was also contemplating, unrelated to implementation of this
support in curses, would be the ability for the following:

allow defining colors if other symbol handling modes are used (possibly limited to the standard 16 colors)
allow defining attributes (for example: glyph:G_pet_female_kitten:U+0066/red/underline)
allow specifying glyphs as wildcards for defining global color/attribute changes

Something I also want to see are keywords for "don't change the current defined data". If this
were to be added, you could for example do this:
OPTIONS=glyph:G_*_fox:U+0064/blue
OPTIONS=glyph:G_statue_*:basechar/gray/underline
for "make all foxes use a blue color, make all statues gray with underline" without needing
to specify the relevant character for every statue. This ("basechar", "basefg", etc)
should perhaps also be added for MENUCOLORS and statushilites, so that you can, for
example, underline all items being worn without needing to specify a bunch of
near-duplicate rules for combining BUC colors + underline worn items
as per #1064
This commit is contained in:
nhmall
2024-03-23 15:33:00 -04:00
parent ef17c7ac2b
commit ba00dc9066
36 changed files with 1799 additions and 1589 deletions

View File

@@ -1112,8 +1112,9 @@ struct window_procs Qt_procs = {
| WC2_SELECTSAVED
#endif
#ifdef ENHANCED_SYMBOLS
| WC2_U_UTF8STR | WC2_U_24BITCOLOR
| WC2_U_UTF8STR
#endif
| WC2_EXTRACOLORS
| WC2_STATUSLINES),
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
nethack_qt_::NetHackQtBind::qt_init_nhwindows,

View File

@@ -582,20 +582,20 @@ void NetHackQtMapViewport::PrintGlyph(int x, int y,
Glyphcolor(x, y) = (uint32) glyphinfo->gm.sym.color;
GlyphFramecolor(x, y) = (uint32) bkglyphinfo->framecolor;
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u
&& glyphinfo->gm.u->utf8str) {
if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u && glyphinfo->gm.u->utf8str) {
Glyphttychar(x, y) = glyphinfo->gm.u->utf32ch;
if (glyphinfo->gm.u->ucolor != 0) {
if ((glyphinfo->gm.u->ucolor & NH_BASIC_COLOR) == 0) {
Glyphcolor(x, y) = glyphinfo->gm.u->ucolor | 0x80000000;
} else {
Glyphcolor(x, y) =
(uint32) glyphinfo->gm.u->ucolor & ~NH_BASIC_COLOR;
}
}
}
#endif
if (glyphinfo->gm.nhcolor != 0) {
uint32 nhcolor = COLORVAL(glyphinfo->gm.nhcolor);
if (glyphinfo->gm.nhcolor == nhcolor) {
/* 24-bit color */
Glyphcolor(x, y) = COLORVAL(glyphinfo->gm.nhcolor) | 0x80000000;
} else {
/* NH_BASIC_COLOR */
Glyphcolor(x, y) = COLORVAL(glyphinfo->gm.nhcolor);
}
}
Glyphflags(x, y) = glyphinfo->gm.glyphflags;
Glyphtileidx(x, y) = (unsigned short) glyphinfo->gm.tileidx;
Changed(x, y);

View File

@@ -127,19 +127,34 @@ X11_print_glyph(
X11_map_symbol *ch_ptr;
X11_color color;
unsigned special;
uint32 nhcolor = 0;
int colordif;
X11_color *co_ptr;
color = glyphinfo->gm.sym.color;
special = glyphinfo->gm.glyphflags;
ch = glyph_char(glyphinfo);
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u != NULL
&& glyphinfo->gm.u->ucolor != 0
&& (glyphinfo->gm.u->ucolor & NH_BASIC_COLOR) != 0)
color = glyphinfo->gm.u->ucolor & ~NH_BASIC_COLOR;
#endif
if (glyphinfo->gm.nhcolor != 0) {
if ((glyphinfo->gm.nhcolor & NH_BASIC_COLOR) != 0) {
/* NH_BASIC_COLOR */
color = COLORVAL(glyphinfo->gm.nhcolor);
#if 0
} else if (iflags.colorcount == 256
&& (X11_procs.wincap2 & WC2_EXTRACOLORS) != 0
&& (glyphinfo->gm.nhcolor & NH_BASIC_COLOR) == 0) {
int clr256idx;
uint32 closecolor = 0;
if (closest_color(COLORVAL(glyphinfo->gm.nhcolor),
&closecolor, &clr256idx))
nhcolor = COLORVAL(closecolor);
#endif
} else {
/* 24-bit color, NH_BASIC_COLOR == 0 */
nhcolor = COLORVAL(glyphinfo->gm.nhcolor);
}
}
if (special != map_info->tile_map.glyphs[y][x].glyphflags) {
map_info->tile_map.glyphs[y][x].glyphflags = special;
update_bbox = TRUE;
@@ -160,16 +175,11 @@ X11_print_glyph(
&& iflags.use_inverse))
? CLR_MAX : 0;
color += colordif;
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && glyphinfo->gm.u != NULL
&& glyphinfo->gm.u->ucolor != 0
&& (glyphinfo->gm.u->ucolor & NH_BASIC_COLOR) == 0) {
color = glyphinfo->gm.u->ucolor | 0x80000000;
if (colordif != 0) {
color |= 0x40000000;
}
}
#endif
if (nhcolor != 0)
color = nhcolor | 0x80000000;
if (colordif != 0)
color |= 0x40000000;
if (*co_ptr != color) {
*co_ptr = color;
if (!map_info->is_tile)

View File

@@ -63,6 +63,7 @@ struct window_procs curses_procs = {
#ifdef CURSES_UNICODE
| WC2_U_UTF8STR
#endif
| WC2_EXTRACOLORS
#ifdef SELECTSAVED
| WC2_SELECTSAVED
#endif
@@ -912,6 +913,7 @@ curses_print_glyph(
int glyph;
int ch;
int color;
uint32 nhcolor = 0;
unsigned int special;
int attr = -1;
@@ -919,6 +921,22 @@ curses_print_glyph(
special = glyphinfo->gm.glyphflags;
ch = glyphinfo->ttychar;
color = glyphinfo->gm.sym.color;
/* Extra color handling
* 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.
* Thus, we only allow users to customize glyph colors to the basic NetHack
* colors. */
if (glyphinfo->gm.nhcolor != 0
&& (curses_procs.wincap2 & WC2_EXTRACOLORS) != 0) {
if ((glyphinfo->gm.nhcolor & NH_BASIC_COLOR) != 0) {
color = COLORVAL(glyphinfo->gm.nhcolor);
#if 0
} else {
/* 24-bit color, NH_BASIC_COLOR == 0 */
nhcolor = COLORVAL(glyphinfo->gm.nhcolor);
#endif
}
}
if ((special & MG_PET) && iflags.hilite_pet) {
attr = curses_convert_attr(iflags.wc2_petattr);
}
@@ -955,20 +973,15 @@ curses_print_glyph(
}
}
curses_putch(wid, x, y, ch,
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u
&& glyphinfo->gm.u->utf8str) {
curses_putch(wid, x, y, ch, glyphinfo->gm.u, color,
bkglyphinfo->framecolor, attr);
} else {
curses_putch(wid, x, y, ch, NULL, color,
bkglyphinfo->framecolor, attr);
}
#else
curses_putch(wid, x, y, ch, color,
bkglyphinfo->framecolor, attr);
(SYMHANDLING(H_UTF8)
&& glyphinfo->gm.u && glyphinfo->gm.u->utf8str)
? glyphinfo->gm.u : NULL,
#endif
(nhcolor != 0) ? nhcolor : color,
bkglyphinfo->framecolor, attr);
}
/*

View File

@@ -1360,8 +1360,9 @@ main(int argc UNUSED, char *argv[] UNUSED)
Fprintf(ofp, "%smaxmontile = %d,\n", indent, lastmontile);
Fprintf(ofp, "%smaxobjtile = %d,\n", indent, lastobjtile);
Fprintf(ofp, "%smaxothtile = %d;\n\n", indent, lastothtile);
Fprintf(ofp, "#define NO_NHCOLOR (0U)\n\n");
Fprintf(ofp, "/* glyph, ttychar, { %s%s } */\n",
"glyphflags, {color, symidx}, ovidx, tileidx", enhanced);
"glyphflags, { NO_COLOR, symidx }, NO_NHCOLOR, ovidx, tileidx", enhanced);
#ifdef ENHANCED_SYMBOLS
enhanced = ", 0"; /* replace ", utf8rep" since we're done with that */
#endif
@@ -1369,7 +1370,7 @@ main(int argc UNUSED, char *argv[] UNUSED)
Fprintf(ofp, "%sNO_GLYPH, ' ', NO_COLOR,\n", indent);
Fprintf(ofp, "%s%s/* glyph_map */\n", indent, indent);
Fprintf(ofp, "%s%s{ %s, TILE_UNEXPLORED%s }\n", indent, indent,
"MG_UNEXPL, { NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X }",
"MG_UNEXPL, { NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X }, NO_NHCOLOR",
enhanced);
Fprintf(ofp, "};\n");
Fprintf(ofp, "\nglyph_map glyphmap[MAX_GLYPH] = {\n");
@@ -1384,7 +1385,7 @@ main(int argc UNUSED, char *argv[] UNUSED)
/*NOTREACHED*/
}
Fprintf(ofp,
" { 0U, { 0, 0 }, %4d%s }, /* [%04d] %s:%03d %s */\n",
" { 0U, { NO_COLOR, 0 }, NO_NHCOLOR, %4d%s }, /* [%04d] %s:%03d %s */\n",
tilenum, enhanced, i,
tilesrc_texts[tilelist[tilenum]->src],
tilelist[tilenum]->file_entry,

View File

@@ -17,8 +17,9 @@ static char *e_atr2str(int);
void cmov(int, int);
void nocmov(int, int);
void term_start_24bitcolor(struct unicode_representation *);
void term_end_24bitcolor(void);
void term_start_extracolor(uint32 nhcolor);
void term_end_extracolor(void);
void term_start_256color(int);
#if defined(TERMLIB)
#if (!defined(UNIX) || !defined(TERMINFO)) && !defined(TOS)
@@ -1468,30 +1469,29 @@ term_start_bgcolor(int color)
xputs(tmp);
}
#ifdef ENHANCED_SYMBOLS
#ifndef SEP2
#define tcfmtstr "\033[38;2;%ld;%ld;%ldm"
#ifdef UNIX
#define tcfmtstr24bit "\033[38;2;%u;%u;%um"
#define tcfmtstr "\033[38;2;%d;%d;%dm"
#define tcfmtstr24bit "\033[38;2;%d;%d;%dm"
#define tcfmtstr256 "\033[38;5;%dm"
#else
#define tcfmtstr24bit "\033[38;2;%lu;%lu;%lum"
#define tcfmtstr "\033[38;2;%ld;%ld;%ldm"
#define tcfmtstr24bit "\033[38;2;%ld;%ld;%ldm"
#define tcfmtstr256 "\033[38:5:%ldm"
#endif
#endif
static void emit24bit(long mcolor);
static void emit24bit(uint32 color24bit);
static void emit256(int u256coloridx);
static void emit24bit(long mcolor)
static void emit24bit(uint32 color24bit)
{
static char tcolorbuf[QBUFSZ];
Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr,
((mcolor >> 16) & 0xFF), /* red */
((mcolor >> 8) & 0xFF), /* green */
((mcolor >> 0) & 0xFF)); /* blue */
((color24bit >> 16) & 0xFF), /* red */
((color24bit >> 8) & 0xFF), /* green */
((color24bit >> 0) & 0xFF)); /* blue */
xputs(tcolorbuf);
}
@@ -1505,26 +1505,25 @@ static void emit256(int u256coloridx)
}
void
term_start_24bitcolor(struct unicode_representation *urep)
term_start_256color(int idx)
{
if (urep && SYMHANDLING(H_UTF8)) {
/* color 0 has bit 0x1000000 set */
long mcolor = (urep->ucolor & 0xFFFFFF);
if (iflags.colorcount == 256)
emit256(urep->u256coloridx);
else
emit24bit(mcolor);
}
emit256(idx);
}
void
term_end_24bitcolor(void)
term_start_extracolor(uint32 nhcolor)
{
if (SYMHANDLING(H_UTF8)) {
xputs("\033[0m");
}
}
#endif /* ENHANCED_SYMBOLS */
#endif /* TTY_GRAPHICS && !NO_TERMS */
/* color 0 has bit NH_BASIC_COLOR set */
uint32 modcolor = COLORVAL(nhcolor);
emit24bit(modcolor);
}
void
term_end_extracolor(void)
{
xputs("\033[0m");
}
#endif /* TTY_GRAPHICS && !NO_TERMS */
/*termcap.c*/

View File

@@ -122,7 +122,7 @@ struct window_procs tty_procs = {
| WC2_DARKGRAY | WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_STATUSLINES
| WC2_U_UTF8STR | WC2_PETATTR
#if !defined(NO_TERMS) || defined(WIN32CON)
| WC2_U_24BITCOLOR
| WC2_EXTRACOLORS
#endif
),
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
@@ -252,6 +252,9 @@ static void status_sanity_check(void);
void g_pututf8(uint8 *utf8str);
#endif
/* this is always present to reduce preproc conditional code */
static boolean calling_from_update_inventory = FALSE;
#ifdef TTY_PERM_INVENT
static struct tty_perminvent_cell emptyttycell = {
0, 0, 0, { 0 }, NO_COLOR + 1
@@ -270,7 +273,6 @@ static long last_glyph_reset_when;
#ifndef NOINVSYM /* invent.c */
#define NOINVSYM '#'
#endif
static boolean calling_from_update_inventory = FALSE;
static int ttyinv_create_window(int, struct WinDesc *);
static void ttyinv_remove_data(struct WinDesc *, boolean);
static void ttyinv_add_menu(winid, struct WinDesc *, char ch, int attr,
@@ -3800,11 +3802,9 @@ tty_print_glyph(
{
boolean inverse_on = FALSE, colordone = FALSE, glyphdone = FALSE;
boolean petattr = FALSE;
int ch, color;
int ch;
uint32 color, nhcolor = 0;
unsigned special;
#ifdef ENHANCED_SYMBOLS
boolean color24bit_on = FALSE;
#endif
HUPSKIP();
#ifdef CLIPPING
@@ -3832,31 +3832,48 @@ tty_print_glyph(
}
#endif
if (iflags.use_color) {
if (color != ttyDisplay->color) {
if (ttyDisplay->color != NO_COLOR)
term_end_color();
}
#ifdef ENHANCED_SYMBOLS
/* we don't link with termcap.o if NO_TERMS is defined */
if ((tty_procs.wincap2 & WC2_U_24BITCOLOR) && SYMHANDLING(H_UTF8)
&& iflags.colorcount >= 256
#ifdef TTY_PERM_INVENT
&& !calling_from_update_inventory
#endif
&& glyphinfo->gm.u && glyphinfo->gm.u->ucolor) {
if ((glyphinfo->gm.u->ucolor & NH_BASIC_COLOR) == 0) {
term_start_24bitcolor(glyphinfo->gm.u);
color24bit_on = TRUE;
colordone = TRUE;
uint32 closecolor;
int clridx;
if (iflags.colorcount >= 256
&& glyphinfo->gm.nhcolor != 0
&& !calling_from_update_inventory
&& (tty_procs.wincap2 & WC2_EXTRACOLORS) != 0) {
if ((glyphinfo->gm.nhcolor & NH_BASIC_COLOR) != 0) {
/* don't set colordone or nhcolor */
color = COLORVAL(glyphinfo->gm.nhcolor);
} else if (iflags.colorcount == 256) {
if (closest_color(COLORVAL(glyphinfo->gm.nhcolor),
&closecolor, &clridx)) {
if (ttyDisplay->color != NO_COLOR) {
term_end_color();
}
ttyDisplay->colorflags = 0;
term_start_256color(clridx);
colordone = TRUE;
}
} else {
color = glyphinfo->gm.u->ucolor & ~NH_BASIC_COLOR;
nhcolor = COLORVAL(glyphinfo->gm.nhcolor);
if (ttyDisplay->color != NO_COLOR) {
term_end_color();
}
ttyDisplay->colorflags = 0;
term_start_extracolor(nhcolor);
colordone = TRUE;
}
}
#endif
if (!colordone) {
/* NH_BASIC_COLOR processing */
ttyDisplay->colorflags = NH_BASIC_COLOR;
if (color != ttyDisplay->color) {
if (ttyDisplay->color != NO_COLOR) {
term_end_color();
}
}
ttyDisplay->color = color;
if (color != NO_COLOR)
term_start_color(color);
if (color != NO_COLOR) {
term_start_color(ttyDisplay->color);
}
}
} /* iflags.use_color aka iflags.wc_color */
@@ -3865,9 +3882,9 @@ tty_print_glyph(
(tried bold for ice but it didn't look very good; inverse is easier
to see although the Valkyrie quest ends up being hard on the eyes) */
if (iflags.use_color
&& bkglyphinfo && bkglyphinfo->framecolor != NO_COLOR) {
ttyDisplay->framecolor = bkglyphinfo->framecolor;
term_start_bgcolor(bkglyphinfo->framecolor);
&& bkglyphinfo && bkglyphinfo->gm.nhcolor != NO_COLOR) {
ttyDisplay->framecolor = bkglyphinfo->gm.nhcolor;
term_start_bgcolor(bkglyphinfo->gm.nhcolor);
} else if ((special & MG_PET) != 0 && iflags.hilite_pet) {
term_start_attr(iflags.wc2_petattr);
petattr = TRUE;
@@ -3906,15 +3923,15 @@ tty_print_glyph(
/* turn off color as well, turning off ATR_INVERSE may have done
this already and if so, we won't know the current state unless
we do it explicitly */
if (ttyDisplay->color != NO_COLOR
|| ttyDisplay->framecolor != NO_COLOR) {
term_end_color();
ttyDisplay->color = ttyDisplay->framecolor = NO_COLOR;
if (ttyDisplay->colorflags == NH_BASIC_COLOR) {
if (ttyDisplay->color != NO_COLOR
|| ttyDisplay->framecolor != NO_COLOR) {
term_end_color();
ttyDisplay->color = ttyDisplay->framecolor = NO_COLOR;
}
} else {
term_end_extracolor();
}
#ifdef ENHANCED_SYMBOLS
if (color24bit_on)
term_end_24bitcolor();
#endif
}
print_vt_code1(AVTC_GLYPH_END);

View File

@@ -977,19 +977,16 @@ paintGlyph(PNHMapWindow data, int i, int j, RECT * rect)
&& glyphinfo->gm.u
&& glyphinfo->gm.u->utf8str) {
ch = glyphinfo->gm.u->utf32ch;
if (glyphinfo->gm.u->ucolor != 0) {
if ((glyphinfo->gm.u->ucolor & NH_BASIC_COLOR) == 0) {
rgbcolor = RGB(
(glyphinfo->gm.u->ucolor >> 16) & 0xFF,
(glyphinfo->gm.u->ucolor >> 8) & 0xFF,
(glyphinfo->gm.u->ucolor >> 0) & 0xFF);
} else {
color = (int) (glyphinfo->gm.u->ucolor & ~NH_BASIC_COLOR);
rgbcolor = nhcolor_to_RGB(color);
}
}
}
#endif
if ((glyphinfo->gm.nhcolor & NH_BASIC_COLOR) == 0) {
rgbcolor = RGB((glyphinfo->gm.nhcolor >> 16) & 0xFF,
(glyphinfo->gm.nhcolor >> 8) & 0xFF,
(glyphinfo->gm.nhcolor >> 0) & 0xFF);
} else {
color = (int) COLORVAL(glyphinfo->gm.nhcolor);
rgbcolor = nhcolor_to_RGB(color);
}
if (((data->map[i][j].gm.glyphflags & MG_PET) && iflags.hilite_pet)
|| ((data->map[i][j].gm.glyphflags & (MG_DETECT | MG_BW_LAVA
| MG_BW_ICE | MG_BW_SINK
@@ -1065,7 +1062,7 @@ static void setGlyph(PNHMapWindow data, int i, int j,
if ((data->map[i][j].glyph != fg->glyph)
|| (data->bkmap[i][j].glyph != bg->glyph)
|| data->map[i][j].ttychar != fg->ttychar
|| data->map[i][j].gm.sym.color != fg->gm.sym.color
|| data->map[i][j].gm.nhcolor != fg->gm.nhcolor
|| data->map[i][j].gm.glyphflags != fg->gm.glyphflags
|| data->map[i][j].gm.tileidx != fg->gm.tileidx) {
data->map[i][j] = *fg;

View File

@@ -93,7 +93,7 @@ struct window_procs mswin_procs = {
WC2_HITPOINTBAR | WC2_FLUSH_STATUS | WC2_RESET_STATUS | WC2_HILITE_STATUS |
#endif
#ifdef ENHANCED_SYMBOLS
WC2_U_UTF8STR | WC2_U_24BITCOLOR |
WC2_U_UTF8STR | WC2_EXTRACOLORS |
#endif
0L,
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */