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 */