From ba00dc9066bc6ca59d375fd8a1d27e8ce8c715e3 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 23 Mar 2024 15:33:00 -0400 Subject: [PATCH] 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 --- include/color.h | 3 +- include/decl.h | 5 +- include/extern.h | 51 +- include/hack.h | 2 - include/sym.h | 12 +- include/winprocs.h | 10 +- include/wintty.h | 36 +- include/wintype.h | 3 +- src/allmain.c | 10 +- src/coloratt.c | 229 +++++++ src/decl.c | 4 +- src/display.c | 46 +- src/glyphs.c | 1184 ++++++++++++++++++++++++++++++++++ src/options.c | 27 +- src/save.c | 1 + src/symbols.c | 203 +----- src/utf8map.c | 1134 +------------------------------- sys/msdos/Makefile.GCC | 38 +- sys/msdos/video.c | 2 +- sys/msdos/vidvesa.c | 4 +- sys/unix/Makefile.src | 34 +- sys/vms/Makefile.src | 8 +- sys/vms/Makefile_src.vms | 12 +- sys/vms/vmsbuild.com | 2 +- sys/windows/Makefile.mingw32 | 2 +- sys/windows/Makefile.nmake | 14 +- sys/windows/consoletty.c | 32 +- win/Qt/qt_bind.cpp | 3 +- win/Qt/qt_map.cpp | 22 +- win/X11/winmap.c | 42 +- win/curses/cursmain.c | 37 +- win/share/tilemap.c | 7 +- win/tty/termcap.c | 55 +- win/tty/wintty.c | 91 +-- win/win32/mhmap.c | 21 +- win/win32/mswproc.c | 2 +- 36 files changed, 1799 insertions(+), 1589 deletions(-) create mode 100644 src/glyphs.c diff --git a/include/color.h b/include/color.h index 4e28f8982..25dc27b2f 100644 --- a/include/color.h +++ b/include/color.h @@ -54,7 +54,8 @@ #define DRAGON_SILVER CLR_BRIGHT_CYAN #define HI_ZAP CLR_BRIGHT_BLUE -#define NH_BASIC_COLOR 0x1000000 +#define NH_BASIC_COLOR 0x1000000 +#define COLORVAL(x) ((x) & 0xFFFFFF) enum nhcolortype { no_color, nh_color, rgb_color }; diff --git a/include/decl.h b/include/decl.h index 286a77446..6d4bef737 100644 --- a/include/decl.h +++ b/include/decl.h @@ -890,9 +890,8 @@ struct instance_globals_s { /* symbols.c */ struct symsetentry symset[NUM_GRAPHICS]; -#ifdef ENHANCED_SYMBOLS - struct symset_customization sym_customizations[NUM_GRAPHICS + 1]; /* adds UNICODESET */ -#endif + /* adds UNICODESET */ + struct symset_customization sym_customizations[NUM_GRAPHICS + 1][custom_count]; nhsym showsyms[SYM_MAX]; /* symbols to be displayed */ /* files.c */ diff --git a/include/extern.h b/include/extern.h index 73d61975b..113d42a9a 100644 --- a/include/extern.h +++ b/include/extern.h @@ -318,6 +318,11 @@ extern void free_menu_coloring(void); extern int count_menucolors(void); extern int32 check_enhanced_colors(char *) NONNULLARG1; extern const char *wc_color_name(int32) NONNULL; +extern int32_t rgbstr_to_int32(const char *rgbstr); +extern boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx); +extern int color_distance(uint32_t, uint32_t); +extern boolean onlyhexdigits(const char *buf); +extern uint32 get_nhcolor_from_256_index(int idx); /* ### cmd.c ### */ @@ -1079,6 +1084,29 @@ extern void getpos_sethilite(void(*f)(boolean), boolean(*d)(coordxy,coordxy)); extern boolean mapxy_valid(coordxy, coordxy); extern boolean gather_locs_interesting(coordxy, coordxy, int); +/* ### glyphs.c ### */ + +extern int glyphrep_to_custom_map_entries(const char *op, + int *glyph) NONNULLPTRS; +extern int add_custom_urep_entry(const char *symset_name, int glyphidx, + uint32 utf32ch, const uint8 *utf8str, + enum graphics_sets which_set) NONNULLARG1; +extern int add_custom_nhcolor_entry(const char *customization_name, + int glyphidx, uint32 nhcolor, + enum graphics_sets which_set) NONNULLARG1; +int set_map_nhcolor(glyph_map *gm, uint32 nhcolor) NONNULLARG1; +extern int unicode_val(const char *); +extern int glyphrep(const char *) NONNULLARG1; +extern int match_glyph(char *) NONNULLARG1; +extern void dump_all_glyphids(FILE *fp) NONNULLARG1; +extern void fill_glyphid_cache(void); +extern void free_glyphid_cache(void); +extern boolean glyphid_cache_status(void); +extern void apply_customizations(enum graphics_sets which_set); +extern void purge_custom_entries(enum graphics_sets which_set); +extern void purge_all_custom_entries(void); +extern void dump_glyphids(void); + /* ### hack.c ### */ extern boolean is_valid_travelpt(coordxy, coordxy); @@ -1399,9 +1427,6 @@ extern void runtime_info_init(void); extern const char *do_runtime_info(int *) NO_NNARGS; extern void release_runtime_info(void); extern char *mdlib_version_string(char *, const char *) NONNULL NONNULLPTRS; -#ifdef ENHANCED_SYMBOLS -extern void dump_glyphids(void); -#endif /* ### mhitm.c ### */ @@ -3002,12 +3027,7 @@ extern const struct symparse *match_sym(char *) NONNULLARG1; extern void savedsym_free(void); extern void savedsym_strbuf(strbuf_t *) NONNULLARG1; extern boolean parsesymbols(char *, int) NONNULLARG1; -#ifdef ENHANCED_SYMBOLS -extern struct customization_detail *find_matching_symset_customiz( - const char *symset_name, int custtype, - enum graphics_sets which_set) NONNULLARG1; -extern void apply_customizations_to_symset(enum graphics_sets which_set); -#endif +extern void clear_all_glyphmap_colors(void); /* ### sys.c ### */ @@ -3353,21 +3373,10 @@ extern int hide_privileges(boolean); /* ### utf8map.c ### */ #ifdef ENHANCED_SYMBOLS -extern int glyphrep(const char *) NONNULLARG1; extern char *mixed_to_utf8(char *buf, size_t bufsz, const char *str, int *) NONNULLARG1; -extern int match_glyph(char *) NONNULLARG1; -extern void dump_all_glyphids(FILE *fp) NONNULLARG1; -extern void fill_glyphid_cache(void); -extern void free_glyphid_cache(void); -extern boolean glyphid_cache_status(void); -extern int glyphrep_to_custom_map_entries(const char *op, int *glyph) NONNULLPTRS; void free_all_glyphmap_u(void); -int add_custom_urep_entry(const char *symset_name, int glyphidx, - uint32 utf32ch, const uint8 *utf8str, long ucolor, - enum graphics_sets which_set) NONNULLARG1; -int set_map_u(glyph_map *gm, uint32 utf32ch, const uint8 *utf8str, - long ucolor) NONNULLPTRS; +int set_map_u(glyph_map *gm, uint32 utf32ch, const uint8 *utf8str) NONNULLPTRS; #endif /* ENHANCED_SYMBOLS */ /* ### vault.c ### */ diff --git a/include/hack.h b/include/hack.h index 9d8522014..7069141dc 100644 --- a/include/hack.h +++ b/include/hack.h @@ -412,9 +412,7 @@ enum earlyarg { #ifndef NODUMPENUMS , ARG_DUMPENUMS #endif -#ifdef ENHANCED_SYMBOLS , ARG_DUMPGLYPHIDS -#endif #ifdef WIN32 , ARG_WINDOWS #endif diff --git a/include/sym.h b/include/sym.h index 15884d404..9808de0b5 100644 --- a/include/sym.h +++ b/include/sym.h @@ -129,8 +129,8 @@ enum graphics_sets { UNICODESET = NUM_GRAPHICS }; -#ifdef ENHANCED_SYMBOLS -enum customization_types { custom_none, custom_symbols, custom_ureps }; +enum customization_types { custom_none, custom_symbols, + custom_ureps, custom_nhcolor, custom_count }; struct custom_symbol { const struct symparse *symparse; @@ -140,9 +140,14 @@ struct custom_urep { int glyphidx; struct unicode_representation u; }; +struct custom_nhcolor { + int glyphidx; + uint32 nhcolor; +}; union customization_content { struct custom_symbol sym; struct custom_urep urep; + struct custom_nhcolor ccolor; }; struct customization_detail { union customization_content content; @@ -154,11 +159,10 @@ struct customization_detail { struct symset_customization { const char *customization_name; int count; - int custtype; + enum customization_types custtype; struct customization_detail *details; struct customization_detail *details_end; }; -#endif /* ENHANCED_SYMBOLS */ extern const struct symdef defsyms[MAXPCHARS + 1]; /* defaults */ #define WARNCOUNT 6 /* number of different warning levels */ diff --git a/include/winprocs.h b/include/winprocs.h index b5ab5b0c3..13f3f521b 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -260,13 +260,13 @@ extern #define WC2_GUICOLOR 0x2000L /* 14 display colours outside map win */ /* pline() can overload the display attributes argument passed to putstr() with one or more flags and at most one of bold/blink/inverse/&c */ -#define WC2_URGENT_MESG 0x4000L /* 15 putstr(WIN_MESSAGE) supports urgency - * via non-display attribute flag */ -#define WC2_SUPPRESS_HIST 0x8000L /* 16 putstr(WIN_MESSAGE) supports history - * suppression via non-disp attr */ +#define WC2_URGENT_MESG 0x4000L /* 15 putstr(WIN_MESSAGE) supports urgency + * via non-display attribute flag */ +#define WC2_SUPPRESS_HIST 0x8000L /* 16 putstr(WIN_MESSAGE) supports history + * suppression via non-disp attr */ #define WC2_MENU_SHIFT 0x010000L /* 17 horizontal menu scrolling */ #define WC2_U_UTF8STR 0x020000L /* 18 utf8str support */ -#define WC2_U_24BITCOLOR 0x040000L /* 19 24-bit color support available */ +#define WC2_EXTRACOLORS 0x040000L /* 19 color support beyond NH_BASIC_COLOR */ /* 13 free bits */ #define ALIGN_LEFT 1 diff --git a/include/wintty.h b/include/wintty.h index 4bce15133..26add9a5f 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -88,20 +88,21 @@ struct WinDesc { /* descriptor for tty-based displays -- all the per-display data */ struct DisplayDesc { - short rows, cols; /* width and height of tty display */ - short curx, cury; /* current cursor position on the screen */ - int color; /* current color */ - uint32 framecolor; /* current background color */ - int attrs; /* attributes in effect */ - int toplin; /* flag for topl stuff */ - int rawprint; /* number of raw_printed lines since synch */ - int inmore; /* non-zero if more() is active */ - int inread; /* non-zero if reading a character */ - int intr; /* non-zero if inread was interrupted */ - winid lastwin; /* last window used for I/O */ - char dismiss_more; /* extra character accepted at --More-- */ - int topl_utf8; /* non-zero if utf8 in str */ - int mixed; /* we are processing mixed output */ + short rows, cols; /* width and height of tty display */ + short curx, cury; /* current cursor position on the screen */ + uint32 color; /* current color */ + uint32 colorflags; /* NH_BASIC_COLOR or 24-bit color */ + uint32 framecolor; /* current background color */ + int attrs; /* attributes in effect */ + int toplin; /* flag for topl stuff */ + int rawprint; /* number of raw_printed lines since synch */ + int inmore; /* non-zero if more() is active */ + int inread; /* non-zero if reading a character */ + int intr; /* non-zero if inread was interrupted */ + winid lastwin; /* last window used for I/O */ + char dismiss_more; /* extra character accepted at --More-- */ + int topl_utf8; /* non-zero if utf8 in str */ + int mixed; /* we are processing mixed output */ }; #endif /* WINDOW_STRUCTS */ @@ -188,10 +189,9 @@ extern void term_end_raw_bold(void); extern void term_end_color(void); extern void term_start_color(int color); extern void term_start_bgcolor(int color); -#ifdef ENHANCED_SYMBOLS -extern void term_start_24bitcolor(struct unicode_representation *); -extern void term_end_24bitcolor(void); /* termcap.c, consoletty.c */ -#endif +extern void term_start_extracolor(uint32 nhcolor); +extern void term_end_extracolor(void); /* termcap.c, consoletty.c */ +extern void term_start_256color(int idx); /* ### topl.c ### */ diff --git a/include/wintype.h b/include/wintype.h index f00fb08ce..63902da46 100644 --- a/include/wintype.h +++ b/include/wintype.h @@ -76,8 +76,6 @@ struct classic_representation { }; struct unicode_representation { - uint32 ucolor; - uint16 u256coloridx; uint32 utf32ch; uint8 *utf8str; }; @@ -85,6 +83,7 @@ struct unicode_representation { typedef struct glyph_map_entry { unsigned glyphflags; struct classic_representation sym; + uint32 nhcolor; short int tileidx; #ifdef ENHANCED_SYMBOLS struct unicode_representation *u; diff --git a/src/allmain.c b/src/allmain.c index 9f8430dbd..dc3170c02 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -911,9 +911,7 @@ static const struct early_opt earlyopts[] = { #ifndef NODUMPENUMS { ARG_DUMPENUMS, "dumpenums", 9, FALSE }, #endif -#ifdef ENHANCED_SYMBOLS { ARG_DUMPGLYPHIDS, "dumpglyphids", 12, FALSE }, -#endif #ifdef WIN32 { ARG_WINDOWS, "windows", 4, TRUE }, #endif @@ -1012,11 +1010,9 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg) dump_enums(); return 2; #endif -#ifdef ENHANCED_SYMBOLS case ARG_DUMPGLYPHIDS: dump_glyphids(); return 2; -#endif #ifdef CRASHREPORT case ARG_BIDSHOW: crashreport_bidshow(); @@ -1113,7 +1109,7 @@ timet_delta(time_t etim, time_t stim) /* end and start times */ return (long) difftime(etim, stim); } -#if !defined(NODUMPENUMS) || defined(ENHANCED_SYMBOLS) +#if !defined(NODUMPENUMS) /* monsdump[] and objdump[] are also used in utf8map.c */ #define DUMP_ENUMS @@ -1277,13 +1273,11 @@ dump_enums(void) } #endif /* NODUMPENUMS */ -#ifdef ENHANCED_SYMBOLS void dump_glyphids(void) { dump_all_glyphids(stdout); } -#endif /* ENHANCED_SYMBOLS */ -#endif /* !NODUMPENUMS || ENHANCED_SYMBOLS */ +#endif /* !NODUMPENUMS */ /*allmain.c*/ diff --git a/src/coloratt.c b/src/coloratt.c index 7fb0237b5..572746bbd 100644 --- a/src/coloratt.c +++ b/src/coloratt.c @@ -219,6 +219,8 @@ static struct nethack_color colortable[] = { { rgb_color, 154, 138, "white", "#FFFFFF", 255, 255, 255 }, }; +static const char hex[] = "00112233445566778899aAbBcCdDeEfF"; + int32 colortable_to_int32(struct nethack_color *cte) { @@ -782,4 +784,231 @@ wc_color_name(int32 colorindx) return result; } +boolean +onlyhexdigits(const char *buf) +{ + const char *dp = buf; + + for (dp = buf; *dp; ++dp) { + if (!(strchr(hex, *dp) || *dp == '-')) + return FALSE; + } + return TRUE; +} + +int32_t +rgbstr_to_int32(const char *rgbstr) +{ + int r, g, b, milestone = 0; + char *cp, *c_r, *c_g, *c_b; + int32_t rgb = 0; + char buf[BUFSZ]; + boolean dash = FALSE; + + + Snprintf(buf, sizeof buf, "%s", + rgbstr ? rgbstr : ""); + + if (*buf && onlyhexdigits(buf)) { + r = g = b = 0; + c_g = c_b = (char *) 0; + c_r = cp = buf; + while (*cp) { + if (digit(*cp) || *cp == '-') { + if (*cp == '-') { + *cp = '\0'; + milestone++; + dash = TRUE; + } + cp++; + if (dash) { + if (milestone < 2) + c_g = cp; + else + c_b = cp; + dash = FALSE; + } + } else { + return -1L; + } + } + /* sanity checks */ + if (c_r && c_g && c_b + && (strlen(c_r) > 0 && strlen(c_r) < 4) + && (strlen(c_g) > 0 && strlen(c_g) < 4) + && (strlen(c_b) > 0 && strlen(c_b) < 4)) { + r = atoi(c_r); + g = atoi(c_g); + b = atoi(c_b); + rgb = (r << 16) | (g << 8) | (b << 0); + return rgb; + } + } else if (*buf) { + /* perhaps an enhanced color name was used instead of rgb value? */ + if ((rgb = check_enhanced_colors(buf)) != -1) { + return rgb; + } + } + return -1; +} + +int +set_map_nhcolor(glyph_map *gmap, uint32 nhcolor) +{ + glyph_map *tmpgm = gmap; + + if (!tmpgm) + return 0; + + gmap->nhcolor = nhcolor; + return 1; +} + +static struct { + int index; + uint32 value; +} color_256_definitions[] = { + /* color values are from unnethack */ + { 16, 0x000000 }, { 17, 0x00005f }, { 18, 0x000087 }, + { 19, 0x0000af }, { 20, 0x0000d7 }, { 21, 0x0000ff }, + { 22, 0x005f00 }, { 23, 0x005f5f }, { 24, 0x005f87 }, + { 25, 0x005faf }, { 26, 0x005fd7 }, { 27, 0x005fff }, + { 28, 0x008700 }, { 29, 0x00875f }, { 30, 0x008787 }, + { 31, 0x0087af }, { 32, 0x0087d7 }, { 33, 0x0087ff }, + { 34, 0x00af00 }, { 35, 0x00af5f }, { 36, 0x00af87 }, + { 37, 0x00afaf }, { 38, 0x00afd7 }, { 39, 0x00afff }, + { 40, 0x00d700 }, { 41, 0x00d75f }, { 42, 0x00d787 }, + { 43, 0x00d7af }, { 44, 0x00d7d7 }, { 45, 0x00d7ff }, + { 46, 0x00ff00 }, { 47, 0x00ff5f }, { 48, 0x00ff87 }, + { 49, 0x00ffaf }, { 50, 0x00ffd7 }, { 51, 0x00ffff }, + { 52, 0x5f0000 }, { 53, 0x5f005f }, { 54, 0x5f0087 }, + { 55, 0x5f00af }, { 56, 0x5f00d7 }, { 57, 0x5f00ff }, + { 58, 0x5f5f00 }, { 59, 0x5f5f5f }, { 60, 0x5f5f87 }, + { 61, 0x5f5faf }, { 62, 0x5f5fd7 }, { 63, 0x5f5fff }, + { 64, 0x5f8700 }, { 65, 0x5f875f }, { 66, 0x5f8787 }, + { 67, 0x5f87af }, { 68, 0x5f87d7 }, { 69, 0x5f87ff }, + { 70, 0x5faf00 }, { 71, 0x5faf5f }, { 72, 0x5faf87 }, + { 73, 0x5fafaf }, { 74, 0x5fafd7 }, { 75, 0x5fafff }, + { 76, 0x5fd700 }, { 77, 0x5fd75f }, { 78, 0x5fd787 }, + { 79, 0x5fd7af }, { 80, 0x5fd7d7 }, { 81, 0x5fd7ff }, + { 82, 0x5fff00 }, { 83, 0x5fff5f }, { 84, 0x5fff87 }, + { 85, 0x5fffaf }, { 86, 0x5fffd7 }, { 87, 0x5fffff }, + { 88, 0x870000 }, { 89, 0x87005f }, { 90, 0x870087 }, + { 91, 0x8700af }, { 92, 0x8700d7 }, { 93, 0x8700ff }, + { 94, 0x875f00 }, { 95, 0x875f5f }, { 96, 0x875f87 }, + { 97, 0x875faf }, { 98, 0x875fd7 }, { 99, 0x875fff }, + { 100, 0x878700 }, { 101, 0x87875f }, { 102, 0x878787 }, + { 103, 0x8787af }, { 104, 0x8787d7 }, { 105, 0x8787ff }, + { 106, 0x87af00 }, { 107, 0x87af5f }, { 108, 0x87af87 }, + { 109, 0x87afaf }, { 110, 0x87afd7 }, { 111, 0x87afff }, + { 112, 0x87d700 }, { 113, 0x87d75f }, { 114, 0x87d787 }, + { 115, 0x87d7af }, { 116, 0x87d7d7 }, { 117, 0x87d7ff }, + { 118, 0x87ff00 }, { 119, 0x87ff5f }, { 120, 0x87ff87 }, + { 121, 0x87ffaf }, { 122, 0x87ffd7 }, { 123, 0x87ffff }, + { 124, 0xaf0000 }, { 125, 0xaf005f }, { 126, 0xaf0087 }, + { 127, 0xaf00af }, { 128, 0xaf00d7 }, { 129, 0xaf00ff }, + { 130, 0xaf5f00 }, { 131, 0xaf5f5f }, { 132, 0xaf5f87 }, + { 133, 0xaf5faf }, { 134, 0xaf5fd7 }, { 135, 0xaf5fff }, + { 136, 0xaf8700 }, { 137, 0xaf875f }, { 138, 0xaf8787 }, + { 139, 0xaf87af }, { 140, 0xaf87d7 }, { 141, 0xaf87ff }, + { 142, 0xafaf00 }, { 143, 0xafaf5f }, { 144, 0xafaf87 }, + { 145, 0xafafaf }, { 146, 0xafafd7 }, { 147, 0xafafff }, + { 148, 0xafd700 }, { 149, 0xafd75f }, { 150, 0xafd787 }, + { 151, 0xafd7af }, { 152, 0xafd7d7 }, { 153, 0xafd7ff }, + { 154, 0xafff00 }, { 155, 0xafff5f }, { 156, 0xafff87 }, + { 157, 0xafffaf }, { 158, 0xafffd7 }, { 159, 0xafffff }, + { 160, 0xd70000 }, { 161, 0xd7005f }, { 162, 0xd70087 }, + { 163, 0xd700af }, { 164, 0xd700d7 }, { 165, 0xd700ff }, + { 166, 0xd75f00 }, { 167, 0xd75f5f }, { 168, 0xd75f87 }, + { 169, 0xd75faf }, { 170, 0xd75fd7 }, { 171, 0xd75fff }, + { 172, 0xd78700 }, { 173, 0xd7875f }, { 174, 0xd78787 }, + { 175, 0xd787af }, { 176, 0xd787d7 }, { 177, 0xd787ff }, + { 178, 0xd7af00 }, { 179, 0xd7af5f }, { 180, 0xd7af87 }, + { 181, 0xd7afaf }, { 182, 0xd7afd7 }, { 183, 0xd7afff }, + { 184, 0xd7d700 }, { 185, 0xd7d75f }, { 186, 0xd7d787 }, + { 187, 0xd7d7af }, { 188, 0xd7d7d7 }, { 189, 0xd7d7ff }, + { 190, 0xd7ff00 }, { 191, 0xd7ff5f }, { 192, 0xd7ff87 }, + { 193, 0xd7ffaf }, { 194, 0xd7ffd7 }, { 195, 0xd7ffff }, + { 196, 0xff0000 }, { 197, 0xff005f }, { 198, 0xff0087 }, + { 199, 0xff00af }, { 200, 0xff00d7 }, { 201, 0xff00ff }, + { 202, 0xff5f00 }, { 203, 0xff5f5f }, { 204, 0xff5f87 }, + { 205, 0xff5faf }, { 206, 0xff5fd7 }, { 207, 0xff5fff }, + { 208, 0xff8700 }, { 209, 0xff875f }, { 210, 0xff8787 }, + { 211, 0xff87af }, { 212, 0xff87d7 }, { 213, 0xff87ff }, + { 214, 0xffaf00 }, { 215, 0xffaf5f }, { 216, 0xffaf87 }, + { 217, 0xffafaf }, { 218, 0xffafd7 }, { 219, 0xffafff }, + { 220, 0xffd700 }, { 221, 0xffd75f }, { 222, 0xffd787 }, + { 223, 0xffd7af }, { 224, 0xffd7d7 }, { 225, 0xffd7ff }, + { 226, 0xffff00 }, { 227, 0xffff5f }, { 228, 0xffff87 }, + { 229, 0xffffaf }, { 230, 0xffffd7 }, { 231, 0xffffff }, + { 232, 0x080808 }, { 233, 0x121212 }, { 234, 0x1c1c1c }, + { 235, 0x262626 }, { 236, 0x303030 }, { 237, 0x3a3a3a }, + { 238, 0x444444 }, { 239, 0x4e4e4e }, { 240, 0x585858 }, + { 241, 0x626262 }, { 242, 0x6c6c6c }, { 243, 0x767676 }, + { 244, 0x808080 }, { 245, 0x8a8a8a }, { 246, 0x949494 }, + { 247, 0x9e9e9e }, { 248, 0xa8a8a8 }, { 249, 0xb2b2b2 }, + { 250, 0xbcbcbc }, { 251, 0xc6c6c6 }, { 252, 0xd0d0d0 }, + { 253, 0xdadada }, { 254, 0xe4e4e4 }, { 255, 0xeeeeee }, +}; + +/** Calculate the color distance between two colors. + * + * Algorithm taken from UnNetHack which took it from + * https://www.compuphase.com/cmetric.htm + **/ + +int +color_distance(uint32_t rgb1, uint32_t rgb2) +{ + int r1 = (rgb1 >> 16) & 0xFF; + int g1 = (rgb1 >> 8) & 0xFF; + int b1 = (rgb1) & 0xFF; + int r2 = (rgb2 >> 16) & 0xFF; + int g2 = (rgb2 >> 8) & 0xFF; + int b2 = (rgb2) & 0xFF; + + int rmean = (r1 + r2) / 2; + int r = r1 - r2; + int g = g1 - g2; + int b = b1 - b2; + return ((((512 + rmean) * r * r) >> 8) + 4 * g * g + + (((767 - rmean) * b * b) >> 8)); +} + +boolean +closest_color(uint32 lcolor, uint32 *closecolor, int *clridx) +{ + int i, color_index = -1, similar = INT_MAX, current; + boolean retbool = FALSE; + + for (i = 0; i < SIZE(color_256_definitions); i++) { + /* look for an exact match */ + if (lcolor == color_256_definitions[i].value) { + color_index = i; + break; + } + /* find a close color match */ + current = color_distance(lcolor, color_256_definitions[i].value); + if (current < similar) { + color_index = i; + similar = current; + } + } + if (closecolor && clridx && color_index >= 0) { + *closecolor = color_256_definitions[color_index].value; + *clridx = color_256_definitions[color_index].index; + retbool = TRUE; + } + return retbool; +} + +uint32 +get_nhcolor_from_256_index(int idx) +{ + uint32 retcolor = NO_COLOR | NH_BASIC_COLOR; + + if (IndexOk(idx, color_256_definitions)) + retcolor = color_256_definitions[idx].value; + return retcolor; +} /*coloratt.c*/ diff --git a/src/decl.c b/src/decl.c index db1a776e8..da1fdf3be 100644 --- a/src/decl.c +++ b/src/decl.c @@ -756,9 +756,7 @@ static const struct instance_globals_s g_init_s = { { 0, 0 }, /* save_dlevel */ /* symbols.c */ { DUMMY }, /* symset */ -#ifdef ENHANCED_SYMBOLS - { { 0 } }, /* symset_customizations */ -#endif + { { 0 }, { 0 } }, /* symset_customizations */ DUMMY, /* showsyms */ /* files.c */ 0, /* symset_count */ diff --git a/src/display.c b/src/display.c index ac0428642..5d9ce00e1 100644 --- a/src/display.c +++ b/src/display.c @@ -1565,15 +1565,19 @@ see_traps(void) } } -/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx }, - tileidx, u } */ +/* glyph, ttychar, framecolor, + { glyphflags, { NO_COLOR, sym.symidx }, nhcolor, tileidx, u } */ static glyph_info no_ginfo = { - NO_GLYPH, ' ', NO_COLOR, { MG_BADXY, { NO_COLOR, 0 }, 0 + NO_GLYPH, ' ', NO_COLOR, + { MG_BADXY, { NO_COLOR, 0 }, + 0, + 0 #ifdef ENHANCED_SYMBOLS - , 0 + , 0 #endif } }; + #ifndef UNBUFFERED_GLYPHINFO /* Note that the 'glyph' argument is not used in the expansion * of this !UNBUFFERED_GLYPHINFO (default) variation, but is @@ -1590,16 +1594,17 @@ staticfn glyph_info *glyphinfo_at(coordxy, coordxy, int); #ifdef TILES_IN_GLYPHMAP extern const glyph_info nul_glyphinfo; /* tile.c */ #else -/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx }, +/* glyph, ttychar, framecolor, { glyphflags, { sym.symidx }, nhcolor, tileidx, 0} */ const glyph_info nul_glyphinfo = { NO_GLYPH, ' ', NO_COLOR, { /* glyph_map */ MG_UNEXPL, { NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X }, - 0 + 0, + 0 #ifdef ENHANCED_SYMBOLS - , 0 + , 0 #endif } }; @@ -1609,9 +1614,11 @@ const glyph_info nul_glyphinfo = { extern glyph_map glyphmap[MAX_GLYPH]; /* from tile.c */ #else glyph_map glyphmap[MAX_GLYPH] = { - { 0U, { 0, 0}, 0 + { 0U, { NO_COLOR, 0 }, + 0, + 0 #ifdef ENHANCED_SYMBOLS - , 0 + , 0 #endif } }; @@ -1819,6 +1826,8 @@ show_glyph(coordxy x, coordxy y, int glyph) boolean show_glyph_change = FALSE; int oldglyph; + //if (glyph == 3972 || glyph == 3988) + // __debugbreak(); /* * Check for bad positions and glyphs. */ @@ -1965,6 +1974,7 @@ show_glyph(coordxy x, coordxy y, int glyph) but that triggers full redraw so doesn't matter here); still, be thorough and check everything */ || gg.gbuf[y][x].glyphinfo.ttychar != glyphinfo.ttychar + || gg.gbuf[y][x].glyphinfo.gm.nhcolor != glyphinfo.gm.nhcolor || gg.gbuf[y][x].glyphinfo.gm.glyphflags != glyphinfo.gm.glyphflags || gg.gbuf[y][x].glyphinfo.gm.sym.color != glyphinfo.gm.sym.color || gg.gbuf[y][x].glyphinfo.gm.tileidx != glyphinfo.gm.tileidx @@ -2014,11 +2024,14 @@ show_glyph(coordxy x, coordxy y, int glyph) static gbuf_entry nul_gbuf = { 0, /* gnew */ - { GLYPH_UNEXPLORED, (unsigned) ' ', NO_COLOR, /* glyphinfo.glyph */ + { GLYPH_UNEXPLORED, (unsigned) ' ', NO_COLOR, + /* glyphinfo.glyph, glyphinfo.ttychar */ /* glyphinfo.gm */ - { MG_UNEXPL, { (unsigned) NO_COLOR, 0 }, 0 + { MG_UNEXPL, { NO_COLOR, 0 }, + 0, + 0 #ifdef ENHANCED_SYMBOLS - , 0 + , 0 #endif } } @@ -2045,10 +2058,12 @@ clear_glyph_buffer(void) || giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color || giptr->gm.glyphflags != nul_gbuf.glyphinfo.gm.glyphflags + || giptr->gm.nhcolor != nul_gbuf.glyphinfo.gm.nhcolor || giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx) #else nul_gbuf.gnew = (giptr->ttychar != ' ' || giptr->gm.sym.color != NO_COLOR + || giptr->gm.nhcolor != 0 || (giptr->gm.glyphflags & ~MG_UNEXPL) != 0) #endif ? 1 : 0; @@ -2084,10 +2099,12 @@ row_refresh(coordxy start, coordxy stop, coordxy y) force = (giptr->ttychar != nul_gbuf.glyphinfo.ttychar || giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color || giptr->gm.glyphflags != nul_gbuf.glyphinfo.gm.glyphflags + || giptr->gm.nhcolor != nul_gbuf.glyphinfo.gm.nhcolor || giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx) #else force = (giptr->ttychar != ' ' || giptr->gm.sym.color != NO_COLOR + || giptr->gm.gm.nhcolor != 0 || (giptr->gm.glyphflags & ~MG_UNEXPL) != 0) #endif ? 1 : 0; @@ -2097,7 +2114,7 @@ row_refresh(coordxy start, coordxy stop, coordxy y) get_bkglyph_and_framecolor(x, y, &bkglyphinfo.glyph, &bkglyphinfo.framecolor); if (force || glyph != GLYPH_UNEXPLORED - || bkglyphinfo.framecolor != NO_COLOR) { + || bkglyphinfo.gm.nhcolor != NO_COLOR) { print_glyph(WIN_MAP, x, y, Glyphinfo_at(x, y, glyph), &bkglyphinfo); } @@ -2161,7 +2178,8 @@ flush_screen(int cursor_on_u) gbuf_entry *gptr = &gg.gbuf[y][x = gg.gbuf_start[y]]; for (; x <= gg.gbuf_stop[y]; gptr++, x++) { - get_bkglyph_and_framecolor(x, y, &bkglyph, &bkglyphinfo.framecolor); + get_bkglyph_and_framecolor(x, y, &bkglyph, + &bkglyphinfo.framecolor); if (gptr->gnew || (gw.wsettings.map_frame_color != NO_COLOR && bkglyphinfo.framecolor != NO_COLOR)) { diff --git a/src/glyphs.c b/src/glyphs.c new file mode 100644 index 000000000..5407eaba2 --- /dev/null +++ b/src/glyphs.c @@ -0,0 +1,1184 @@ +/* NetHack 3.7 glyphs.c */ +/* Copyright (c) Michael Allison, 2021. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" + +extern const struct symparse loadsyms[]; +extern struct enum_dump monsdump[]; +extern struct enum_dump objdump[]; +extern glyph_map glyphmap[MAX_GLYPH]; +extern const char *const known_handling[]; /* symbols.c */ +extern glyph_map glyphmap[MAX_GLYPH]; +staticfn void shuffle_customizations(void); + +#define Fprintf (void) fprintf + +enum reserved_activities { res_nothing, res_dump_glyphids, res_fill_cache }; +enum things_to_find { find_nothing, find_pm, find_oc, find_cmap, find_glyph }; +struct find_struct { + enum things_to_find findtype; + int val; + int loadsyms_offset; + int loadsyms_count; + int *extraval; + uint32 color; + const char *unicode_val; /* U+NNNN format */ + void (*callback)(int glyph, struct find_struct *); + enum reserved_activities restype; + genericptr_t reserved; +}; +static const struct find_struct zero_find = { 0 }; +struct glyphid_cache_t { + int glyphnum; + char *id; +}; +static struct glyphid_cache_t *glyphid_cache; +static unsigned glyphid_cache_lsize; +static size_t glyphid_cache_size; +static struct find_struct glyphcache_find, to_custom_symbol_find; +static const long nonzero_black = CLR_BLACK | NH_BASIC_COLOR; + +staticfn struct customization_detail *find_matching_customization( + const char *customization_name, enum customization_types custtype, + enum graphics_sets which_set); +#if 0 +staticfn struct customization_detail *find_display_sym_customization( + const char *customization_name, const struct symparse *symparse, + enum graphics_sets which_set); +staticfn struct customization_detail *find_display_urep_customization( + const char *customization_name, int glyphidx, + enum graphics_sets which_set); +#endif +staticfn void init_glyph_cache(void); +staticfn void add_glyph_to_cache(int glyphnum, const char *id); +staticfn int find_glyph_in_cache(const char *id); +staticfn uint32 glyph_hash(const char *id); +staticfn void to_custom_symset_entry_callback(int glyph, + struct find_struct *findwhat); +staticfn int parse_id(const char *id, struct find_struct *findwhat); +staticfn int glyph_find_core(const char *id, struct find_struct *findwhat); +staticfn char *fix_glyphname(char *str); +/* staticfn void purge_custom_entries(enum graphics_sets which_set); */ + + +staticfn void +to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat) +{ +#if 0 + glyph_map *gmap = &glyphmap[glyph]; +#endif +#ifdef ENHANCED_SYMBOLS + uint8 utf8str[6] = { 0, 0, 0, 0, 0, 0 }; + int uval = 0; +#endif + + if (findwhat->extraval) + *findwhat->extraval = glyph; +#ifdef ENHANCED_SYMBOLS + if (findwhat->unicode_val) + uval = unicode_val(findwhat->unicode_val); + if (uval && unicodeval_to_utf8str(uval, utf8str, sizeof utf8str)) { + add_custom_urep_entry(gs.symset->name, glyph, uval, utf8str, + gs.symset_which_set); + } +#endif + if (findwhat->color) { + add_custom_nhcolor_entry(gs.symset->name, glyph, findwhat->color, + gs.symset_which_set); + } +} + +/* + * Return value: + * 1 = success + * 0 = failure + */ +int +glyphrep_to_custom_map_entries(const char *op, int *glyphptr) +{ + to_custom_symbol_find = zero_find; + char buf[BUFSZ], *c_glyphid, *c_unicode, *c_colorval, *cp; + int milestone, reslt = 0; + long rgb = 0L; + boolean slash = FALSE, colon = FALSE; + + if (!glyphid_cache) + reslt = 1; /* for debugger use only; no cache available */ + + milestone = 0; + Snprintf(buf, sizeof buf, "%s", op); + c_unicode = c_colorval = (char *) 0; + c_glyphid = cp = buf; + while (*cp) { + if ((*cp == '/') || (*cp == ':')) { + if (*cp == '/') + slash = TRUE; + if (*cp == ':') + colon = TRUE; + *cp = '\0'; + milestone++; + } + cp++; + if (colon && milestone < 2 && *cp == 'U') { + c_unicode = cp; + colon = FALSE; + } + if (slash && milestone >= 2) { + c_colorval = cp; + slash = FALSE; + } + } + /* some sanity checks */ + if (c_glyphid && *c_glyphid == ' ') + c_glyphid++; + if (c_unicode && *c_unicode == ' ') + c_unicode++; + if (c_colorval && *c_colorval == ' ') + c_colorval++; + if ((c_colorval && (rgb = rgbstr_to_int32(c_colorval)) != -1L) + || !c_colorval) { + /* if the color 0 is an actual color, as opposed to just "not set" + we set a marker bit outside the 24-bit range to indicate a + valid color value 0. That allows valid color 0, but allows a + simple checking for 0 to detect "not set". The window port that + implements the color switch, needs to either check that bit + or appropriately mask colors with 0xFFFFFF. */ + to_custom_symbol_find.color = (rgb == -1 || !c_colorval) ? 0L + : (rgb == 0L) ? nonzero_black + : rgb; + } + if (c_unicode + && (*c_unicode == 'U' || *c_unicode == 'u') + && (c_unicode[1] == '+')) + to_custom_symbol_find.unicode_val = c_unicode; + to_custom_symbol_find.extraval = glyphptr; + to_custom_symbol_find.callback = to_custom_symset_entry_callback; + reslt = glyph_find_core(c_glyphid, &to_custom_symbol_find); + return reslt; +} + +staticfn char * +fix_glyphname(char *str) +{ + char *c; + + for (c = str; *c; c++) { + if (*c >= 'A' && *c <= 'Z') + *c += (char) ('a' - 'A'); + else if (*c >= '0' && *c <= '9') + ; + else if (*c < 'a' || *c > 'z') + *c = '_'; + } + return str; +} + +staticfn int +glyph_find_core(const char *id, struct find_struct *findwhat) +{ + int glyph; + boolean do_callback, end_find = FALSE; + + if (parse_id(id, findwhat)) { + if (findwhat->findtype == find_glyph) { + (*findwhat->callback)(findwhat->val, findwhat); + } else { + for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { + do_callback = FALSE; + switch (findwhat->findtype) { + case find_cmap: + if (glyph_to_cmap(glyph) == findwhat->val) + do_callback = TRUE; + break; + case find_pm: + if (glyph_is_monster(glyph) + && monsym(&mons[glyph_to_mon(glyph)]) == findwhat->val) + do_callback = TRUE; + break; + case find_oc: + if (glyph_is_object(glyph) + && glyph_to_obj(glyph) == findwhat->val) + do_callback = TRUE; + break; + case find_glyph: + if (glyph == findwhat->val) { + do_callback = TRUE; + end_find = TRUE; + } + break; + case find_nothing: + default: + end_find = TRUE; + break; + } + if (do_callback) + (findwhat->callback)(glyph, findwhat); + if (end_find) + break; + } + } + return 1; + } + return 0; +} + +/* + When we start to process a config file or a symbol file, + that might have G_ entries, generating all 9000+ glyphid + for comparison repeatedly each time we encounter a G_ + entry to decipher, then comparing against them, is obviously + extremely performance-poor. + + Setting aside the "comparison" part for now (that has to be + done in some manner), we can likely do something about the + repeated "generation" of the names for parsing prior to the + actual comparison part by generating them once, ahead of the + bulk of the potential parsings. We can later free up + all the memory those names consumed once the bulk parsing is + over with. +*/ + + +void fill_glyphid_cache(void) +{ + int reslt = 0; + + if (!glyphid_cache) { + init_glyph_cache(); + } + if (glyphid_cache) { + glyphcache_find = zero_find; + glyphcache_find.findtype = find_nothing; + glyphcache_find.reserved = (genericptr_t) glyphid_cache; + glyphcache_find.restype = res_fill_cache; + reslt = parse_id((char *) 0, &glyphcache_find); + if (!reslt) { + free_glyphid_cache(); + glyphid_cache = (struct glyphid_cache_t *) 0; + } + } +} + +/* + * The glyph ID cache is a simple double-hash table. + * The cache size is a power of two, and two hashes are derived from the + * cache ID. The first is a location in the table, and the second is an + * offset. On any collision, the second hash is added to the first until + * a match or an empty bucket is found. + * The second hash is an odd number, which is necessary and sufficient + * to traverse the entire table. + */ + +staticfn void +init_glyph_cache(void) +{ + size_t glyph; + + /* Cache size of power of 2 not less than 2*MAX_GLYPH */ + glyphid_cache_lsize = 0; + glyphid_cache_size = 1; + while (glyphid_cache_size < 2*MAX_GLYPH) { + ++glyphid_cache_lsize; + glyphid_cache_size <<= 1; + } + + glyphid_cache = (struct glyphid_cache_t *) alloc( + glyphid_cache_size * sizeof (struct glyphid_cache_t)); + for (glyph = 0; glyph < glyphid_cache_size; ++glyph) { + glyphid_cache[glyph].glyphnum = 0; + glyphid_cache[glyph].id = (char *) 0; + } +} + +void free_glyphid_cache(void) +{ + size_t idx; + + if (!glyphid_cache) + return; + for (idx = 0; idx < glyphid_cache_size; ++idx) { + if (glyphid_cache[idx].id) { + free(glyphid_cache[idx].id); + glyphid_cache[idx].id = (char *) 0; + } + } + free(glyphid_cache); + glyphid_cache = (struct glyphid_cache_t *) 0; +} + +staticfn void +add_glyph_to_cache(int glyphnum, const char *id) +{ + uint32 hash = glyph_hash(id); + size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); + size_t hash2 = (size_t) + (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); + size_t i = hash1; + + do { + if (glyphid_cache[i].id == NULL) { + /* Empty bucket found */ + glyphid_cache[i].id = dupstr(id); + glyphid_cache[i].glyphnum = glyphnum; + return; + } + /* For speed, assume that no ID occurs twice */ + i = (i + hash2) & (glyphid_cache_size - 1); + } while (i != hash1); + /* This should never happen */ + panic("glyphid_cache full"); +} + +staticfn int +find_glyph_in_cache(const char *id) +{ + uint32 hash = glyph_hash(id); + size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); + size_t hash2 = (size_t) + (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); + size_t i = hash1; + + do { + if (glyphid_cache[i].id == NULL) { + /* Empty bucket found */ + return -1; + } + if (strcmpi(id, glyphid_cache[i].id) == 0) { + /* Match found */ + return glyphid_cache[i].glyphnum; + } + i = (i + hash2) & (glyphid_cache_size - 1); + } while (i != hash1); + return -1; +} + +staticfn uint32 +glyph_hash(const char *id) +{ + uint32 hash = 0; + size_t i; + + for (i = 0; id[i] != '\0'; ++i) { + char ch = id[i]; + if ('A' <= ch && ch <= 'Z') { + ch += 'a' - 'A'; + } + hash = (hash << 1) | (hash >> 31); + hash ^= ch; + } + return hash; +} + +boolean +glyphid_cache_status(void) +{ + return (glyphid_cache != 0); +} + +void +dump_all_glyphids(FILE *fp) +{ + struct find_struct dump_glyphid_find = zero_find; + + dump_glyphid_find.findtype = find_nothing; + dump_glyphid_find.reserved = (genericptr_t) fp; + dump_glyphid_find.restype = res_dump_glyphids; + (void) parse_id((char *) 0, &dump_glyphid_find); +} + +int +match_glyph(char *buf) +{ + char workbuf[BUFSZ]; + + /* buf contains a G_ glyph reference, not an S_ symbol. + There could be an R-G-B color attached too. + Let's get a copy to work with. */ + Snprintf(workbuf, sizeof workbuf, "%s", buf); /* get a copy */ + return glyphrep(workbuf); +} + +int +glyphrep(const char *op) +{ + int reslt = 0, glyph = NO_GLYPH; + + if (!glyphid_cache) + reslt = 1; /* for debugger use only; no cache available */ + reslt = glyphrep_to_custom_map_entries(op, &glyph); + if (reslt) + return 1; + return 0; +} + +#ifdef ENHANCED_SYMBOLS +int +add_custom_urep_entry( + const char *customization_name, + int glyphidx, + uint32 utf32ch, + const uint8 *utf8str, + enum graphics_sets which_set) +{ + struct symset_customization *gdc = &gs.sym_customizations[which_set][custom_ureps]; + struct customization_detail *details, *newdetails = 0; + + + if (!gdc->details) { + gdc->customization_name = dupstr(customization_name); + gdc->custtype = custom_ureps; + gdc->details = 0; + gdc->details_end = 0; + } + details = find_matching_customization(customization_name, + custom_ureps, which_set); /* FIXME */ + if (details) { + while (details) { + if (details->content.urep.glyphidx == glyphidx) { + if (details->content.urep.u.utf8str) + free(details->content.urep.u.utf8str); + if (utf32ch) { + details->content.urep.u.utf8str = + (uint8 *) dupstr((const char *) utf8str); + details->content.urep.u.utf32ch = utf32ch; + } else { + details->content.urep.u.utf8str = (uint8 *) 0; + details->content.urep.u.utf32ch = 0; + } + return 1; + } + details = details->next; + } + } + /* create new details entry */ + newdetails = (struct customization_detail *) alloc( + sizeof (struct customization_detail)); + newdetails->content.urep.glyphidx = glyphidx; + if (utf8str && *utf8str) { + newdetails->content.urep.u.utf8str = + (uint8 *) dupstr((const char *) utf8str); + } else { + newdetails->content.urep.u.utf8str = + (uint8 *) 0; + } + newdetails->content.urep.u.utf32ch = utf32ch; + newdetails->next = (struct customization_detail *) 0; + if (gdc->details == NULL) { + gdc->details = newdetails; + } else { + gdc->details_end->next = newdetails; + } + gdc->details_end = newdetails; + gdc->count++; + return 1; +} +#endif + +int +add_custom_nhcolor_entry( + const char *customization_name, + int glyphidx, + uint32 nhcolor, + enum graphics_sets which_set) +{ + struct symset_customization *gdc + = &gs.sym_customizations[which_set][custom_nhcolor]; + struct customization_detail *details, *newdetails = 0; +#if 0 + static uint32 closecolor = 0; + static int clridx = 0; +#endif + + if (!gdc->details) { + gdc->customization_name = dupstr(customization_name); + gdc->custtype = custom_nhcolor; + gdc->details = 0; + gdc->details_end = 0; + } + details = find_matching_customization(customization_name, + custom_nhcolor, which_set); + if (details) { + while (details) { + if (details->content.ccolor.glyphidx == glyphidx) { + details->content.ccolor.nhcolor = nhcolor; + return 1; + } + details = details->next; + } + } + /* create new details entry */ + newdetails = (struct customization_detail *) alloc( + sizeof (struct customization_detail)); + newdetails->content.urep.glyphidx = glyphidx; + newdetails->content.ccolor.nhcolor = nhcolor; +#if 0 + if ((nhcolor & NH_BASIC_COLOR) != 0) { + newdetails->content.ccolor.nhcolor = nhcolor; + } else { + newdetails->content.ccolor.nhcolor = nhcolor; + } +#endif + newdetails->next = (struct customization_detail *) 0; + if (gdc->details == NULL) { + gdc->details = newdetails; + } else { + gdc->details_end->next = newdetails; + } + gdc->details_end = newdetails; + gdc->count++; + return 1; +} + +void +apply_customizations(enum graphics_sets which_set) +{ + glyph_map *gmap; + struct customization_detail *details; + struct symset_customization *sc; + boolean at_least_one = FALSE; + int custs; + + for (custs = 0; custs < (int) custom_count; ++custs) { + sc = &gs.sym_customizations[which_set][custs]; + if (sc->count && sc->details) { + at_least_one = TRUE; + /* These glyph customizations get applied to the glyphmap array, + not to symset entries */ + details = sc->details; + while (details) { +#ifdef ENHANCED_SYMBOLS + if (sc->custtype == custom_ureps) { + gmap = &glyphmap[details->content.urep.glyphidx]; + if (gs.symset[which_set].handling == H_UTF8) + (void) set_map_u(gmap, + details->content.urep.u.utf32ch, + details->content.urep.u.utf8str); + } +#endif + if (sc->custtype == custom_nhcolor) { + gmap = &glyphmap[details->content.ccolor.glyphidx]; + (void) set_map_nhcolor(gmap, + details->content.ccolor.nhcolor); + } + details = details->next; + } + } + } + if (at_least_one) { + shuffle_customizations(); + } +} + +/* Shuffle the customizations to match shuffled object descriptions, + * so a red potion isn't displayed with a blue customization, and so on. + */ +staticfn void +shuffle_customizations(void) +{ + static const int offsets[2] = { GLYPH_OBJ_OFF, GLYPH_OBJ_PILETOP_OFF }; + int j; + + for (j = 0; j < SIZE(offsets); j++) { + glyph_map *obj_glyphs = glyphmap + offsets[j]; + int i; +#ifdef ENHANCED_SYMBOLS + struct unicode_representation *tmp_u[NUM_OBJECTS]; +#endif + uint32 tmp_nhcolor[NUM_OBJECTS]; + int duplicate[NUM_OBJECTS]; + + for (i = 0; i < NUM_OBJECTS; i++) { + duplicate[i] = -1; +#ifdef ENHANCED_SYMBOLS + tmp_u[i] = (struct unicode_representation *) 0; +#endif + tmp_nhcolor[i] = 0; + } + for (i = 0; i < NUM_OBJECTS; i++) { + int idx = objects[i].oc_descr_idx; + + /* + * Shuffling gem appearances can cause the same oc_descr_idx to + * appear more than once. Detect this condition and ensure that + * each pointer points to a unique allocation. + */ + if (duplicate[idx] >= 0) { +#ifdef ENHANCED_SYMBOLS + /* Current structure already appears in tmp_u */ + struct unicode_representation *other = tmp_u[duplicate[idx]]; +#endif + uint32 other_nhcolor = tmp_nhcolor[duplicate[idx]]; + +#ifdef ENHANCED_SYMBOLS + tmp_u[i] = (struct unicode_representation *) + alloc(sizeof *tmp_u[i]); + *tmp_u[i] = *other; + if (other->utf8str != NULL) { + tmp_u[i]->utf8str = (uint8 *) + dupstr((const char *) other->utf8str); + } +#endif + tmp_nhcolor[i] = other_nhcolor; + } else { +#ifdef ENHANCED_SYMBOLS + tmp_u[i] = obj_glyphs[idx].u; + if (obj_glyphs[idx].u != NULL) { + duplicate[idx] = i; + obj_glyphs[idx].u = NULL; + } + #endif + tmp_nhcolor[i] = obj_glyphs[idx].nhcolor; + } + } + for (i = 0; i < NUM_OBJECTS; i++) { + /* Some glyphmaps may not have been transferred */ +#ifdef ENHANCED_SYMBOLS + if (obj_glyphs[i].u != NULL) { + free(obj_glyphs[i].u->utf8str); + free(obj_glyphs[i].u); + } +#endif + obj_glyphs[i].nhcolor = tmp_nhcolor[i]; + } + } +} + +staticfn struct customization_detail * +find_matching_customization( + const char *customization_name, + enum customization_types custtype, + enum graphics_sets which_set) +{ + struct symset_customization *gdc = &gs.sym_customizations[which_set][custtype]; + + if ((gdc->custtype == custtype) && gdc->customization_name + && (strcmp(customization_name, gdc->customization_name) == 0)) + return gdc->details; + return (struct customization_detail *) 0; +} + +void +purge_all_custom_entries(void) +{ + int i; + + for (i = 0; i < NUM_GRAPHICS + 1; ++i) { + purge_custom_entries(i); + } +} + +void +purge_custom_entries(enum graphics_sets which_set) +{ + enum customization_types custtype; + struct symset_customization *gdc; + struct customization_detail *details, *next; + + for (custtype = custom_none; custtype < custom_count; ++custtype) { + gdc = &gs.sym_customizations[which_set][custtype]; + details = gdc->details; + while (details) { + next = details->next; + if (gdc->custtype == custom_ureps) { + if (details->content.urep.u.utf8str) + free(details->content.urep.u.utf8str); + details->content.urep.u.utf8str = (uint8 *) 0; + } else if (gdc->custtype == custom_symbols) { + details->content.sym.symparse = (struct symparse *) 0; + details->content.sym.val = 0; + } else if (gdc->custtype == custom_nhcolor) { + details->content.ccolor.nhcolor = 0; + details->content.ccolor.glyphidx = 0; + } + free(details); + details = next; + } + gdc->details = 0; + gdc->details_end = 0; + if (gdc->customization_name) { + free((genericptr_t) gdc->customization_name); + gdc->customization_name = 0; + } + gdc->count = 0; + } +} + +#if 0 +struct customization_detail * +find_display_sym_customization( + const char *customization_name, + const struct symparse *symparse, + enum graphics_sets which_set) +{ + struct symset_customization *gdc; + struct customization_detail *symdetails; + + gdc = &gs.sym_customizations[which_set][custom_symbols]; + if ((gdc->custtype == custom_symbols) + && (strcmp(customization_name, gdc->customization_name) == 0)) { + symdetails = gdc->details; + while (symdetails) { + if (symdetails->content.sym.symparse == symparse) + return symdetails; + symdetails = symdetails->next; + } + } + return (struct customization_detail *) 0; +} +#endif + +staticfn int +parse_id(const char *id, struct find_struct *findwhat) +{ + FILE *fp = (FILE *) 0; + int i = 0, j, mnum, glyph, + pm_offset = 0, oc_offset = 0, cmap_offset = 0, + pm_count = 0, oc_count = 0, cmap_count = 0; + boolean skip_base = FALSE, skip_this_one, dump_ids = FALSE, + filling_cache = FALSE, is_S = FALSE, is_G = FALSE; + char buf[4][QBUFSZ]; + + if (findwhat->findtype == find_nothing && findwhat->restype) { + if (findwhat->restype == res_dump_glyphids) { + if (findwhat->reserved) { + fp = (FILE *) findwhat->reserved; + dump_ids = TRUE; + } else { + return 0; + } + } + if (findwhat->restype == res_fill_cache) { + if (findwhat->reserved + && findwhat->reserved == (genericptr_t) glyphid_cache) { + filling_cache = TRUE; + } else { + return 0; + } + } + } + + is_G = (id && id[0] == 'G' && id[1] == '_'); + is_S = (id && id[0] == 'S' && id[1] == '_'); + + if ((is_G && !glyphid_cache) || filling_cache || dump_ids || is_S) { + while (loadsyms[i].range) { + if (!pm_offset && loadsyms[i].range == SYM_MON) + pm_offset = i; + if (!pm_count && pm_offset && loadsyms[i].range != SYM_MON) + pm_count = i - pm_offset; + if (!oc_offset && loadsyms[i].range == SYM_OC) + oc_offset = i; + if (!oc_count && oc_offset && loadsyms[i].range != SYM_OC) + oc_count = i - oc_offset; + if (!cmap_offset && loadsyms[i].range == SYM_PCHAR) + cmap_offset = i; + if (!cmap_count && cmap_offset && loadsyms[i].range != SYM_PCHAR) + cmap_count = i - cmap_offset; + i++; + } + } + if (is_G || filling_cache || dump_ids) { + if (!filling_cache && id && glyphid_cache) { + int val = find_glyph_in_cache(id); + if (val >= 0) { + findwhat->findtype = find_glyph; + findwhat->val = val; + findwhat->loadsyms_offset = 0; + return 1; + } else { + return 0; + } + } else { + const char *buf2, *buf3, *buf4; + + /* individual matching glyph entries */ + for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { + skip_base = FALSE; + skip_this_one = FALSE; + buf[0][0] = buf[1][0] = buf[2][0] = buf[3][0] = '\0'; + if (glyph_is_monster(glyph)) { + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + buf2 = ""; + buf3 = monsdump[glyph_to_mon(glyph)].nm; + + if (glyph_is_normal_male_monster(glyph)) { + buf2 = "male_"; + } else if (glyph_is_normal_female_monster(glyph)) { + buf2 = "female_"; + } else if (glyph_is_ridden_male_monster(glyph)) { + buf2 = "ridden_male_"; + } else if (glyph_is_ridden_female_monster(glyph)) { + buf2 = "ridden_female_"; + } else if (glyph_is_detected_male_monster(glyph)) { + buf2 = "detected_male_"; + } else if (glyph_is_detected_female_monster(glyph)) { + buf2 = "detected_female_"; + } else if (glyph_is_male_pet(glyph)) { + buf2 = "pet_male_"; + } else if (glyph_is_female_pet(glyph)) { + buf2 = "pet_female_"; + } + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + } else if (glyph_is_body(glyph)) { + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + buf2 = ""; /* superfluous */ + buf3 = monsdump[glyph_to_body_corpsenm(glyph)].nm; + if (glyph_is_body_piletop(glyph)) { + buf2 = "piletop_body_"; + } else { + buf2 = "body_"; + } + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + } else if (glyph_is_statue(glyph)) { + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + buf2 = ""; + buf3 = monsdump[glyph_to_statue_corpsenm(glyph)].nm; + if (glyph_is_fem_statue_piletop(glyph)) { + buf2 = "piletop_statue_of_female_"; + } else if (glyph_is_fem_statue(glyph)) { + buf2 = "statue_of_female_"; + } else if (glyph_is_male_statue_piletop(glyph)) { + buf2 = "piletop_statue_of_male_"; + } else if (glyph_is_male_statue(glyph)) { + buf2 = "statue_of_male_"; + } + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + } else if (glyph_is_object(glyph)) { + i = glyph_to_obj(glyph); + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + buf2 = ""; + buf3 = ""; + if (((i > SCR_STINKING_CLOUD) && (i < SCR_MAIL)) + || ((i > WAN_LIGHTNING) && (i < GOLD_PIECE))) + skip_this_one = TRUE; + if (!skip_this_one) { + if ((i >= WAN_LIGHT) && (i <= WAN_LIGHTNING)) + buf2 = "wand of "; + else if ((i >= SPE_DIG) && (i < SPE_BLANK_PAPER)) + buf2 = "spellbook of "; + else if ((i >= SCR_ENCHANT_ARMOR) + && (i <= SCR_STINKING_CLOUD)) + buf2 = "scroll of "; + else if ((i >= POT_GAIN_ABILITY) && (i <= POT_WATER)) + buf2 = (i == POT_WATER) ? "flask of n" + : "potion of "; + else if ((i >= RIN_ADORNMENT) + && (i <= RIN_PROTECTION_FROM_SHAPE_CHAN)) + buf2 = "ring of "; + else if (i == LAND_MINE) + buf2 = "unset "; + buf3 = (i == SCR_BLANK_PAPER) ? "blank scroll" + : (i == SPE_BLANK_PAPER) ? "blank spellbook" + : (i == SLIME_MOLD) ? "slime mold" + : obj_descr[i].oc_name + ? obj_descr[i].oc_name + : obj_descr[i].oc_descr; + Strcpy(buf[0], "G_"); + if (glyph_is_normal_piletop_obj(glyph)) + Strcat(buf[0], "piletop_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + } + } else if (glyph_is_cmap(glyph) || glyph_is_cmap_zap(glyph) + || glyph_is_swallow(glyph) + || glyph_is_explosion(glyph)) { + int cmap = -1; + + /* buf2 will hold the distinguishing prefix */ + /* buf3 will hold the base name */ + /* buf4 will hold the distinguishing suffix */ + buf2 = ""; + buf3 = ""; + buf4 = ""; + if (glyph == GLYPH_CMAP_OFF) { + cmap = S_stone; + buf3 = "stone substrate"; + skip_base = TRUE; + } else if (glyph_is_cmap_gehennom(glyph)) { + cmap = (glyph - GLYPH_CMAP_GEH_OFF) + S_vwall; + buf4 = "_gehennom"; + } else if (glyph_is_cmap_knox(glyph)) { + cmap = (glyph - GLYPH_CMAP_KNOX_OFF) + S_vwall; + buf4 = "_knox"; + } else if (glyph_is_cmap_main(glyph)) { + cmap = (glyph - GLYPH_CMAP_MAIN_OFF) + S_vwall; + buf4 = "_main"; + } else if (glyph_is_cmap_mines(glyph)) { + cmap = (glyph - GLYPH_CMAP_MINES_OFF) + S_vwall; + buf4 = "_mines"; + } else if (glyph_is_cmap_sokoban(glyph)) { + cmap = (glyph - GLYPH_CMAP_SOKO_OFF) + S_vwall; + buf4 = "_sokoban"; + } else if (glyph_is_cmap_a(glyph)) { + cmap = (glyph - GLYPH_CMAP_A_OFF) + S_ndoor; + } else if (glyph_is_cmap_altar(glyph)) { + static const char *const altar_text[] = { + "unaligned", "chaotic", "neutral", + "lawful", "other", + }; + + j = (glyph - GLYPH_ALTAR_OFF); + cmap = S_altar; + if (j != altar_other) { + Snprintf(buf[2], sizeof buf[2], "%s_", + altar_text[j]); + buf2 = buf[2]; + } else { + buf3 = "altar other"; + skip_base = TRUE; + } + } else if (glyph_is_cmap_b(glyph)) { + cmap = (glyph - GLYPH_CMAP_B_OFF) + S_grave; + } else if (glyph_is_cmap_zap(glyph)) { + static const char *const zap_texts[] = { + "missile", "fire", "frost", "sleep", + "death", "lightning", "poison gas", "acid" + }; + + j = (glyph - GLYPH_ZAP_OFF); + cmap = (j % 4) + S_vbeam; + Snprintf(buf[2], sizeof buf[2], "%s", + loadsyms[cmap + cmap_offset].name + 2); + Snprintf(buf[3], sizeof buf[3], "%s zap %s", + zap_texts[j / 4], fix_glyphname(buf[2])); + buf3 = buf[3]; + buf2 = ""; + skip_base = TRUE; + } else if (glyph_is_cmap_c(glyph)) { + cmap = (glyph - GLYPH_CMAP_C_OFF) + S_digbeam; + } else if (glyph_is_swallow(glyph)) { + static const char *const swallow_texts[] = { + "top left", "top center", "top right", + "middle left", "middle right", "bottom left", + "bottom center", "bottom right", + }; + + j = glyph - GLYPH_SWALLOW_OFF; + cmap = glyph_to_swallow(glyph); + mnum = j / ((S_sw_br - S_sw_tl) + 1); + i = cmap - S_sw_tl; + Strcpy(buf[3], "swallow "); + Strcat(buf[3], monsdump[mnum].nm); + Strcat(buf[3], " "); + Strcat(buf[3], swallow_texts[cmap]); + buf3 = buf[3]; + skip_base = TRUE; + } else if (glyph_is_explosion(glyph)) { + static const char *const expl_type_texts[] = { + "dark", "noxious", "muddy", "wet", + "magical", "fiery", "frosty", + }; + static const char *const expl_texts[] = { + "tl", "tc", "tr", "ml", "mc", + "mr", "bl", "bc", "br", + }; + int expl; + + j = glyph - GLYPH_EXPLODE_OFF; + expl = j / ((S_expl_br - S_expl_tl) + 1); + cmap = (j % ((S_expl_br - S_expl_tl) + 1)) + + S_expl_tl; + i = cmap - S_expl_tl; + Snprintf(buf[2], sizeof buf[2], "%s ", + expl_type_texts[expl]); + buf2 = buf[2]; + Snprintf(buf[3], sizeof buf[3], "%s%s", "expl_", + expl_texts[i]); + buf3 = buf[3]; + skip_base = TRUE; + } + if (!skip_base) { + if (cmap >= 0 && cmap < MAXPCHARS) { + buf3 = loadsyms[cmap + cmap_offset].name + 2; + } + } + Strcpy(buf[0], "G_"); + Strcat(buf[0], buf2); + Strcat(buf[0], buf3); + Strcat(buf[0], buf4); + } else if (glyph_is_invisible(glyph)) { + Strcpy(buf[0], "G_invisible"); + } else if (glyph_is_nothing(glyph)) { + Strcpy(buf[0], "G_nothing"); + } else if (glyph_is_unexplored(glyph)) { + Strcpy(buf[0], "G_unexplored"); + } else if (glyph_is_warning(glyph)) { + j = glyph - GLYPH_WARNING_OFF; + Snprintf(buf[0], sizeof buf[0], "G_%s%d", "warning", j); + } + if (memchr(buf[0], '\0', sizeof buf[0]) == NULL) + panic("parse_id: buf[0] overflowed"); + if (!skip_this_one) { + fix_glyphname(buf[0]+2); + if (dump_ids) { + Fprintf(fp, "(%04d) %s\n", glyph, buf[0]); + } else if (filling_cache) { + add_glyph_to_cache(glyph, buf[0]); + } else if (id) { + if (!strcmpi(id, buf[0])) { + findwhat->findtype = find_glyph; + findwhat->val = glyph; + findwhat->loadsyms_offset = 0; + return 1; + } + } + } + } + } /* not glyphid_cache */ + } else if (is_S) { + /* cmap entries */ + for (i = 0; i < cmap_count; ++i) { + if (!strcmpi(loadsyms[i + cmap_offset].name + 2, id + 2)) { + findwhat->findtype = find_cmap; + findwhat->val = i; + findwhat->loadsyms_offset = i + cmap_offset; + return 1; + } + } + /* objclass entries */ + for (i = 0; i < oc_count; ++i) { + if (!strcmpi(loadsyms[i + oc_offset].name + 2, id + 2)) { + findwhat->findtype = find_oc; + findwhat->val = i; + findwhat->loadsyms_offset = i + oc_offset; + return 1; + } + } + /* permonst entries */ + for (i = 0; i <= pm_count; ++i) { + if (!strcmpi(loadsyms[i + pm_offset].name + 2, id + 2)) { + findwhat->findtype = find_pm; + findwhat->val = i + 1; /* starts at 1 */ + findwhat->loadsyms_offset = i + pm_offset; + return 1; + } + } + } + if (dump_ids || filling_cache) + return 1; + findwhat->findtype = find_nothing; + findwhat->val = 0; + findwhat->loadsyms_offset = 0; + return 0; +} + + +#ifdef TEST_GLYPHNAMES + +static struct { + int idx; + const char *nm1; + const char *nm2; +} cmapname[MAXPCHARS] = { +#define PCHAR_TILES +#include "defsym.h" +#undef PCHAR_TILES +}; + +void +test_glyphnames(void) +{ + int reslt; + + reslt = find_glyphs("G_potion_of_monster_detection"); + reslt = find_glyphs("G_piletop_body_chickatrice"); + reslt = find_glyphs("G_detected_male_homunculus"); + reslt = find_glyphs("S_pool"); + reslt = find_glyphs("S_dog"); + reslt = glyphs_to_unicode("S_dog", "U+130E6", 0L); +} + +staticfn void +just_find_callback(int glyph UNUSED, struct find_struct *findwhat UNUSED) +{ + return; +} + +staticfn int +find_glyphs(const char *id) +{ + struct find_struct find_only = zero_find; + + find_only.unicode_val = 0; + find_only.callback = just_find_callback; + return glyph_find_core(id, &find_only); +} + +staticfn void +to_unicode_callback(int glyph UNUSED, struct find_struct *findwhat) +{ + int uval; +#ifdef NO_PARSING_SYMSET + glyph_map *gm = &glyphmap[glyph]; +#endif + uint8 utf8str[6]; + + if (!findwhat->unicode_val) + return; + uval = unicode_val(findwhat->unicode_val); + if (unicodeval_to_utf8str(uval, utf8str, sizeof utf8str)) { +#ifdef NO_PARSING_SYMSET + set_map_u(gm, uval, utf8str, + (findwhat->color != 0L) ? findwhat->color : 0L); +#else + +#endif + } +} + +int +glyphs_to_unicode(const char *id, const char *unicode_val, long clr) +{ + struct find_struct to_unicode = zero_find; + + to_unicode.unicode_val = unicode_val; + to_unicode.callback = to_unicode_callback; + /* if the color 0 is an actual color, as opposed to just "not set" + we set a marker bit outside the 24-bit range to indicate a + valid color value 0. That allows valid color 0, but allows a + simple checking for 0 to detect "not set". The window port that + implements the color switch, needs to either check that bit + or appropriately mask colors with 0xFFFFFF. */ + to_unicode.color = (clr == -1) ? 0L : (clr == 0L) ? nonzero_black : clr; + return glyph_find_core(id, &to_unicode); +} + +#if 0 +struct customization_detail * +find_display_urep_customization( + const char *customization_name, + int glyphidx, + enum graphics_sets which_set) +{ + struct symset_customization *gdc = &gs.sym_customizations[which_set]; + struct customization_detail *urepdetails; + + if ((gdc->custtype == custom_reps) + || (strcmp(customization_name, gdc->customization_name) == 0)) { + urepdetails = gdc->details; + while (urepdetails) { + if (urepdetails->content.urep.glyphidx == glyphidx) + return urepdetails; + urepdetails = urepdetails->next; + } + } + return (struct customization_detail *) 0; +} +#endif /* 0 */ +#endif /* SOME TEST STUFF */ + +/* glyphs.c */ + + + diff --git a/src/options.c b/src/options.c index a3c5942aa..6b4ee4f60 100644 --- a/src/options.c +++ b/src/options.c @@ -1771,9 +1771,7 @@ optfn_glyph( int optidx UNUSED, int req, boolean negated, char *opts, char *op) { -#ifdef ENHANCED_SYMBOLS int glyph; -#endif if (req == do_init) { return optn_ok; @@ -1790,10 +1788,8 @@ optfn_glyph( return optn_err; /* strip leading/trailing spaces, condense internal ones (3.6.2) */ mungspaces(op); -#ifdef ENHANCED_SYMBOLS if (!glyphrep_to_custom_map_entries(op, &glyph)) return optn_err; -#endif return optn_ok; } if (req == get_val) { @@ -4077,19 +4073,12 @@ optfn_symset( if (req == do_handler) { int reslt; - if (gs.symset[PRIMARYSET].handling == H_UTF8) { -#ifdef ENHANCED_SYMBOLS - if (!glyphid_cache_status()) - fill_glyphid_cache(); -#endif - } + if (!glyphid_cache_status()) + fill_glyphid_cache(); reslt = handler_symset(optidx); - if (gs.symset[PRIMARYSET].handling == H_UTF8) { -#ifdef ENHANCED_SYMBOLS - if (glyphid_cache_status()) - free_glyphid_cache(); -#endif - } + if (glyphid_cache_status()) + free_glyphid_cache(); + /* apply_customizations(gc.currentgraphics); */ return reslt; } return optn_ok; @@ -6928,11 +6917,9 @@ initoptions_init(void) gc.cmdline_windowsys = NULL; } -#ifdef ENHANCED_SYMBOLS /* make any symbol parsing quicker */ if (!glyphid_cache_status()) fill_glyphid_cache(); -#endif /* set up the command parsing */ reset_commands(TRUE); /* init */ @@ -7201,11 +7188,9 @@ initoptions_finish(void) && !opt_set_in_config[opt_bgcolors]) iflags.bgcolors = FALSE; -#ifdef ENHANCED_SYMBOLS if (glyphid_cache_status()) free_glyphid_cache(); - apply_customizations_to_symset(gc.currentgraphics); -#endif + apply_customizations(gc.currentgraphics); go.opt_initial = FALSE; /* diff --git a/src/save.c b/src/save.c index 789b3d68d..ca7632878 100644 --- a/src/save.c +++ b/src/save.c @@ -1168,6 +1168,7 @@ freedynamicdata(void) msgtype_free(); savedsym_free(); tmp_at(DISP_FREEMEM, 0); /* temporary display effects */ + purge_all_custom_entries(); #ifdef FREE_ALL_MEMORY #define free_current_level() savelev(&tnhfp, -1) #define freeobjchn(X) (saveobjchn(&tnhfp, &X), X = 0) diff --git a/src/symbols.c b/src/symbols.c index f700cbf52..ec8ad062d 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -7,9 +7,6 @@ staticfn void savedsym_add(const char *, const char *, int); staticfn struct _savedsym *savedsym_find(const char *, int); -#ifdef ENHANCED_SYMBOLS -staticfn void purge_custom_entries(enum graphics_sets which_set); -#endif extern const uchar def_r_oc_syms[MAXOCLASSES]; /* drawing.c */ @@ -346,8 +343,9 @@ clear_symsetentry(int which_set, boolean name_too) isn't using UTF8, discard the data for that */ if (old_handling == H_UTF8 && gs.symset[other_set].handling != H_UTF8) free_all_glyphmap_u(); - purge_custom_entries(which_set); #endif + purge_custom_entries(which_set); + clear_all_glyphmap_colors(); } /* called from windmain.c */ @@ -357,7 +355,7 @@ symset_is_compatible( unsigned long wincap2) { #ifdef ENHANCED_SYMBOLS -#define WC2_utf8_bits (WC2_U_UTF8STR | WC2_U_24BITCOLOR) +#define WC2_utf8_bits (WC2_U_UTF8STR) if (handling == H_UTF8 && ((wincap2 & WC2_utf8_bits) != WC2_utf8_bits)) return FALSE; #undef WC2_bits @@ -462,8 +460,10 @@ parse_sym_line(char *buf, int which_set) /* find the '=' or ':' */ bufp = strchr(buf, '='); altp = strchr(buf, ':'); + if (!bufp || (altp && altp < bufp)) bufp = altp; + if (!bufp) { if (strncmpi(buf, "finish", 6) == 0) { /* end current graphics set */ @@ -480,15 +480,15 @@ parse_sym_line(char *buf, int which_set) if (*bufp == ' ') ++bufp; - symp = match_sym(buf); if (!symp && buf[0] == 'G' && buf[1] == '_') { -#ifdef ENHANCED_SYMBOLS if (gc.chosen_symset_start) { is_glyph = match_glyph(buf); } else { is_glyph = TRUE; /* report error only once */ } +#ifdef ENHANCED_SYMBOLS + enhanced_unavailable = FALSE; #else enhanced_unavailable = TRUE; #endif @@ -627,8 +627,8 @@ parse_sym_line(char *buf, int which_set) } else { /* Not SYM_CONTROL */ if (gs.symset[which_set].handling != H_UTF8) { - val = sym_val(bufp); if (gc.chosen_symset_start) { + val = sym_val(bufp); if (which_set == PRIMARYSET) { update_primary_symset(symp, val); } else if (which_set == ROGUESET) { @@ -643,6 +643,9 @@ parse_sym_line(char *buf, int which_set) #endif } } + } else if (gc.chosen_symset_start) { + /* glyph, not symbol */ + glyphrep_to_custom_map_entries(buf, &glyph); } #ifndef ENHANCED_SYMBOLS nhUse(glyph); @@ -677,6 +680,7 @@ load_symset(const char *s, int which_set) if (read_sym_file(which_set)) { switch_symbols(TRUE); + apply_customizations(gc.currentgraphics); } else { clear_symsetentry(which_set, TRUE); return 0; @@ -816,24 +820,20 @@ parsesymbols(char *opts, int which_set) mungspaces(strval); symp = match_sym(symname); -#ifdef ENHANCED_SYMBOLS if (!symp && symname[0] == 'G' && symname[1] == '_') { is_glyph = match_glyph(symname); } -#endif if (!symp && !is_glyph) return FALSE; if (symp) { if (symp->range && symp->range != SYM_CONTROL) { if (gs.symset[which_set].handling == H_UTF8 || (lowc(strval[0]) == 'u' && strval[1] == '+')) { -#ifdef ENHANCED_SYMBOLS char buf[BUFSZ]; int glyph; Snprintf(buf, sizeof buf, "%s:%s", opts, strval); glyphrep_to_custom_map_entries(buf, &glyph); -#endif /* ENHANCED_SYMBOLS */ } else { val = sym_val(strval); if (which_set == ROGUESET) @@ -1066,17 +1066,13 @@ do_symset(boolean rogueflag) if (gs.symset[which_set].name) { /* non-default symbols */ int ok; -#ifdef ENHANCED_SYMBOLS if (!glyphid_cache_status()) { fill_glyphid_cache(); } -#endif ok = read_sym_file(which_set); -#ifdef ENHANCED_SYMBOLS if (glyphid_cache_status()) { free_glyphid_cache(); } -#endif if (ok) { ready_to_switch = TRUE; } else { @@ -1093,173 +1089,24 @@ do_symset(boolean rogueflag) assign_graphics(ROGUESET); } else if (!rogueflag) assign_graphics(PRIMARYSET); -#ifdef ENHANCED_SYMBOLS - apply_customizations_to_symset(rogueflag ? ROGUESET : PRIMARYSET); -#endif + apply_customizations(rogueflag ? ROGUESET : PRIMARYSET); preference_update("symset"); return TRUE; } -#ifdef ENHANCED_SYMBOLS +extern glyph_map glyphmap[MAX_GLYPH]; + +void +clear_all_glyphmap_colors(void) +{ + int glyph; + + for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { + if (glyphmap[glyph].nhcolor) + glyphmap[glyph].nhcolor = 0; + } +} RESTORE_WARNING_FORMAT_NONLITERAL -struct customization_detail *find_display_sym_customization( - const char *customization_name, const struct symparse *symparse, - enum graphics_sets which_set); -struct customization_detail *find_matching_symset_customiz( - const char *customization_name, int custtype, - enum graphics_sets which_set); -struct customization_detail *find_display_urep_customization( - const char *customization_name, int glyphidx, - enum graphics_sets which_set); -extern glyph_map glyphmap[MAX_GLYPH]; -staticfn void shuffle_customizations(void); - -void -apply_customizations_to_symset(enum graphics_sets which_set) -{ - glyph_map *gmap; - struct customization_detail *details; - - if (gs.symset[which_set].handling == H_UTF8 - && gs.sym_customizations[which_set].count - && gs.sym_customizations[which_set].details) { - /* These UTF-8 customizations get applied to the glyphmap array, - not to symset entries */ - details = gs.sym_customizations[which_set].details; - while (details) { - gmap = &glyphmap[details->content.urep.glyphidx]; - (void) set_map_u(gmap, - details->content.urep.u.utf32ch, - details->content.urep.u.utf8str, - details->content.urep.u.ucolor); - details = details->next; - } - shuffle_customizations(); - } -} -/* Shuffle the customizations to match shuffled object descriptions, - * so a red potion isn't displayed with a blue customization, and so on. - */ -staticfn void -shuffle_customizations(void) -{ - static const int offsets[2] = { GLYPH_OBJ_OFF, GLYPH_OBJ_PILETOP_OFF }; - int j; - - for (j = 0; j < SIZE(offsets); j++) { - glyph_map *obj_glyphs = glyphmap + offsets[j]; - int i; - struct unicode_representation *tmp_u[NUM_OBJECTS]; - int duplicate[NUM_OBJECTS]; - - for (i = 0; i < NUM_OBJECTS; i++) { - duplicate[i] = -1; - tmp_u[i] = (struct unicode_representation *) 0; - } - for (i = 0; i < NUM_OBJECTS; i++) { - int idx = objects[i].oc_descr_idx; - - /* - * Shuffling gem appearances can cause the same oc_descr_idx to - * appear more than once. Detect this condition and ensure that - * each pointer points to a unique allocation. - */ - if (duplicate[idx] >= 0) { - /* Current structure already appears in tmp_u */ - struct unicode_representation *other = tmp_u[duplicate[idx]]; - - tmp_u[i] = (struct unicode_representation *) - alloc(sizeof *tmp_u[i]); - *tmp_u[i] = *other; - if (other->utf8str != NULL) { - tmp_u[i]->utf8str = (uint8 *) - dupstr((const char *) other->utf8str); - } - } else { - tmp_u[i] = obj_glyphs[idx].u; - if (obj_glyphs[idx].u != NULL) { - duplicate[idx] = i; - obj_glyphs[idx].u = NULL; - } - } - } - for (i = 0; i < NUM_OBJECTS; i++) { - /* Some glyphmaps may not have been transferred */ - if (obj_glyphs[i].u != NULL) { - free(obj_glyphs[i].u->utf8str); - free(obj_glyphs[i].u); - } - obj_glyphs[i].u = tmp_u[i]; - } - } -} - -struct customization_detail * -find_matching_symset_customiz( - const char *customization_name, - int custtype, - enum graphics_sets which_set) -{ - struct symset_customization *gdc = &gs.sym_customizations[which_set]; - - if ((gdc->custtype == custtype) - && (strcmp(customization_name, gdc->customization_name) != 0)) - return gdc->details; - return (struct customization_detail *) 0; -} - -staticfn void -purge_custom_entries(enum graphics_sets which_set) -{ - struct symset_customization *gdc = &gs.sym_customizations[which_set]; - struct customization_detail *details = gdc->details, *next; - - while (details) { - next = details->next; - if (gdc->custtype == custom_ureps) { - if (details->content.urep.u.utf8str) - free(details->content.urep.u.utf8str); - details->content.urep.u.utf8str = (uint8 *) 0; - details->content.urep.u.ucolor = 0L; - details->content.urep.u.u256coloridx = 0L; - } else if (gdc->custtype == custom_symbols) { - details->content.sym.symparse = (struct symparse *) 0; - details->content.sym.val = 0; - } - free(details); - details = next; - } - gdc->details = 0; - gdc->details_end = 0; - if (gdc->customization_name) { - free((genericptr_t) gdc->customization_name); - gdc->customization_name = 0; - } - gdc->count = 0; -} - -struct customization_detail * -find_display_sym_customization( - const char *customization_name, - const struct symparse *symparse, - enum graphics_sets which_set) -{ - struct symset_customization *gdc = &gs.sym_customizations[which_set]; - struct customization_detail *symdetails; - - if ((gdc->custtype == custom_symbols) - && (strcmp(customization_name, gdc->customization_name) == 0)) { - symdetails = gdc->details; - while (symdetails) { - if (symdetails->content.sym.symparse == symparse) - return symdetails; - symdetails = symdetails->next; - } - } - return (struct customization_detail *) 0; -} -#endif /* ENHANCED_SYMBOLS */ - /*symbols.c*/ diff --git a/src/utf8map.c b/src/utf8map.c index 8ab54129e..4931d57d9 100644 --- a/src/utf8map.c +++ b/src/utf8map.c @@ -5,233 +5,18 @@ #include "hack.h" #include +#ifdef ENHANCED_SYMBOLS + extern const struct symparse loadsyms[]; extern struct enum_dump monsdump[]; extern struct enum_dump objdump[]; extern glyph_map glyphmap[MAX_GLYPH]; extern const char *const known_handling[]; /* symbols.c */ -#ifdef ENHANCED_SYMBOLS - -#define Fprintf (void) fprintf -enum reserved_activities { res_nothing, res_dump_glyphids, res_fill_cache }; -enum things_to_find { find_nothing, find_pm, find_oc, find_cmap, find_glyph }; -struct find_struct { - enum things_to_find findtype; - int val; - int loadsyms_offset; - int loadsyms_count; - int *extraval; - long color; - const char *unicode_val; /* U+NNNN format */ - void (*callback)(int glyph, struct find_struct *); - enum reserved_activities restype; - genericptr_t reserved; -}; -static const struct find_struct zero_find = { 0 }; -struct glyphid_cache_t { - int glyphnum; - char *id; -}; -static struct glyphid_cache_t *glyphid_cache; -static unsigned glyphid_cache_lsize; -static size_t glyphid_cache_size; -static struct find_struct glyphcache_find, to_custom_symbol_find; - -staticfn void init_glyph_cache(void); -staticfn void add_glyph_to_cache(int glyphnum, const char *id); -staticfn int find_glyph_in_cache(const char *id); -staticfn uint32 glyph_hash(const char *id); -staticfn void to_custom_symset_entry_callback(int glyph, - struct find_struct *findwhat); -staticfn int unicode_val(const char *cp); -staticfn int parse_id(const char *id, struct find_struct *findwhat); -staticfn int glyph_find_core(const char *id, struct find_struct *findwhat); -staticfn char *fix_glyphname(char *str); -staticfn int32_t rgbstr_to_int32(const char *rgbstr); -boolean closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx); -staticfn int color_distance(uint32_t, uint32_t); -staticfn boolean onlyhexdigits(const char *buf); - -static const long nonzero_black = CLR_BLACK | NH_BASIC_COLOR; - -staticfn void -to_custom_symset_entry_callback(int glyph, struct find_struct *findwhat) -{ -#ifdef NO_PARSING_SYMSET - glyph_map *gmap = &glyphmap[glyph]; -#endif - uint8 utf8str[6] = { 0, 0, 0, 0, 0, 0 }; - int uval; - - if (!findwhat->unicode_val) - return; - if (findwhat->extraval) - *findwhat->extraval = glyph; - uval = unicode_val(findwhat->unicode_val); - if (unicodeval_to_utf8str(uval, utf8str, sizeof utf8str)) { -#ifdef NO_PARSING_SYMSET - set_map_u(gmap, uval, utf8str, - (findwhat->color != 0L) ? findwhat->color : 0L); -#endif - add_custom_urep_entry(known_handling[H_UTF8], glyph, - uval, utf8str, findwhat->color, - gs.symset_which_set); - } -} - -/* - * Return value: - * 1 = success - * 0 = failure - */ -int -glyphrep_to_custom_map_entries(const char *op, int *glyphptr) -{ - to_custom_symbol_find = zero_find; - char buf[BUFSZ], *c_glyphid, *c_unicode, *c_rgb, *cp; - int milestone, reslt = 0; - long rgb; - boolean slash = FALSE; - - if (!glyphid_cache) - reslt = 1; /* for debugger use only; no cache available */ - - milestone = 0; - Snprintf(buf, sizeof buf, "%s", op); - c_unicode = c_rgb = (char *) 0; - c_glyphid = cp = buf; - while (*cp) { - if ((*cp == '/') || (*cp == ':')) { - *cp = '\0'; - milestone++; - slash = TRUE; - } - cp++; - if (slash) { - if (milestone < 2) - c_unicode = cp; - else - c_rgb = cp; - slash = FALSE; - } - } - /* some sanity checks */ - if (c_glyphid && *c_glyphid == ' ') - c_glyphid++; - if (c_unicode && *c_unicode == ' ') - c_unicode++; - if (c_rgb && *c_rgb == ' ') - c_rgb++; - if (c_unicode && (*c_unicode == 'U' || *c_unicode == 'u') - && (c_unicode[1] == '+')) { - /* unicode = unicode_val(c_unicode); */ - if ((rgb = rgbstr_to_int32(c_rgb)) != -1L || !c_rgb) { - to_custom_symbol_find.unicode_val = c_unicode; - /* if the color 0 is an actual color, as opposed to just "not set" - we set a marker bit outside the 24-bit range to indicate a - valid color value 0. That allows valid color 0, but allows a - simple checking for 0 to detect "not set". The window port that - implements the color switch, needs to either check that bit - or appropriately mask colors with 0xFFFFFF. */ - to_custom_symbol_find.color = (rgb == -1 || !c_rgb) ? 0L - : (rgb == 0L) ? nonzero_black : rgb; - to_custom_symbol_find.extraval = glyphptr; - to_custom_symbol_find.callback = to_custom_symset_entry_callback; - reslt = glyph_find_core(c_glyphid, &to_custom_symbol_find); - return reslt; - } - } - return 0; -} - static const char hex[] = "00112233445566778899aAbBcCdDeEfF"; -staticfn boolean -onlyhexdigits(const char *buf) -{ - const char *dp = buf; - for (dp = buf; *dp; ++dp) { - if (!(strchr(hex, *dp) || *dp == '-')) - return FALSE; - } - return TRUE; -} - -staticfn int32_t -rgbstr_to_int32(const char *rgbstr) -{ - int r, g, b, milestone = 0; - char *cp, *c_r, *c_g, *c_b; - int32_t rgb = 0; - char buf[BUFSZ]; - boolean dash = FALSE; - - - Snprintf(buf, sizeof buf, "%s", - rgbstr ? rgbstr : ""); - - if (*buf && onlyhexdigits(buf)) { - r = g = b = 0; - c_g = c_b = (char *) 0; - c_r = cp = buf; - while (*cp) { - if (digit(*cp) || *cp == '-') { - if (*cp == '-') { - *cp = '\0'; - milestone++; - dash = TRUE; - } - cp++; - if (dash) { - if (milestone < 2) - c_g = cp; - else - c_b = cp; - dash = FALSE; - } - } else { - return -1L; - } - } - /* sanity checks */ - if (c_r && c_g && c_b - && (strlen(c_r) > 0 && strlen(c_r) < 4) - && (strlen(c_g) > 0 && strlen(c_g) < 4) - && (strlen(c_b) > 0 && strlen(c_b) < 4)) { - r = atoi(c_r); - g = atoi(c_g); - b = atoi(c_b); - rgb = (r << 16) | (g << 8) | (b << 0); - return rgb; - } - } else if (*buf) { - /* perhaps an enhanced color name was used instead of rgb value? */ - if ((rgb = check_enhanced_colors(buf)) != -1) { - return rgb; - } - } - return -1; -} - -staticfn char * -fix_glyphname(char *str) -{ - char *c; - - for (c = str; *c; c++) { - if (*c >= 'A' && *c <= 'Z') - *c += (char) ('a' - 'A'); - else if (*c >= '0' && *c <= '9') - ; - else if (*c < 'a' || *c > 'z') - *c = '_'; - } - return str; -} - -staticfn int +int unicode_val(const char *cp) { const char *dp; @@ -251,17 +36,16 @@ unicode_val(const char *cp) } int -set_map_u(glyph_map *gmap, uint32 utf32ch, const uint8 *utf8str, long ucolor) +set_map_u(glyph_map *gmap, uint32 utf32ch, const uint8 *utf8str) { - static uint32_t closecolor = 0; - static int clridx = 0; glyph_map *tmpgm = gmap; - if (!tmpgm) + if (!tmpgm || !utf32ch) return 0; if (gmap->u == 0) { - gmap->u = (struct unicode_representation *) alloc(sizeof *gmap->u); + gmap->u = + (struct unicode_representation *) alloc(sizeof *gmap->u); gmap->u->utf8str = 0; } if (gmap->u->utf8str != 0) { @@ -269,218 +53,10 @@ set_map_u(glyph_map *gmap, uint32 utf32ch, const uint8 *utf8str, long ucolor) gmap->u->utf8str = 0; } gmap->u->utf8str = (uint8 *) dupstr((const char *) utf8str); - gmap->u->ucolor = ucolor; - if (closest_color(ucolor, &closecolor, &clridx)) - gmap->u->u256coloridx = clridx; - else - gmap->u->u256coloridx = 0; gmap->u->utf32ch = utf32ch; return 1; } - -staticfn int -glyph_find_core(const char *id, struct find_struct *findwhat) -{ - int glyph; - boolean do_callback, end_find = FALSE; - - if (parse_id(id, findwhat)) { - if (findwhat->findtype == find_glyph) { - (*findwhat->callback)(findwhat->val, findwhat); - } else { - for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { - do_callback = FALSE; - switch (findwhat->findtype) { - case find_cmap: - if (glyph_to_cmap(glyph) == findwhat->val) - do_callback = TRUE; - break; - case find_pm: - if (glyph_is_monster(glyph) - && monsym(&mons[glyph_to_mon(glyph)]) == findwhat->val) - do_callback = TRUE; - break; - case find_oc: - if (glyph_is_object(glyph) - && glyph_to_obj(glyph) == findwhat->val) - do_callback = TRUE; - break; - case find_glyph: - if (glyph == findwhat->val) { - do_callback = TRUE; - end_find = TRUE; - } - break; - case find_nothing: - default: - end_find = TRUE; - break; - } - if (do_callback) - (findwhat->callback)(glyph, findwhat); - if (end_find) - break; - } - } - return 1; - } - return 0; -} - -/* - When we start to process a config file or a symbol file, - that might have G_ entries, generating all 9000+ glyphid - for comparison repeatedly each time we encounter a G_ - entry to decipher, then comparing against them, is obviously - extremely performance-poor. - - Setting aside the "comparison" part for now (that has to be - done in some manner), we can likely do something about the - repeated "generation" of the names for parsing prior to the - actual comparison part by generating them once, ahead of the - bulk of the potential parsings. We can later free up - all the memory those names consumed once the bulk parsing is - over with. -*/ - - -void fill_glyphid_cache(void) -{ - int reslt = 0; - - if (!glyphid_cache) { - init_glyph_cache(); - } - if (glyphid_cache) { - glyphcache_find = zero_find; - glyphcache_find.findtype = find_nothing; - glyphcache_find.reserved = (genericptr_t) glyphid_cache; - glyphcache_find.restype = res_fill_cache; - reslt = parse_id((char *) 0, &glyphcache_find); - if (!reslt) { - free_glyphid_cache(); - glyphid_cache = (struct glyphid_cache_t *) 0; - } - } -} - -/* - * The glyph ID cache is a simple double-hash table. - * The cache size is a power of two, and two hashes are derived from the - * cache ID. The first is a location in the table, and the second is an - * offset. On any collision, the second hash is added to the first until - * a match or an empty bucket is found. - * The second hash is an odd number, which is necessary and sufficient - * to traverse the entire table. - */ - -staticfn void -init_glyph_cache(void) -{ - size_t glyph; - - /* Cache size of power of 2 not less than 2*MAX_GLYPH */ - glyphid_cache_lsize = 0; - glyphid_cache_size = 1; - while (glyphid_cache_size < 2*MAX_GLYPH) { - ++glyphid_cache_lsize; - glyphid_cache_size <<= 1; - } - - glyphid_cache = (struct glyphid_cache_t *) alloc( - glyphid_cache_size * sizeof (struct glyphid_cache_t)); - for (glyph = 0; glyph < glyphid_cache_size; ++glyph) { - glyphid_cache[glyph].glyphnum = 0; - glyphid_cache[glyph].id = (char *) 0; - } -} - -void free_glyphid_cache(void) -{ - size_t idx; - - if (!glyphid_cache) - return; - for (idx = 0; idx < glyphid_cache_size; ++idx) { - if (glyphid_cache[idx].id) { - free(glyphid_cache[idx].id); - glyphid_cache[idx].id = (char *) 0; - } - } - free(glyphid_cache); - glyphid_cache = (struct glyphid_cache_t *) 0; -} - -staticfn void -add_glyph_to_cache(int glyphnum, const char *id) -{ - uint32 hash = glyph_hash(id); - size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); - size_t hash2 = (size_t) - (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); - size_t i = hash1; - - do { - if (glyphid_cache[i].id == NULL) { - /* Empty bucket found */ - glyphid_cache[i].id = dupstr(id); - glyphid_cache[i].glyphnum = glyphnum; - return; - } - /* For speed, assume that no ID occurs twice */ - i = (i + hash2) & (glyphid_cache_size - 1); - } while (i != hash1); - /* This should never happen */ - panic("glyphid_cache full"); -} - -staticfn int -find_glyph_in_cache(const char *id) -{ - uint32 hash = glyph_hash(id); - size_t hash1 = (size_t) (hash & (glyphid_cache_size - 1)); - size_t hash2 = (size_t) - (((hash >> glyphid_cache_lsize) & (glyphid_cache_size - 1)) | 1); - size_t i = hash1; - - do { - if (glyphid_cache[i].id == NULL) { - /* Empty bucket found */ - return -1; - } - if (strcmpi(id, glyphid_cache[i].id) == 0) { - /* Match found */ - return glyphid_cache[i].glyphnum; - } - i = (i + hash2) & (glyphid_cache_size - 1); - } while (i != hash1); - return -1; -} - -staticfn uint32 -glyph_hash(const char *id) -{ - uint32 hash = 0; - size_t i; - - for (i = 0; id[i] != '\0'; ++i) { - char ch = id[i]; - if ('A' <= ch && ch <= 'Z') { - ch += 'a' - 'A'; - } - hash = (hash << 1) | (hash >> 31); - hash ^= ch; - } - return hash; -} - -boolean -glyphid_cache_status(void) -{ - return (glyphid_cache != 0); -} - void free_all_glyphmap_u(void) { @@ -569,704 +145,8 @@ mixed_to_utf8(char *buf, size_t bufsz, const char *str, int *retflags) *put = '\0'; return buf; } - -void -dump_all_glyphids(FILE *fp) -{ - struct find_struct dump_glyphid_find = zero_find; - - dump_glyphid_find.findtype = find_nothing; - dump_glyphid_find.reserved = (genericptr_t) fp; - dump_glyphid_find.restype = res_dump_glyphids; - (void) parse_id((char *) 0, &dump_glyphid_find); -} - -int -match_glyph(char *buf) -{ - char workbuf[BUFSZ]; - - /* buf contains a G_ glyph reference, not an S_ symbol. - There could be an R-G-B color attached too. - Let's get a copy to work with. */ - Snprintf(workbuf, sizeof workbuf, "%s", buf); /* get a copy */ - return glyphrep(workbuf); -} - -int -glyphrep(const char *op) -{ - int reslt = 0, glyph = NO_GLYPH; - - if (!glyphid_cache) - reslt = 1; /* for debugger use only; no cache available */ - reslt = glyphrep_to_custom_map_entries(op, &glyph); - if (reslt) - return 1; - return 0; -} - -int -add_custom_urep_entry( - const char *customization_name, - int glyphidx, - uint32 utf32ch, - const uint8 *utf8str, - long ucolor, - enum graphics_sets which_set) -{ - static uint32_t closecolor = 0; - static int clridx = 0; - struct symset_customization *gdc = &gs.sym_customizations[which_set]; - struct customization_detail *details, *newdetails = 0; - - - if (!gdc->details) { - gdc->customization_name = dupstr(customization_name); - gdc->custtype = custom_ureps; - gdc->details = 0; - gdc->details_end = 0; - } - details = find_matching_symset_customiz(customization_name, - custom_symbols, which_set); - if (details) { - while (details) { - if (details->content.urep.glyphidx == glyphidx) { - if (details->content.urep.u.utf8str) - free(details->content.urep.u.utf8str); - details->content.urep.u.utf8str = - (uint8 *) dupstr((const char *) utf8str); - details->content.urep.u.ucolor = ucolor; - if (closest_color(ucolor, &closecolor, &clridx)) - details->content.urep.u.u256coloridx = clridx; - else - details->content.urep.u.u256coloridx = 0; - details->content.urep.u.utf32ch = utf32ch; - return 1; - } - details = details->next; - } - } - /* create new details entry */ - newdetails = (struct customization_detail *) alloc( - sizeof (struct customization_detail)); - newdetails->content.urep.glyphidx = glyphidx; - newdetails->content.urep.u.utf8str = - (uint8 *) dupstr((const char *) utf8str); - newdetails->content.urep.u.ucolor = ucolor; - if (closest_color(ucolor, &closecolor, &clridx)) - newdetails->content.urep.u.u256coloridx = clridx; - else - newdetails->content.urep.u.u256coloridx = 0; - newdetails->content.urep.u.utf32ch = utf32ch; - newdetails->next = (struct customization_detail *) 0; - if (gdc->details == NULL) { - gdc->details = newdetails; - } else { - gdc->details_end->next = newdetails; - } - gdc->details_end = newdetails; - gdc->count++; - return 1; -} - -staticfn int -parse_id(const char *id, struct find_struct *findwhat) -{ - FILE *fp = (FILE *) 0; - int i = 0, j, mnum, glyph, - pm_offset = 0, oc_offset = 0, cmap_offset = 0, - pm_count = 0, oc_count = 0, cmap_count = 0; - boolean skip_base = FALSE, skip_this_one, dump_ids = FALSE, - filling_cache = FALSE, is_S = FALSE, is_G = FALSE; - char buf[4][QBUFSZ]; - - if (findwhat->findtype == find_nothing && findwhat->restype) { - if (findwhat->restype == res_dump_glyphids) { - if (findwhat->reserved) { - fp = (FILE *) findwhat->reserved; - dump_ids = TRUE; - } else { - return 0; - } - } - if (findwhat->restype == res_fill_cache) { - if (findwhat->reserved - && findwhat->reserved == (genericptr_t) glyphid_cache) { - filling_cache = TRUE; - } else { - return 0; - } - } - } - - is_G = (id && id[0] == 'G' && id[1] == '_'); - is_S = (id && id[0] == 'S' && id[1] == '_'); - - if ((is_G && !glyphid_cache) || filling_cache || dump_ids || is_S) { - while (loadsyms[i].range) { - if (!pm_offset && loadsyms[i].range == SYM_MON) - pm_offset = i; - if (!pm_count && pm_offset && loadsyms[i].range != SYM_MON) - pm_count = i - pm_offset; - if (!oc_offset && loadsyms[i].range == SYM_OC) - oc_offset = i; - if (!oc_count && oc_offset && loadsyms[i].range != SYM_OC) - oc_count = i - oc_offset; - if (!cmap_offset && loadsyms[i].range == SYM_PCHAR) - cmap_offset = i; - if (!cmap_count && cmap_offset && loadsyms[i].range != SYM_PCHAR) - cmap_count = i - cmap_offset; - i++; - } - } - if (is_G || filling_cache || dump_ids) { - if (!filling_cache && id && glyphid_cache) { - int val = find_glyph_in_cache(id); - if (val >= 0) { - findwhat->findtype = find_glyph; - findwhat->val = val; - findwhat->loadsyms_offset = 0; - return 1; - } else { - return 0; - } - } else { - const char *buf2, *buf3, *buf4; - - /* individual matching glyph entries */ - for (glyph = 0; glyph < MAX_GLYPH; ++glyph) { - skip_base = FALSE; - skip_this_one = FALSE; - buf[0][0] = buf[1][0] = buf[2][0] = buf[3][0] = '\0'; - if (glyph_is_monster(glyph)) { - /* buf2 will hold the distinguishing prefix */ - /* buf3 will hold the base name */ - buf2 = ""; - buf3 = monsdump[glyph_to_mon(glyph)].nm; - - if (glyph_is_normal_male_monster(glyph)) { - buf2 = "male_"; - } else if (glyph_is_normal_female_monster(glyph)) { - buf2 = "female_"; - } else if (glyph_is_ridden_male_monster(glyph)) { - buf2 = "ridden_male_"; - } else if (glyph_is_ridden_female_monster(glyph)) { - buf2 = "ridden_female_"; - } else if (glyph_is_detected_male_monster(glyph)) { - buf2 = "detected_male_"; - } else if (glyph_is_detected_female_monster(glyph)) { - buf2 = "detected_female_"; - } else if (glyph_is_male_pet(glyph)) { - buf2 = "pet_male_"; - } else if (glyph_is_female_pet(glyph)) { - buf2 = "pet_female_"; - } - Strcpy(buf[0], "G_"); - Strcat(buf[0], buf2); - Strcat(buf[0], buf3); - } else if (glyph_is_body(glyph)) { - /* buf2 will hold the distinguishing prefix */ - /* buf3 will hold the base name */ - buf2 = ""; /* superfluous */ - buf3 = monsdump[glyph_to_body_corpsenm(glyph)].nm; - if (glyph_is_body_piletop(glyph)) { - buf2 = "piletop_body_"; - } else { - buf2 = "body_"; - } - Strcpy(buf[0], "G_"); - Strcat(buf[0], buf2); - Strcat(buf[0], buf3); - } else if (glyph_is_statue(glyph)) { - /* buf2 will hold the distinguishing prefix */ - /* buf3 will hold the base name */ - buf2 = ""; - buf3 = monsdump[glyph_to_statue_corpsenm(glyph)].nm; - if (glyph_is_fem_statue_piletop(glyph)) { - buf2 = "piletop_statue_of_female_"; - } else if (glyph_is_fem_statue(glyph)) { - buf2 = "statue_of_female_"; - } else if (glyph_is_male_statue_piletop(glyph)) { - buf2 = "piletop_statue_of_male_"; - } else if (glyph_is_male_statue(glyph)) { - buf2 = "statue_of_male_"; - } - Strcpy(buf[0], "G_"); - Strcat(buf[0], buf2); - Strcat(buf[0], buf3); - } else if (glyph_is_object(glyph)) { - i = glyph_to_obj(glyph); - /* buf2 will hold the distinguishing prefix */ - /* buf3 will hold the base name */ - buf2 = ""; - buf3 = ""; - if (((i > SCR_STINKING_CLOUD) && (i < SCR_MAIL)) - || ((i > WAN_LIGHTNING) && (i < GOLD_PIECE))) - skip_this_one = TRUE; - if (!skip_this_one) { - if ((i >= WAN_LIGHT) && (i <= WAN_LIGHTNING)) - buf2 = "wand of "; - else if ((i >= SPE_DIG) && (i < SPE_BLANK_PAPER)) - buf2 = "spellbook of "; - else if ((i >= SCR_ENCHANT_ARMOR) - && (i <= SCR_STINKING_CLOUD)) - buf2 = "scroll of "; - else if ((i >= POT_GAIN_ABILITY) && (i <= POT_WATER)) - buf2 = (i == POT_WATER) ? "flask of n" - : "potion of "; - else if ((i >= RIN_ADORNMENT) - && (i <= RIN_PROTECTION_FROM_SHAPE_CHAN)) - buf2 = "ring of "; - else if (i == LAND_MINE) - buf2 = "unset "; - buf3 = (i == SCR_BLANK_PAPER) ? "blank scroll" - : (i == SPE_BLANK_PAPER) ? "blank spellbook" - : (i == SLIME_MOLD) ? "slime mold" - : obj_descr[i].oc_name - ? obj_descr[i].oc_name - : obj_descr[i].oc_descr; - Strcpy(buf[0], "G_"); - if (glyph_is_normal_piletop_obj(glyph)) - Strcat(buf[0], "piletop_"); - Strcat(buf[0], buf2); - Strcat(buf[0], buf3); - } - } else if (glyph_is_cmap(glyph) || glyph_is_cmap_zap(glyph) - || glyph_is_swallow(glyph) - || glyph_is_explosion(glyph)) { - int cmap = -1; - - /* buf2 will hold the distinguishing prefix */ - /* buf3 will hold the base name */ - /* buf4 will hold the distinguishing suffix */ - buf2 = ""; - buf3 = ""; - buf4 = ""; - if (glyph == GLYPH_CMAP_OFF) { - cmap = S_stone; - buf3 = "stone substrate"; - skip_base = TRUE; - } else if (glyph_is_cmap_gehennom(glyph)) { - cmap = (glyph - GLYPH_CMAP_GEH_OFF) + S_vwall; - buf4 = "_gehennom"; - } else if (glyph_is_cmap_knox(glyph)) { - cmap = (glyph - GLYPH_CMAP_KNOX_OFF) + S_vwall; - buf4 = "_knox"; - } else if (glyph_is_cmap_main(glyph)) { - cmap = (glyph - GLYPH_CMAP_MAIN_OFF) + S_vwall; - buf4 = "_main"; - } else if (glyph_is_cmap_mines(glyph)) { - cmap = (glyph - GLYPH_CMAP_MINES_OFF) + S_vwall; - buf4 = "_mines"; - } else if (glyph_is_cmap_sokoban(glyph)) { - cmap = (glyph - GLYPH_CMAP_SOKO_OFF) + S_vwall; - buf4 = "_sokoban"; - } else if (glyph_is_cmap_a(glyph)) { - cmap = (glyph - GLYPH_CMAP_A_OFF) + S_ndoor; - } else if (glyph_is_cmap_altar(glyph)) { - static const char *const altar_text[] = { - "unaligned", "chaotic", "neutral", - "lawful", "other", - }; - - j = (glyph - GLYPH_ALTAR_OFF); - cmap = S_altar; - if (j != altar_other) { - Snprintf(buf[2], sizeof buf[2], "%s_", - altar_text[j]); - buf2 = buf[2]; - } else { - buf3 = "altar other"; - skip_base = TRUE; - } - } else if (glyph_is_cmap_b(glyph)) { - cmap = (glyph - GLYPH_CMAP_B_OFF) + S_grave; - } else if (glyph_is_cmap_zap(glyph)) { - static const char *const zap_texts[] = { - "missile", "fire", "frost", "sleep", - "death", "lightning", "poison gas", "acid" - }; - - j = (glyph - GLYPH_ZAP_OFF); - cmap = (j % 4) + S_vbeam; - Snprintf(buf[2], sizeof buf[2], "%s", - loadsyms[cmap + cmap_offset].name + 2); - Snprintf(buf[3], sizeof buf[3], "%s zap %s", - zap_texts[j / 4], fix_glyphname(buf[2])); - buf3 = buf[3]; - buf2 = ""; - skip_base = TRUE; - } else if (glyph_is_cmap_c(glyph)) { - cmap = (glyph - GLYPH_CMAP_C_OFF) + S_digbeam; - } else if (glyph_is_swallow(glyph)) { - static const char *const swallow_texts[] = { - "top left", "top center", "top right", - "middle left", "middle right", "bottom left", - "bottom center", "bottom right", - }; - - j = glyph - GLYPH_SWALLOW_OFF; - cmap = glyph_to_swallow(glyph); - mnum = j / ((S_sw_br - S_sw_tl) + 1); - i = cmap - S_sw_tl; - Strcpy(buf[3], "swallow "); - Strcat(buf[3], monsdump[mnum].nm); - Strcat(buf[3], " "); - Strcat(buf[3], swallow_texts[cmap]); - buf3 = buf[3]; - skip_base = TRUE; - } else if (glyph_is_explosion(glyph)) { - static const char *const expl_type_texts[] = { - "dark", "noxious", "muddy", "wet", - "magical", "fiery", "frosty", - }; - static const char *const expl_texts[] = { - "tl", "tc", "tr", "ml", "mc", - "mr", "bl", "bc", "br", - }; - int expl; - - j = glyph - GLYPH_EXPLODE_OFF; - expl = j / ((S_expl_br - S_expl_tl) + 1); - cmap = (j % ((S_expl_br - S_expl_tl) + 1)) - + S_expl_tl; - i = cmap - S_expl_tl; - Snprintf(buf[2], sizeof buf[2], "%s ", - expl_type_texts[expl]); - buf2 = buf[2]; - Snprintf(buf[3], sizeof buf[3], "%s%s", "expl_", - expl_texts[i]); - buf3 = buf[3]; - skip_base = TRUE; - } - if (!skip_base) { - if (cmap >= 0 && cmap < MAXPCHARS) { - buf3 = loadsyms[cmap + cmap_offset].name + 2; - } - } - Strcpy(buf[0], "G_"); - Strcat(buf[0], buf2); - Strcat(buf[0], buf3); - Strcat(buf[0], buf4); - } else if (glyph_is_invisible(glyph)) { - Strcpy(buf[0], "G_invisible"); - } else if (glyph_is_nothing(glyph)) { - Strcpy(buf[0], "G_nothing"); - } else if (glyph_is_unexplored(glyph)) { - Strcpy(buf[0], "G_unexplored"); - } else if (glyph_is_warning(glyph)) { - j = glyph - GLYPH_WARNING_OFF; - Snprintf(buf[0], sizeof buf[0], "G_%s%d", "warning", j); - } - if (memchr(buf[0], '\0', sizeof buf[0]) == NULL) - panic("parse_id: buf[0] overflowed"); - if (!skip_this_one) { - fix_glyphname(buf[0]+2); - if (dump_ids) { - Fprintf(fp, "(%04d) %s\n", glyph, buf[0]); - } else if (filling_cache) { - add_glyph_to_cache(glyph, buf[0]); - } else if (id) { - if (!strcmpi(id, buf[0])) { - findwhat->findtype = find_glyph; - findwhat->val = glyph; - findwhat->loadsyms_offset = 0; - return 1; - } - } - } - } - } /* not glyphid_cache */ - } else if (is_S) { - /* cmap entries */ - for (i = 0; i < cmap_count; ++i) { - if (!strcmpi(loadsyms[i + cmap_offset].name + 2, id + 2)) { - findwhat->findtype = find_cmap; - findwhat->val = i; - findwhat->loadsyms_offset = i + cmap_offset; - return 1; - } - } - /* objclass entries */ - for (i = 0; i < oc_count; ++i) { - if (!strcmpi(loadsyms[i + oc_offset].name + 2, id + 2)) { - findwhat->findtype = find_oc; - findwhat->val = i; - findwhat->loadsyms_offset = i + oc_offset; - return 1; - } - } - /* permonst entries */ - for (i = 0; i <= pm_count; ++i) { - if (!strcmpi(loadsyms[i + pm_offset].name + 2, id + 2)) { - findwhat->findtype = find_pm; - findwhat->val = i + 1; /* starts at 1 */ - findwhat->loadsyms_offset = i + pm_offset; - return 1; - } - } - } - if (dump_ids || filling_cache) - return 1; - findwhat->findtype = find_nothing; - findwhat->val = 0; - findwhat->loadsyms_offset = 0; - return 0; -} - -static struct { - int index; - uint32_t value; -} color_definitions_256[] = { - /* color values are from unnethack */ - { 16, 0x000000 }, { 17, 0x00005f }, { 18, 0x000087 }, - { 19, 0x0000af }, { 20, 0x0000d7 }, { 21, 0x0000ff }, - { 22, 0x005f00 }, { 23, 0x005f5f }, { 24, 0x005f87 }, - { 25, 0x005faf }, { 26, 0x005fd7 }, { 27, 0x005fff }, - { 28, 0x008700 }, { 29, 0x00875f }, { 30, 0x008787 }, - { 31, 0x0087af }, { 32, 0x0087d7 }, { 33, 0x0087ff }, - { 34, 0x00af00 }, { 35, 0x00af5f }, { 36, 0x00af87 }, - { 37, 0x00afaf }, { 38, 0x00afd7 }, { 39, 0x00afff }, - { 40, 0x00d700 }, { 41, 0x00d75f }, { 42, 0x00d787 }, - { 43, 0x00d7af }, { 44, 0x00d7d7 }, { 45, 0x00d7ff }, - { 46, 0x00ff00 }, { 47, 0x00ff5f }, { 48, 0x00ff87 }, - { 49, 0x00ffaf }, { 50, 0x00ffd7 }, { 51, 0x00ffff }, - { 52, 0x5f0000 }, { 53, 0x5f005f }, { 54, 0x5f0087 }, - { 55, 0x5f00af }, { 56, 0x5f00d7 }, { 57, 0x5f00ff }, - { 58, 0x5f5f00 }, { 59, 0x5f5f5f }, { 60, 0x5f5f87 }, - { 61, 0x5f5faf }, { 62, 0x5f5fd7 }, { 63, 0x5f5fff }, - { 64, 0x5f8700 }, { 65, 0x5f875f }, { 66, 0x5f8787 }, - { 67, 0x5f87af }, { 68, 0x5f87d7 }, { 69, 0x5f87ff }, - { 70, 0x5faf00 }, { 71, 0x5faf5f }, { 72, 0x5faf87 }, - { 73, 0x5fafaf }, { 74, 0x5fafd7 }, { 75, 0x5fafff }, - { 76, 0x5fd700 }, { 77, 0x5fd75f }, { 78, 0x5fd787 }, - { 79, 0x5fd7af }, { 80, 0x5fd7d7 }, { 81, 0x5fd7ff }, - { 82, 0x5fff00 }, { 83, 0x5fff5f }, { 84, 0x5fff87 }, - { 85, 0x5fffaf }, { 86, 0x5fffd7 }, { 87, 0x5fffff }, - { 88, 0x870000 }, { 89, 0x87005f }, { 90, 0x870087 }, - { 91, 0x8700af }, { 92, 0x8700d7 }, { 93, 0x8700ff }, - { 94, 0x875f00 }, { 95, 0x875f5f }, { 96, 0x875f87 }, - { 97, 0x875faf }, { 98, 0x875fd7 }, { 99, 0x875fff }, - { 100, 0x878700 }, { 101, 0x87875f }, { 102, 0x878787 }, - { 103, 0x8787af }, { 104, 0x8787d7 }, { 105, 0x8787ff }, - { 106, 0x87af00 }, { 107, 0x87af5f }, { 108, 0x87af87 }, - { 109, 0x87afaf }, { 110, 0x87afd7 }, { 111, 0x87afff }, - { 112, 0x87d700 }, { 113, 0x87d75f }, { 114, 0x87d787 }, - { 115, 0x87d7af }, { 116, 0x87d7d7 }, { 117, 0x87d7ff }, - { 118, 0x87ff00 }, { 119, 0x87ff5f }, { 120, 0x87ff87 }, - { 121, 0x87ffaf }, { 122, 0x87ffd7 }, { 123, 0x87ffff }, - { 124, 0xaf0000 }, { 125, 0xaf005f }, { 126, 0xaf0087 }, - { 127, 0xaf00af }, { 128, 0xaf00d7 }, { 129, 0xaf00ff }, - { 130, 0xaf5f00 }, { 131, 0xaf5f5f }, { 132, 0xaf5f87 }, - { 133, 0xaf5faf }, { 134, 0xaf5fd7 }, { 135, 0xaf5fff }, - { 136, 0xaf8700 }, { 137, 0xaf875f }, { 138, 0xaf8787 }, - { 139, 0xaf87af }, { 140, 0xaf87d7 }, { 141, 0xaf87ff }, - { 142, 0xafaf00 }, { 143, 0xafaf5f }, { 144, 0xafaf87 }, - { 145, 0xafafaf }, { 146, 0xafafd7 }, { 147, 0xafafff }, - { 148, 0xafd700 }, { 149, 0xafd75f }, { 150, 0xafd787 }, - { 151, 0xafd7af }, { 152, 0xafd7d7 }, { 153, 0xafd7ff }, - { 154, 0xafff00 }, { 155, 0xafff5f }, { 156, 0xafff87 }, - { 157, 0xafffaf }, { 158, 0xafffd7 }, { 159, 0xafffff }, - { 160, 0xd70000 }, { 161, 0xd7005f }, { 162, 0xd70087 }, - { 163, 0xd700af }, { 164, 0xd700d7 }, { 165, 0xd700ff }, - { 166, 0xd75f00 }, { 167, 0xd75f5f }, { 168, 0xd75f87 }, - { 169, 0xd75faf }, { 170, 0xd75fd7 }, { 171, 0xd75fff }, - { 172, 0xd78700 }, { 173, 0xd7875f }, { 174, 0xd78787 }, - { 175, 0xd787af }, { 176, 0xd787d7 }, { 177, 0xd787ff }, - { 178, 0xd7af00 }, { 179, 0xd7af5f }, { 180, 0xd7af87 }, - { 181, 0xd7afaf }, { 182, 0xd7afd7 }, { 183, 0xd7afff }, - { 184, 0xd7d700 }, { 185, 0xd7d75f }, { 186, 0xd7d787 }, - { 187, 0xd7d7af }, { 188, 0xd7d7d7 }, { 189, 0xd7d7ff }, - { 190, 0xd7ff00 }, { 191, 0xd7ff5f }, { 192, 0xd7ff87 }, - { 193, 0xd7ffaf }, { 194, 0xd7ffd7 }, { 195, 0xd7ffff }, - { 196, 0xff0000 }, { 197, 0xff005f }, { 198, 0xff0087 }, - { 199, 0xff00af }, { 200, 0xff00d7 }, { 201, 0xff00ff }, - { 202, 0xff5f00 }, { 203, 0xff5f5f }, { 204, 0xff5f87 }, - { 205, 0xff5faf }, { 206, 0xff5fd7 }, { 207, 0xff5fff }, - { 208, 0xff8700 }, { 209, 0xff875f }, { 210, 0xff8787 }, - { 211, 0xff87af }, { 212, 0xff87d7 }, { 213, 0xff87ff }, - { 214, 0xffaf00 }, { 215, 0xffaf5f }, { 216, 0xffaf87 }, - { 217, 0xffafaf }, { 218, 0xffafd7 }, { 219, 0xffafff }, - { 220, 0xffd700 }, { 221, 0xffd75f }, { 222, 0xffd787 }, - { 223, 0xffd7af }, { 224, 0xffd7d7 }, { 225, 0xffd7ff }, - { 226, 0xffff00 }, { 227, 0xffff5f }, { 228, 0xffff87 }, - { 229, 0xffffaf }, { 230, 0xffffd7 }, { 231, 0xffffff }, - { 232, 0x080808 }, { 233, 0x121212 }, { 234, 0x1c1c1c }, - { 235, 0x262626 }, { 236, 0x303030 }, { 237, 0x3a3a3a }, - { 238, 0x444444 }, { 239, 0x4e4e4e }, { 240, 0x585858 }, - { 241, 0x626262 }, { 242, 0x6c6c6c }, { 243, 0x767676 }, - { 244, 0x808080 }, { 245, 0x8a8a8a }, { 246, 0x949494 }, - { 247, 0x9e9e9e }, { 248, 0xa8a8a8 }, { 249, 0xb2b2b2 }, - { 250, 0xbcbcbc }, { 251, 0xc6c6c6 }, { 252, 0xd0d0d0 }, - { 253, 0xdadada }, { 254, 0xe4e4e4 }, { 255, 0xeeeeee }, -}; - -/** Calculate the color distance between two colors. - * - * Algorithm taken from UnNetHack which took it from - * https://www.compuphase.com/cmetric.htm - **/ - -staticfn int -color_distance(uint32_t rgb1, uint32_t rgb2) -{ - int r1 = (rgb1 >> 16) & 0xFF; - int g1 = (rgb1 >> 8) & 0xFF; - int b1 = (rgb1) & 0xFF; - int r2 = (rgb2 >> 16) & 0xFF; - int g2 = (rgb2 >> 8) & 0xFF; - int b2 = (rgb2) & 0xFF; - - int rmean = (r1 + r2) / 2; - int r = r1 - r2; - int g = g1 - g2; - int b = b1 - b2; - return ((((512 + rmean) * r * r) >> 8) + 4 * g * g - + (((767 - rmean) * b * b) >> 8)); -} - -boolean -closest_color(uint32_t lcolor, uint32_t *closecolor, int *clridx) -{ - int i, color_index = -1, similar = INT_MAX, current; - boolean retbool = FALSE; - - for (i = 0; i < SIZE(color_definitions_256); i++) { - /* look for an exact match */ - if (lcolor == color_definitions_256[i].value) { - color_index = i; - break; - } - /* find a close color match */ - current = color_distance(lcolor, color_definitions_256[i].value); - if (current < similar) { - color_index = i; - similar = current; - } - } - if (closecolor && clridx && color_index >= 0) { - *closecolor = color_definitions_256[color_index].value; - *clridx = color_definitions_256[color_index].index; - retbool = TRUE; - } - return retbool; -} #endif /* ENHANCED_SYMBOLS */ -#ifdef TEST_GLYPHNAMES - -static struct { - int idx; - const char *nm1; - const char *nm2; -} cmapname[MAXPCHARS] = { -#define PCHAR_TILES -#include "defsym.h" -#undef PCHAR_TILES -}; - -staticfn int glyphs_to_unicode(const char *id, const char *unicode_val, - long clr); -staticfn int find_glyphs(const char *id); -staticfn void just_find_callback(int glyph, struct find_struct *findwhat); -staticfn void to_unicode_callback(int glyph, struct find_struct *findwhat); -staticfn struct customization_detail *find_display_urep_customization( - const char *customization_name, int glyphidx, - enum graphics_sets which_set); - -void -test_glyphnames(void) -{ - int reslt; - - reslt = find_glyphs("G_potion_of_monster_detection"); - reslt = find_glyphs("G_piletop_body_chickatrice"); - reslt = find_glyphs("G_detected_male_homunculus"); - reslt = find_glyphs("S_pool"); - reslt = find_glyphs("S_dog"); - reslt = glyphs_to_unicode("S_dog", "U+130E6", 0L); -} - -staticfn void -just_find_callback(int glyph UNUSED, struct find_struct *findwhat UNUSED) -{ - return; -} - -staticfn int -find_glyphs(const char *id) -{ - struct find_struct find_only = zero_find; - - find_only.unicode_val = 0; - find_only.callback = just_find_callback; - return glyph_find_core(id, &find_only); -} - -staticfn void -to_unicode_callback(int glyph UNUSED, struct find_struct *findwhat) -{ - int uval; -#ifdef NO_PARSING_SYMSET - glyph_map *gm = &glyphmap[glyph]; -#endif - uint8 utf8str[6]; - - if (!findwhat->unicode_val) - return; - uval = unicode_val(findwhat->unicode_val); - if (unicodeval_to_utf8str(uval, utf8str, sizeof utf8str)) { -#ifdef NO_PARSING_SYMSET - set_map_u(gm, uval, utf8str, - (findwhat->color != 0L) ? findwhat->color : 0L); -#else - -#endif - } -} - -int -glyphs_to_unicode(const char *id, const char *unicode_val, long clr) -{ - struct find_struct to_unicode = zero_find; - - to_unicode.unicode_val = unicode_val; - to_unicode.callback = to_unicode_callback; - /* if the color 0 is an actual color, as opposed to just "not set" - we set a marker bit outside the 24-bit range to indicate a - valid color value 0. That allows valid color 0, but allows a - simple checking for 0 to detect "not set". The window port that - implements the color switch, needs to either check that bit - or appropriately mask colors with 0xFFFFFF. */ - to_unicode.color = (clr == -1) ? 0L : (clr == 0L) ? nonzero_black : clr; - return glyph_find_core(id, &to_unicode); -} - -#if 0 -struct customization_detail * -find_display_urep_customization( - const char *customization_name, - int glyphidx, - enum graphics_sets which_set) -{ - struct symset_customization *gdc = &gs.sym_customizations[which_set]; - struct customization_detail *urepdetails; - - if ((gdc->custtype == custom_ureps) - || (strcmp(customization_name, gdc->customization_name) == 0)) { - urepdetails = gdc->details; - while (urepdetails) { - if (urepdetails->content.urep.glyphidx == glyphidx) - return urepdetails; - urepdetails = urepdetails->next; - } - } - return (struct customization_detail *) 0; -} -#endif -#endif /* SOME TEST STUFF */ - /* utf8map.c */ diff --git a/sys/msdos/Makefile.GCC b/sys/msdos/Makefile.GCC index 81283f7bc..52272f5d8 100644 --- a/sys/msdos/Makefile.GCC +++ b/sys/msdos/Makefile.GCC @@ -278,25 +278,25 @@ VOBJ04 = $(O)dig.o $(O)display.o $(O)do.o $(O)do_name.o $(O)do_wear VOBJ05 = $(O)dog.o $(O)dogmove.o $(O)dokick.o $(O)dothrow.o $(O)drawing.o VOBJ06 = $(O)dungeon.o $(O)eat.o $(O)end.o $(O)engrave.o $(O)exper.o VOBJ07 = $(O)explode.o $(O)extralev.o $(O)files.o $(O)fountain.o $(O)getpos.o -VOBJ08 = $(O)getline.o $(O)hack.o $(O)hacklib.o $(O)insight.o $(O)invent.o -VOBJ09 = $(O)isaac64.o $(O)lock.o $(O)mail.o $(O)main.o $(O)makemon.o -VOBJ10 = $(O)mcastu.o $(O)mdlib.o $(O)mhitm.o $(O)mhitu.o $(O)minion.o -VOBJ11 = $(O)mkmap.o $(O)mklev.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o -VOBJ12 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o $(O)mplayer.o -VOBJ13 = $(O)mthrowu.o $(O)muse.o $(O)music.o $(O)o_init.o $(O)objects.o -VOBJ14 = $(O)objnam.o $(O)options.o $(O)pickup.o $(O)pline.o $(O)polyself.o -VOBJ15 = $(O)potion.o $(O)quest.o $(O)questpgr.o $(O)pager.o $(O)pray.o -VOBJ16 = $(O)priest.o $(O)read.o $(O)rect.o $(O)region.o $(O)report.o -VOBJ17 = $(O)restore.o $(O)rip.o $(O)rnd.o $(O)role.o $(O)rumors.o -VOBJ18 = $(O)save.o $(O)selvar.o $(O)sfstruct.o $(O)shk.o $(O)shknam.o -VOBJ19 = $(O)sit.o $(O)sounds.o $(O)sp_lev.o $(O)spell.o $(O)stairs.o -VOBJ20 = $(O)steal.o $(O)steed.o $(O)symbols.o $(O)sys.o $(O)teleport.o -VOBJ21 = $(O)strutil.o $(O)termcap.o $(O)timeout.o $(O)topl.o $(O)topten.o -VOBJ22 = $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)utf8map.o $(O)vault.o -VOBJ23 = $(O)track.o $(O)vision.o $(O)weapon.o $(O)were.o $(O)wield.o -VOBJ24 = $(O)windows.o $(O)wintty.o $(O)wizard.o $(O)wizcmds.o $(O)worm.o -VOBJ25 = $(O)worn.o $(O)write.o $(O)zap.o $(O)light.o $(O)dlb.o -VOBJ26 = $(REGEX) +VOBJ08 = $(O)glyphs.o $(O)getline.o $(O)hack.o $(O)hacklib.o $(O)insight.o +VOBJ09 = $(O)invent.o $(O)isaac64.o $(O)lock.o $(O)mail.o $(O)main.o +VOBJ10 = $(O)makemon.o $(O)mcastu.o $(O)mdlib.o $(O)mhitm.o $(O)mhitu.o +VOBJ11 = $(O)minion.o $(O)mkmap.o $(O)mklev.o $(O)mkmaze.o $(O)mkobj.o +VOBJ12 = $(O)mkroom.o $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o +VOBJ13 = $(O)mplayer.o $(O)mthrowu.o $(O)muse.o $(O)music.o $(O)o_init.o +VOBJ14 = $(O)objects.o $(O)objnam.o $(O)options.o $(O)pickup.o $(O)pline.o +VOBJ15 = $(O)polyself.o $(O)potion.o $(O)quest.o $(O)questpgr.o $(O)pager.o +VOBJ16 = $(O)pray.o $(O)priest.o $(O)read.o $(O)rect.o $(O)region.o +VOBJ17 = $(O)report.o $(O)restore.o $(O)rip.o $(O)rnd.o $(O)role.o +VOBJ18 = $(O)rumors.o $(O)save.o $(O)selvar.o $(O)sfstruct.o $(O)shk.o +VOBJ19 = $(O)shknam.o $(O)sit.o $(O)sounds.o $(O)sp_lev.o $(O)spell.o +VOBJ20 = $(O)stairs.o $(O)steal.o $(O)steed.o $(O)symbols.o $(O)sys.o +VOBJ21 = $(O)teleport.o $(O)strutil.o $(O)termcap.o $(O)timeout.o $(O)topl.o +VOBJ22 = $(O)topten.o $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)utf8map.o +VOBJ23 = $(O)vault.o $(O)track.o $(O)vision.o $(O)weapon.o $(O)were.o +VOBJ24 = $(O)wield.o $(O)windows.o $(O)wintty.o $(O)wizard.o $(O)wizcmds.o +VOBJ25 = $(O)worm.o $(O)worn.o $(O)write.o $(O)zap.o $(O)light.o +VOBJ26 = $(O)dlb.o $(REGEX) SOBJ = $(O)msdos.o $(O)pcsys.o $(O)tty.o $(O)unix.o \ $(O)video.o $(O)vidtxt.o $(O)pckeys.o diff --git a/sys/msdos/video.c b/sys/msdos/video.c index 3b1d20934..3a883e428 100644 --- a/sys/msdos/video.c +++ b/sys/msdos/video.c @@ -483,7 +483,7 @@ tty_start_screen(void) void gr_init(void) { - windowprocs.wincap2 &= ~WC2_U_24BITCOLOR; + windowprocs.wincap2 &= ~WC2_EXTRACOLORS; #ifdef SCREEN_VGA if (iflags.usevga) { vga_Init(); diff --git a/sys/msdos/vidvesa.c b/sys/msdos/vidvesa.c index 330ced994..d7bb341b6 100644 --- a/sys/msdos/vidvesa.c +++ b/sys/msdos/vidvesa.c @@ -1102,11 +1102,9 @@ vesa_Init(void) vesa_SwitchMode(vesa_mode); vesa_SetViewPort(); windowprocs.win_cliparound = vesa_cliparound; -#ifdef ENHANCED_SYMBOLS if (vesa_pixel_size > 8) { - windowprocs.wincap2 |= WC2_U_24BITCOLOR; + windowprocs.wincap2 |= WC2_EXTRACOLORS; } -#endif #ifdef TILES_IN_GLYPHMAP paletteptr = get_palette(); iflags.tile_view = TRUE; diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 9a31be3c5..e45bb2e71 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -510,7 +510,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c \ drawing.c dungeon.c eat.c end.c engrave.c exper.c explode.c \ extralev.c files.c fountain.c hack.c hacklib.c \ - getpos.c insight.c invent.c isaac64.c light.c \ + getpos.c glyphs.c insight.c invent.c isaac64.c light.c \ lock.c mail.c makemon.c mcastu.c mdlib.c mhitm.c \ mhitu.c minion.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c \ mondata.c monmove.c monst.c mplayer.c mthrowu.c muse.c music.c \ @@ -581,8 +581,8 @@ HOSTOBJ = $(FIRSTOBJ) alloc.o drawing.o HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \ $(TARGETPFX)apply.o $(TARGETPFX)artifact.o $(TARGETPFX)attrib.o \ $(TARGETPFX)ball.o $(TARGETPFX)bones.o $(TARGETPFX)botl.o \ - $(TARGETPFX)calendar.o \ - $(TARGETPFX)cmd.o $(TARGETPFX)coloratt.o $(TARGETPFX)dbridge.o $(TARGETPFX)decl.o \ + $(TARGETPFX)calendar.o $(TARGETPFX)cmd.o \ + $(TARGETPFX)coloratt.o $(TARGETPFX)dbridge.o $(TARGETPFX)decl.o \ $(TARGETPFX)detect.o $(TARGETPFX)dig.o $(TARGETPFX)display.o \ $(TARGETPFX)dlb.o $(TARGETPFX)do.o $(TARGETPFX)do_name.o \ $(TARGETPFX)do_wear.o $(TARGETPFX)dog.o $(TARGETPFX)dogmove.o \ @@ -590,10 +590,10 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \ $(TARGETPFX)dungeon.o $(TARGETPFX)eat.o $(TARGETPFX)end.o \ $(TARGETPFX)engrave.o $(TARGETPFX)exper.o $(TARGETPFX)explode.o \ $(TARGETPFX)extralev.o $(TARGETPFX)files.o $(TARGETPFX)fountain.o \ - $(TARGETPFX)getpos.o $(TARGETPFX)hack.o $(TARGETPFX)insight.o \ - $(TARGETPFX)invent.o $(TARGETPFX)isaac64.o $(TARGETPFX)light.o \ - $(TARGETPFX)lock.o $(TARGETPFX)mail.o $(TARGETPFX)makemon.o \ - $(TARGETPFX)mcastu.o $(TARGETPFX)mdlib.o \ + $(TARGETPFX)getpos.o $(TARGETPFX)glyphs.o $(TARGETPFX)hack.o \ + $(TARGETPFX)insight.o $(TARGETPFX)invent.o $(TARGETPFX)isaac64.o \ + $(TARGETPFX)light.o $(TARGETPFX)lock.o $(TARGETPFX)mail.o \ + $(TARGETPFX)makemon.o $(TARGETPFX)mcastu.o $(TARGETPFX)mdlib.o \ $(TARGETPFX)mhitm.o $(TARGETPFX)mhitu.o $(TARGETPFX)minion.o \ $(TARGETPFX)mklev.o $(TARGETPFX)mkmap.o $(TARGETPFX)mkmaze.o \ $(TARGETPFX)mkobj.o $(TARGETPFX)mkroom.o $(TARGETPFX)mon.o \ @@ -611,17 +611,18 @@ HOBJ = $(TARGETPFX)allmain.o $(TARGETPFX)alloc.o \ $(TARGETPFX)role.o $(TARGETPFX)rumors.o $(TARGETPFX)save.o \ $(TARGETPFX)selvar.o $(TARGETPFX)sfstruct.o \ $(TARGETPFX)shk.o $(TARGETPFX)shknam.o $(TARGETPFX)sit.o \ - $(TARGETPFX)sounds.o $(TARGETPFX)sp_lev.o $(TARGETPFX)spell.o $(TARGETPFX)stairs.o \ - $(TARGETPFX)symbols.o $(TARGETPFX)sys.o $(TARGETPFX)steal.o \ - $(TARGETPFX)steed.o $(TARGETPFX)strutil.o $(TARGETPFX)teleport.o \ - $(TARGETPFX)timeout.o $(TARGETPFX)topten.o $(TARGETPFX)track.o $(TARGETPFX)trap.o \ - $(TARGETPFX)u_init.o $(TARGETPFX)uhitm.o $(TARGETPFX)utf8map.o \ - $(TARGETPFX)vault.o $(TARGETPFX)vision.o $(TARGETPFX)weapon.o \ + $(TARGETPFX)sounds.o $(TARGETPFX)sp_lev.o $(TARGETPFX)spell.o \ + $(TARGETPFX)stairs.o $(TARGETPFX)symbols.o $(TARGETPFX)sys.o \ + $(TARGETPFX)steal.o $(TARGETPFX)steed.o $(TARGETPFX)strutil.o \ + $(TARGETPFX)teleport.o $(TARGETPFX)timeout.o $(TARGETPFX)topten.o \ + $(TARGETPFX)track.o $(TARGETPFX)trap.o $(TARGETPFX)u_init.o \ + $(TARGETPFX)uhitm.o $(TARGETPFX)utf8map.o $(TARGETPFX)vault.o \ + $(TARGETPFX)vision.o $(TARGETPFX)weapon.o \ $(TARGETPFX)were.o $(TARGETPFX)wield.o $(TARGETPFX)windows.o \ - $(TARGETPFX)wizard.o $(TARGETPFX)wizcmds.o $(TARGETPFX)worm.o $(TARGETPFX)worn.o \ - $(TARGETPFX)write.o $(TARGETPFX)zap.o \ + $(TARGETPFX)wizard.o $(TARGETPFX)wizcmds.o $(TARGETPFX)worm.o \ + $(TARGETPFX)worn.o $(TARGETPFX)write.o $(TARGETPFX)zap.o \ $(REGEXOBJ) $(RANDOBJ) $(SYSOBJ) $(WINOBJ) $(HINTOBJ) $(SNDLIBOBJ) \ - $(TARGETPFX)version.o + $(TARGETPFX)version.o DATE_O = $(TARGETPFX)date.o @@ -1154,6 +1155,7 @@ $(TARGETPFX)files.o: files.c $(HACK_H) ../include/dlb.h ../include/wintty.h \ #zlib.h $(TARGETPFX)fountain.o: fountain.c $(HACK_H) $(TARGETPFX)getpos.o: getpos.c $(HACK_H) +$(TARGETPFX)glyphs.o: glyphs.c $(HACK_H) $(TARGETPFX)hack.o: hack.c $(HACK_H) $(TARGETPFX)hacklib.o: hacklib.c $(HACK_H) $(TARGETPFX)insight.o: insight.c $(HACK_H) diff --git a/sys/vms/Makefile.src b/sys/vms/Makefile.src index 8ccd977a3..df797c38c 100644 --- a/sys/vms/Makefile.src +++ b/sys/vms/Makefile.src @@ -150,8 +150,8 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ botl.c calendar.c cmd.c coloratt.c dbridge.c decl.c detect.c dig.c \ display.c dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c \ dothrow.c drawing.c dungeon.c eat.c end.c engrave.c exper.c \ - explode.c extralev.c files.c fountain.c getpos.c hack.c hacklib.c \ - insight.c invent.c light.c lock.c \ + explode.c extralev.c files.c fountain.c getpos.c glyphs.c hack.c \ + hacklib.c insight.c invent.c light.c lock.c \ mail.c makemon.c mcastu.c mhitm.c mhitu.c minion.c \ mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c mondata.c \ monmove.c monst.c mplayer.c mthrowu.c muse.c music.c o_init.c \ @@ -196,8 +196,8 @@ HOBJ1 = allmain.obj,alloc.obj,apply.obj,artifact.obj,attrib.obj, \ do.obj,do_name.obj,do_wear.obj HOBJ2 = dog.obj,dogmove.obj,dokick.obj,dothrow.obj,drawing.obj, \ dungeon.obj,eat.obj,end.obj,engrave.obj,exper.obj,explode.obj, \ - extralev.obj,files.obj,fountain.obj,getpos.obj,hack.obj,hacklib.obj, \ - insight.obj,invent.obj + extralev.obj,files.obj,fountain.obj,getpos.obj,glyphs.obj,hack.obj, \ + hacklib.obj,insight.obj,invent.obj HOBJ3 = light.obj,lock.obj,mail.obj,makemon.obj,mcastu.obj, \ mhitm.obj,mhitu.obj,minion.obj,mklev.obj,mkmap.obj,mkmaze.obj, \ mkobj.obj,mkroom.obj,mon.obj,mondata.obj,monmove.obj diff --git a/sys/vms/Makefile_src.vms b/sys/vms/Makefile_src.vms index 1dac50b89..b5a4d793e 100644 --- a/sys/vms/Makefile_src.vms +++ b/sys/vms/Makefile_src.vms @@ -118,8 +118,8 @@ HACKFILES := allmain alloc apply artifact attrib ball bones \ botl calendar cmd coloratt dbridge decl detect dig display dlb do \ do_name do_wear dog dogmove dokick dothrow drawing \ dungeon eat end engrave exper explode extralev \ - files fountain getpos hack hacklib insight invent isaac64 light \ - lock mail makemon mcastu mdlib mhitm mhitu minion mklev \ + files fountain getpos glyphs hack hacklib insight invent isaac64 \ + light lock mail makemon mcastu mdlib mhitm mhitu minion mklev \ mkmap mkmaze mkobj mkroom mon \ mondata monmove monst mplayer mthrowu muse music \ nhlua nhlsel nhlobj objnam o_init objects \ @@ -700,7 +700,9 @@ $(TARGETPFX)attrib.obj: attrib.c $(HACK_H) $(TARGETPFX)ball.obj: ball.c $(HACK_H) $(TARGETPFX)bones.obj: bones.c $(HACK_H) $(TARGETPFX)botl.obj: botl.c $(HACK_H) +$(TARGETPFX)calendar.obj: calendar.c $(HACK_H) $(TARGETPFX)cmd.obj: cmd.c $(HACK_H) $(INCL)func_tab.h +$(TARGETPFX)coloratt.obj: coloratt.c $(HACK_H) $(TARGETPFX)dbridge.obj: dbridge.c $(HACK_H) $(TARGETPFX)decl.obj: decl.c $(HACK_H) $(TARGETPFX)detect.obj: detect.c $(HACK_H) $(INCL)artifact.h @@ -728,6 +730,8 @@ $(TARGETPFX)extralev.obj: extralev.c $(HACK_H) $(TARGETPFX)files.obj: files.c $(HACK_H) $(INCL)dlb.h $(INCL)wintty.h \ #zlib.h $(TARGETPFX)fountain.obj: fountain.c $(HACK_H) +$(TARGETPFX)getpos.obj: getpos.c $(HACK_H) +$(TARGETPFX)glyphs.obj: glyphs.c $(HACK_H) $(TARGETPFX)hack.obj: hack.c $(HACK_H) $(TARGETPFX)hacklib.obj: hacklib.c $(HACK_H) $(TARGETPFX)insight.obj: insight.c $(HACK_H) @@ -791,12 +795,14 @@ $(TARGETPFX)questpgr.obj: questpgr.c $(HACK_H) $(INCL)dlb.h \ $(TARGETPFX)read.obj: read.c $(HACK_H) $(TARGETPFX)rect.obj: rect.c $(HACK_H) $(TARGETPFX)region.obj: region.c $(HACK_H) +$(TARGETPFX)report.obj: report.c $(HACK_H) $(TARGETPFX)restore.obj: restore.c $(HACK_H) $(INCL)tcap.h $(TARGETPFX)rip.obj: rip.c $(HACK_H) $(TARGETPFX)rnd.obj: rnd.c $(HACK_H) $(INCL)isaac64.h $(TARGETPFX)role.obj: role.c $(HACK_H) $(TARGETPFX)rumors.obj: rumors.c $(HACK_H) $(INCL)dlb.h $(TARGETPFX)save.obj: save.c $(HACK_H) +$(TARGETPFX)selvar.obj: selvar.c $(HACK_H) $(TARGETPFX)sfstruct.obj: sfstruct.c $(HACK_H) $(TARGETPFX)shk.obj: shk.c $(HACK_H) $(TARGETPFX)shknam.obj: shknam.c $(HACK_H) @@ -804,6 +810,7 @@ $(TARGETPFX)sit.obj: sit.c $(HACK_H) $(INCL)artifact.h $(TARGETPFX)sounds.obj: sounds.c $(HACK_H) $(TARGETPFX)sp_lev.obj: sp_lev.c $(HACK_H) $(INCL)sp_lev.h $(TARGETPFX)spell.obj: spell.c $(HACK_H) +$(TARGETPFX)stairs.obj: stairs.c $(HACK_H) $(TARGETPFX)steal.obj: steal.c $(HACK_H) $(TARGETPFX)steed.obj: steed.c $(HACK_H) $(TARGETPFX)symbols.obj: symbols.c $(HACK_H) $(INCL)tcap.h @@ -824,6 +831,7 @@ $(TARGETPFX)were.obj: were.c $(HACK_H) $(TARGETPFX)wield.obj: wield.c $(HACK_H) $(TARGETPFX)windows.obj: windows.c $(HACK_H) $(INCL)dlb.h $(INCL)wintty.h $(TARGETPFX)wizard.obj: wizard.c $(HACK_H) +$(TARGETPFX)wizcmds.obj: wizcmds.c $(HACK_H) $(TARGETPFX)worm.obj: worm.c $(HACK_H) $(TARGETPFX)worn.obj: worn.c $(HACK_H) $(TARGETPFX)write.obj: write.c $(HACK_H) diff --git a/sys/vms/vmsbuild.com b/sys/vms/vmsbuild.com index e7b11df52..b9f8cc721 100755 --- a/sys/vms/vmsbuild.com +++ b/sys/vms/vmsbuild.com @@ -423,7 +423,7 @@ $ gosub compile_list $ c_list = "allmain,apply,artifact,attrib,ball,bones,botl,calendar,cmd" - + ",coloratt,dbridge,dothrow,drawing,detect,dig,display,do,do_name" - + ",do_wear,dog,dogmove,dokick,dungeon,eat,end,engrave,exper,explode" - - + ",extralev,files,fountain,getpos" + + ",extralev,files,fountain,getpos,glyphs" $ gosub compile_list $ c_list = "hack,hacklib,insight,invent,light,lock,mail,makemon" - + ",mcastu,mdlib,mhitm,mhitu,minion,mklev,mkmap,mkmaze" - diff --git a/sys/windows/Makefile.mingw32 b/sys/windows/Makefile.mingw32 index 73519fa1a..473ace2f6 100644 --- a/sys/windows/Makefile.mingw32 +++ b/sys/windows/Makefile.mingw32 @@ -988,7 +988,7 @@ COREOBJS = $(addsuffix .o, allmain alloc apply artifact attrib ball bones botl \ dbridge decl detect dig display dlb do do_name do_wear \ dog dogmove dokick dothrow drawing dungeon \ eat end engrave exper explode extralev files fountain \ - getpos hack insight invent isaac64 light lock \ + getpos glyphs hack insight invent isaac64 light lock \ mail makemon mcastu mdlib mhitm mhitu minion mklev mkmap mkmaze mkobj mkroom \ mon mondata monmove monst mplayer mthrowu muse music \ nhlobj nhlsel nhlua windsound o_init objects objnam options \ diff --git a/sys/windows/Makefile.nmake b/sys/windows/Makefile.nmake index 95bf151f2..04cb692c9 100644 --- a/sys/windows/Makefile.nmake +++ b/sys/windows/Makefile.nmake @@ -509,7 +509,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ botl.c calendar.c cmd.c coloratt.c dbridge.c decl.c detect.c dig.c display.c \ dlb.c do.c do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c \ drawing.c dungeon.c eat.c end.c engrave.c exper.c explode.c \ - files.c fountain.c hack.c \ + files.c fountain.c getpos.c glyphs.c hack.c \ insight.c invent.c isaac64.c light.c \ lock.c mail.c makemon.c mcastu.c mdlib.c mhitm.c \ mhitu.c minion.c mklev.c mkmap.c mkmaze.c mkobj.c mkroom.c mon.c \ @@ -517,9 +517,9 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ nhlua.c nhlsel.c nhlobj.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ priest.c quest.c questpgr.c read.c rect.c region.c restore.c \ - rip.c rnd.c role.c rumors.c save.c sfstruct.c \ - shk.c shknam.c sit.c sounds.c \ - sp_lev.c spell.c steal.c steed.c symbols.c sys.c teleport.c \ + rip.c rnd.c role.c rumors.c save.c selvar.c sfstruct.c \ + shk.c shknam.c sit.c sounds.c sp_lev.c spell.c \ + stairs.c steal.c steed.c symbols.c sys.c teleport.c \ timeout.c topten.c track.c trap.c u_init.c uhitm.c utf8map.c \ vault.c version.c vision.c weapon.c were.c wield.c \ windows.c wizard.c worm.c worn.c write.c zap.c @@ -664,7 +664,7 @@ VTTYOBJ05 = $(OTTY)do_name.o $(OTTY)do_wear.o $(OTTY)dog.o $(OTTY)dogmove VTTYOBJ06 = $(OTTY)dothrow.o $(OTTY)drawing.o $(OTTY)dungeon.o $(OTTY)eat.o VTTYOBJ07 = $(OTTY)end.o $(OTTY)engrave.o $(OTTY)exper.o $(OTTY)explode.o VTTYOBJ08 = $(OTTY)extralev.o $(OTTY)files.o $(OTTY)fountain.o $(OTTY)getpos.o -VTTYOBJ09 = $(OTTY)hack.o $(OTTY)insight.o $(OTTY)invent.o +VTTYOBJ09 = $(OTTY)glyphs.o $(OTTY)hack.o $(OTTY)insight.o $(OTTY)invent.o VTTYOBJ10 = $(OTTY)isaac64.o $(OTTY)light.o $(OTTY)lock.o $(OTTY)mail.o VTTYOBJ11 = $(OTTY)makemon.o $(OTTY)mcastu.o $(OTTY)mhitm.o $(OTTY)mhitu.o VTTYOBJ12 = $(OTTY)minion.o $(OTTY)mklev.o $(OTTY)mkmap.o $(OTTY)mkmaze.o @@ -732,7 +732,7 @@ VGUIOBJ05 = $(OGUI)do_wear.o $(OGUI)dog.o $(OGUI)dogmove.o $(OGUI)dokick. VGUIOBJ06 = $(OGUI)dothrow.o $(OGUI)drawing.o $(OGUI)dungeon.o $(OGUI)eat.o VGUIOBJ07 = $(OGUI)end.o $(OGUI)engrave.o $(OGUI)exper.o $(OGUI)explode.o VGUIOBJ08 = $(OGUI)extralev.o $(OGUI)files.o $(OGUI)fountain.o $(OGUI)getpos.o -VGUIOBJ09 = $(OGUI)hack.o $(OGUI)insight.o $(OGUI)invent.o +VGUIOBJ09 = $(OGUI)glyphs.o $(OGUI)hack.o $(OGUI)insight.o $(OGUI)invent.o VGUIOBJ10 = $(OGUI)isaac64.o $(OGUI)light.o $(OGUI)lock.o $(OGUI)mail.o VGUIOBJ11 = $(OGUI)makemon.o $(OGUI)mcastu.o $(OGUI)mhitm.o $(OGUI)mhitu.o VGUIOBJ12 = $(OGUI)minion.o $(OGUI)mklev.o $(OGUI)mkmap.o $(OGUI)mkmaze.o @@ -2724,6 +2724,7 @@ $(OTTY)files.o: files.c $(HACK_H) $(INCL)\dlb.h \ $(INCL)\wintty.h $(OTTY)fountain.o: fountain.c $(HACK_H) $(OTTY)getpos.o: getpos.c $(HACK_H) +$(OTTY)glyphs.o: glyphs.c $(HACK_H) $(OTTY)hack.o: hack.c $(HACK_H) $(OTTY)hacklib.o: hacklib.c $(HACK_H) $(OTTY)insight.o: insight.c $(HACK_H) @@ -3097,6 +3098,7 @@ $(OGUI)files.o: files.c $(HACK_H) $(INCL)\dlb.h \ $(INCL)\wintty.h $(OGUI)fountain.o: fountain.c $(HACK_H) $(OGUI)getpos.o: getpos.c $(HACK_H) +$(OGUI)glyphs.o: glyphs.c $(HACK_H) $(OGUI)hack.o: hack.c $(HACK_H) $(OGUI)hacklib.o: hacklib.c $(HACK_H) $(OGUI)insight.o: insight.c $(HACK_H) diff --git a/sys/windows/consoletty.c b/sys/windows/consoletty.c index 39305a150..51a3079f7 100644 --- a/sys/windows/consoletty.c +++ b/sys/windows/consoletty.c @@ -170,8 +170,9 @@ struct console_t { WORD background; WORD foreground; WORD attr; - int current_nhcolor; - int current_nhbkcolor; + int32 current_nhcolor; + int32 current_nhbkcolor; + int32 current_colorflags; int current_nhattr[ATR_INVERSE+1]; COORD cursor; HANDLE hConOut; @@ -207,6 +208,7 @@ struct console_t { 0, /* attr */ 0, /* current_nhcolor */ 0, /* current_nhbkcolor */ + 0, /* current_colorflags */ {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}, {0, 0}, /* cursor */ NULL, /* hConOut*/ @@ -693,8 +695,7 @@ emit_start_24bitcolor(long color24bit) { DWORD unused, reserved; static char tcolorbuf[QBUFSZ]; - long mcolor = - (color24bit & 0xFFFFFF); /* color 0 has bit 0x1000000 set */ + uint32 mcolor = COLORVAL(color24bit); Snprintf(tcolorbuf, sizeof tcolorbuf, tcfmtstr24bit, ((mcolor >> 16) & 0xFF), /* red */ ((mcolor >> 8) & 0xFF), /* green */ @@ -1451,21 +1452,36 @@ g_pututf8(uint8 *sequence) } void -term_start_24bitcolor(struct unicode_representation *uval) +term_start_extracolor(uint32 nhcolor) { #ifdef VIRTUAL_TERMINAL_SEQUENCES - console.color24 = uval->ucolor; /* color 0 has bit 0x1000000 set */ - console.color256idx = uval->u256coloridx; + if ((nhcolor & NH_BASIC_COLOR) == 0) { + console.color24 = COLORVAL(nhcolor); /* color 0 has bit 0x1000000 set */ + console.current_colorflags = 0; + } else { #endif + /* NH_BASIC_COLOR */ + console.current_nhcolor = COLORVAL(nhcolor); + console.current_colorflags = NH_BASIC_COLOR; + term_start_color(console.current_nhcolor); +#ifdef VIRTUAL_TERMINAL_SEQUENCES + } +#endif +} + +void term_start_256color(int idx) +{ + console.color256idx = idx; } void -term_end_24bitcolor(void) +term_end_extracolor(void) { #ifdef VIRTUAL_TERMINAL_SEQUENCES console.color24 = 0L; console.color256idx = 0; #endif + console.current_nhcolor = NO_COLOR; } void diff --git a/win/Qt/qt_bind.cpp b/win/Qt/qt_bind.cpp index 7acf32ba6..e1d5324b6 100644 --- a/win/Qt/qt_bind.cpp +++ b/win/Qt/qt_bind.cpp @@ -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, diff --git a/win/Qt/qt_map.cpp b/win/Qt/qt_map.cpp index 140f1e776..81b0ff282 100644 --- a/win/Qt/qt_map.cpp +++ b/win/Qt/qt_map.cpp @@ -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); diff --git a/win/X11/winmap.c b/win/X11/winmap.c index 9ffcff8cc..bab8c1070 100644 --- a/win/X11/winmap.c +++ b/win/X11/winmap.c @@ -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) diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index eea0afc2f..6acce2576 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -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); + } /* diff --git a/win/share/tilemap.c b/win/share/tilemap.c index 36b673868..b3327d7a6 100644 --- a/win/share/tilemap.c +++ b/win/share/tilemap.c @@ -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, diff --git a/win/tty/termcap.c b/win/tty/termcap.c index ad3b42313..b5d905312 100644 --- a/win/tty/termcap.c +++ b/win/tty/termcap.c @@ -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*/ diff --git a/win/tty/wintty.c b/win/tty/wintty.c index ca69c629c..16bb94492 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -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); diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c index 5ebfcc2e0..cb14f60c1 100644 --- a/win/win32/mhmap.c +++ b/win/win32/mhmap.c @@ -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; diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 8f5f86c61..0b95886a9 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -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 */