ENHANCED_SYMBOLS

A new feature, enabled by default to maximize testing, but one which can
be disabled by commenting it out in config.h

With this, some additional information is added to the glyphmap entries
in a new optional substructure called u with these fields:
    ucolor          RGB color for use with truecolor terminals/platforms.
                    A ucolor value of zero means "not set." The actual
                    rgb value of 0 has the 0x1000000 bit set.
    u256coloridx    256 color index value for use with 256 color
                    terminals, the closest color match to ucolor.
    utf8str         Custom representation via utf-8 string (can be null).

There is a new symset included in the symbols file, called enhanced1.

Some initial code has been added to parse individual
OPTIONS=glyph:glyphid/R-G-B entries in the config file.

The glyphid can, in theory, either be an individual glyph (G_* glyphid)
for a single glyph, or it can be an existing symbol S_ value
(monster, object, or cmap symbol) to store the custom representation for
all the glyphs that match that symbol.

Examples:
   OPTIONS=glyph:G_fountain/U+03A8/0-150-255

(Your platform/terminal font needs to be able to include/display the
character, of course.)

The NetHack core code does parsing and storing the customized
entries, and adding them to the glyphmap data structure.

Any window port can utilize the additional information in the glyphinfo
that is passed to them, once code is added to do so.

Also, consolidate some symbol-related code into symbols.c, and remove it from
files.c and options.c
This commit is contained in:
nhmall
2022-05-07 10:25:13 -04:00
parent 132e1d433a
commit cb0c21e91d
50 changed files with 3072 additions and 1242 deletions

View File

@@ -829,7 +829,10 @@ static const struct early_opt earlyopts[] = {
{ARG_SHOWPATHS, "showpaths", 9, FALSE},
#ifndef NODUMPENUMS
{ARG_DUMPENUMS, "dumpenums", 9, FALSE},
#ifdef ENHANCED_SYMBOLS
{ARG_DUMPGLYPHIDS, "dumpglyphids", 12, FALSE},
#endif
#endif /* NODUMPENUMS */
#ifdef WIN32
{ARG_WINDOWS, "windows", 4, TRUE},
#endif
@@ -913,7 +916,13 @@ argcheck(int argc, char *argv[], enum earlyarg e_arg)
dump_enums();
return 2;
}
#ifdef ENHANCED_SYMBOLS
case ARG_DUMPGLYPHIDS: {
dump_glyphids();
return 2;
}
#endif
#endif /* NODUMPENUMS */
#ifdef WIN32
case ARG_WINDOWS: {
if (extended_opt) {
@@ -1006,6 +1015,17 @@ timet_delta(time_t etim, time_t stim) /* end and start times */
}
#ifndef NODUMPENUMS
#define DUMP_ENUMS
struct enum_dump monsdump[] = {
#include "monsters.h"
{ NUMMONS, "NUMMONS" },
};
struct enum_dump objdump[] = {
#include "objects.h"
{ NUM_OBJECTS, "NUM_OBJECTS" },
};
#undef DUMP_ENUMS
void
dump_enums(void)
{
@@ -1018,21 +1038,6 @@ dump_enums(void)
};
static const char *const titles[NUM_ENUM_DUMPS] =
{ "monnums", "objects_nums" , "misc_object_nums" };
struct enum_dump {
int val;
const char *nm;
};
#define DUMP_ENUMS
struct enum_dump monsdump[] = {
#include "monsters.h"
{ NUMMONS, "NUMMONS" },
};
struct enum_dump objdump[] = {
#include "objects.h"
{ NUM_OBJECTS, "NUM_OBJECTS" },
};
#undef DUMP_ENUMS
struct enum_dump omdump[] = {
{ LAST_GEM, "LAST_GEM" },
@@ -1058,6 +1063,14 @@ dump_enums(void)
}
raw_print("");
}
#ifdef ENHANCED_SYMBOLS
void
dump_glyphids(void)
{
dump_all_glyphids(stdout);
}
#endif /* ENHANCED_SYMBOLS */
#endif /* NODUMPENUMS */
/*allmain.c*/

View File

@@ -373,9 +373,12 @@ const struct instance_globals g_init = {
UNDEFINED_VALUES, /* nowhere */
UNDEFINED_PTR, /* gate_str */
/* drawing.c */
/* symbols.c */
DUMMY, /* symset */
0, /* currentgraphics */
#ifdef ENHANCED_SYMBOLS
DUMMY, /* symset_customizations */
#endif
0, /* currentgraphics */
DUMMY, /* showsyms */
DUMMY, /* primary_syms */
DUMMY, /* rogue_syms */

View File

@@ -1363,9 +1363,14 @@ see_traps(void)
}
}
/* glyph, ttychar, {color, symidx, glyphflags, tileidx } */
/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx },
tileidx, u } */
static glyph_info no_ginfo = {
NO_GLYPH, ' ', { NO_COLOR, 0, MG_BADXY, 0 }
NO_GLYPH, ' ', { MG_BADXY, { NO_COLOR, 0 }, 0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
};
#ifndef UNBUFFERED_GLYPHINFO
#define Glyphinfo_at(x, y, glyph) \
@@ -1379,12 +1384,17 @@ static glyph_info ginfo;
#ifdef USE_TILES
extern const glyph_info nul_glyphinfo; /* tile.c */
#else
/* glyph, ttychar, { color, symidx, glyphflags, tileidx} */
/* glyph, ttychar, { glyphflags, { sym.color, sym.symidx },
tileidx, 0} */
const glyph_info nul_glyphinfo = {
NO_GLYPH, ' ',
{ /* glyph_map */
NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X,
MG_UNEXPL, 0
MG_UNEXPL,
{ NO_COLOR, SYM_UNEXPLORED + SYM_OFF_X },
0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
};
#endif
@@ -1393,7 +1403,7 @@ const glyph_info nul_glyphinfo = {
extern glyph_map glyphmap[MAX_GLYPH]; /* from tile.c */
#else
glyph_map glyphmap[MAX_GLYPH] = {
{0, 0, 0U, 0 }
{ 0U, { 0, 0}, 0, 0 }
};
#endif
@@ -1686,7 +1696,7 @@ show_glyph(int x, int y, int glyph)
be thorough and check everything */
|| g.gbuf[y][x].glyphinfo.ttychar != glyphinfo.ttychar
|| g.gbuf[y][x].glyphinfo.gm.glyphflags != glyphinfo.gm.glyphflags
|| g.gbuf[y][x].glyphinfo.gm.color != glyphinfo.gm.color
|| g.gbuf[y][x].glyphinfo.gm.sym.color != glyphinfo.gm.sym.color
|| g.gbuf[y][x].glyphinfo.gm.tileidx != glyphinfo.gm.tileidx
#endif
|| iflags.use_background_glyph) {
@@ -1721,7 +1731,12 @@ show_glyph(int x, int y, int glyph)
static gbuf_entry nul_gbuf = {
0, /* gnew */
{ GLYPH_UNEXPLORED, (unsigned) ' ', /* glyphinfo.glyph */
{ (unsigned) NO_COLOR, 0, MG_UNEXPL, 0 } /* glyphinfo.gm */
/* glyphinfo.gm */
{ MG_UNEXPL, { (unsigned) NO_COLOR, 0 }, 0
#ifdef ENHANCED_SYMBOLS
, 0
#endif
}
}
};
@@ -1743,13 +1758,13 @@ clear_glyph_buffer(void)
#endif
#ifndef UNBUFFERED_GLYPHINFO
nul_gbuf.gnew = (giptr->ttychar != nul_gbuf.glyphinfo.ttychar
|| giptr->gm.color != nul_gbuf.glyphinfo.gm.color
|| giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color
|| giptr->gm.glyphflags
!= nul_gbuf.glyphinfo.gm.glyphflags
|| giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx)
#else
nul_gbuf.gnew = (giptr->glyphinfo.ttychar != ' '
|| giptr->gm.color != NO_COLOR
|| giptr->gm.sym.color != NO_COLOR
|| (giptr->gm.glyphflags & ~MG_UNEXPL) != 0)
#endif
? 1 : 0;
@@ -1782,12 +1797,12 @@ row_refresh(int start, int stop, int y)
#endif
#ifndef UNBUFFERED_GLYPHINFO
force = (giptr->ttychar != nul_gbuf.glyphinfo.ttychar
|| giptr->gm.color != nul_gbuf.glyphinfo.gm.color
|| giptr->gm.sym.color != nul_gbuf.glyphinfo.gm.sym.color
|| giptr->gm.glyphflags != nul_gbuf.glyphinfo.gm.glyphflags
|| giptr->gm.tileidx != nul_gbuf.glyphinfo.gm.tileidx)
#else
force = (giptr->ttychar != ' '
|| giptr->gm.color != NO_COLOR
|| giptr->gm.sym.color != NO_COLOR
|| (giptr->gm.glyphflags & ~MG_UNEXPL) != 0)
#endif
? 1 : 0;
@@ -2193,7 +2208,7 @@ map_glyphinfo(
&& glyph_is_monster(glyph));
const glyph_map *gmap = &glyphmap[glyph];
glyphinfo->gm = *gmap; /* glyphflags, symidx, color, tileidx */
glyphinfo->gm = *gmap; /* glyphflags, sym.symidx, sym.color, tileidx */
/*
* Only hero tinkering permitted on-the-fly (who).
* Unique glyphs in glyphmap[] determine everything else (what).
@@ -2210,12 +2225,12 @@ map_glyphinfo(
} else if (HAS_ROGUE_IBM_GRAPHICS
&& g.symset[g.currentgraphics].nocolor == 0) {
/* actually player should be yellow-on-gray if in corridor */
glyphinfo->gm.color = CLR_YELLOW;
glyphinfo->gm.sym.color = CLR_YELLOW;
} else if (flags.showrace) {
/* for showrace, non-human hero is displayed by the symbol of
corresponding type of monster rather than by '@' (handled
by newsym()); we change the color to same as human hero */
glyphinfo->gm.color = HI_DOMESTIC;
glyphinfo->gm.sym.color = HI_DOMESTIC;
}
#endif
/* accessibility
@@ -2227,7 +2242,7 @@ map_glyphinfo(
if ((g.glyphmap_perlevel_flags & GMAP_ROGUELEVEL)
? g.ov_rogue_syms[offset]
: g.ov_primary_syms[offset])
glyphinfo->gm.symidx = offset;
glyphinfo->gm.sym.symidx = offset;
}
glyphinfo->gm.glyphflags |= MG_HERO;
}
@@ -2235,9 +2250,9 @@ map_glyphinfo(
&& (mgflags & MG_FLAG_NOOVERRIDE) && glyph_is_pet(glyph)) {
/* one more accessiblity kludge;
turn off override symbol if caller has specfieid NOOVERRIDE */
glyphinfo->gm.symidx = mons[glyph_to_mon(glyph)].mlet + SYM_OFF_M;
glyphinfo->gm.sym.symidx = mons[glyph_to_mon(glyph)].mlet + SYM_OFF_M;
}
glyphinfo->ttychar = g.showsyms[glyphinfo->gm.symidx];
glyphinfo->ttychar = g.showsyms[glyphinfo->gm.sym.symidx];
glyphinfo->glyph = glyph;
}
@@ -2382,38 +2397,38 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
* offsets. The order is set in display.h.
*/
if ((offset = (glyph - GLYPH_NOTHING_OFF)) >= 0) {
gmap->symidx = SYM_NOTHING + SYM_OFF_X;
gmap->sym.symidx = SYM_NOTHING + SYM_OFF_X;
color = NO_COLOR;
gmap->glyphflags |= MG_NOTHING;
} else if ((offset = (glyph - GLYPH_UNEXPLORED_OFF)) >= 0) {
gmap->symidx = SYM_UNEXPLORED + SYM_OFF_X;
gmap->sym.symidx = SYM_UNEXPLORED + SYM_OFF_X;
color = NO_COLOR;
gmap->glyphflags |= MG_UNEXPL;
} else if ((offset = (glyph - GLYPH_STATUE_FEM_PILETOP_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_FEMALE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_STATUE_MALE_PILETOP_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_MALE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_BODY_PILETOP_OFF)) >= 0) {
gmap->symidx = objects[CORPSE].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[CORPSE].oc_class + SYM_OFF_O;
if (has_rogue_color)
color = CLR_RED;
else
mon_color(offset);
gmap->glyphflags |= (MG_CORPSE | MG_OBJPILE);
} else if ((offset = (glyph - GLYPH_OBJ_PILETOP_OFF)) >= 0) {
gmap->symidx = objects[offset].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[offset].oc_class + SYM_OFF_O;
if (offset == BOULDER)
gmap->symidx = SYM_BOULDER + SYM_OFF_X;
gmap->sym.symidx = SYM_BOULDER + SYM_OFF_X;
if (has_rogue_color) {
switch (objects[offset].oc_class) {
case COIN_CLASS:
@@ -2430,14 +2445,14 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
obj_color(offset);
gmap->glyphflags |= MG_OBJPILE;
} else if ((offset = (glyph - GLYPH_STATUE_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
obj_color(STATUE);
gmap->glyphflags |= (MG_STATUE | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_STATUE_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = CLR_RED;
else
@@ -2445,70 +2460,70 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
gmap->glyphflags |= (MG_STATUE | MG_MALE);
} else if ((offset = (glyph - GLYPH_WARNING_OFF))
>= 0) { /* warn flash */
gmap->symidx = offset + SYM_OFF_W;
gmap->sym.symidx = offset + SYM_OFF_W;
if (has_rogue_color)
color = NO_COLOR;
else
warn_color(offset);
} else if ((offset = (glyph - GLYPH_EXPLODE_FROSTY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_frosty);
} else if ((offset = (glyph - GLYPH_EXPLODE_FIERY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_fiery);
} else if ((offset = (glyph - GLYPH_EXPLODE_MAGICAL_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_magical);
} else if ((offset = (glyph - GLYPH_EXPLODE_WET_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_wet);
} else if ((offset = (glyph - GLYPH_EXPLODE_MUDDY_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_muddy);
} else if ((offset = (glyph - GLYPH_EXPLODE_NOXIOUS_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_noxious);
} else if ((offset = (glyph - GLYPH_EXPLODE_DARK_OFF)) >= 0) {
gmap->symidx = S_expl_tl + offset + SYM_OFF_P;
gmap->sym.symidx = S_expl_tl + offset + SYM_OFF_P;
explode_color(expl_dark);
} else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {
/* see swallow_to_glyph() in display.c */
gmap->symidx = (S_sw_tl + (offset & 0x7)) + SYM_OFF_P;
gmap->sym.symidx = (S_sw_tl + (offset & 0x7)) + SYM_OFF_P;
if (has_rogue_color)
color = NO_COLOR;
else
mon_color(offset >> 3);
} else if ((offset = (glyph - GLYPH_CMAP_C_OFF)) >= 0) {
gmap->symidx = S_digbeam + offset + SYM_OFF_P;
gmap->sym.symidx = S_digbeam + offset + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_digbeam + offset);
else
cmap_color(S_digbeam + offset);
} else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {
/* see zapdir_to_glyph() in display.c */
gmap->symidx = (S_vbeam + (offset & 0x3)) + SYM_OFF_P;
gmap->sym.symidx = (S_vbeam + (offset & 0x3)) + SYM_OFF_P;
if (has_rogue_color)
color = NO_COLOR;
else
zap_color((offset >> 2));
} else if ((offset = (glyph - GLYPH_CMAP_B_OFF)) >= 0) {
int cmap = S_grave + offset;
gmap->symidx = cmap + SYM_OFF_P;
gmap->sym.symidx = cmap + SYM_OFF_P;
cmap_color(cmap);
if (!iflags.use_color) {
/* try to provide a visible difference between water and lava
if they use the same symbol and color is disabled */
if (cmap == S_lava
&& (g.showsyms[gmap->symidx]
&& (g.showsyms[gmap->sym.symidx]
== g.showsyms[S_pool + SYM_OFF_P]
|| g.showsyms[gmap->symidx]
|| g.showsyms[gmap->sym.symidx]
== g.showsyms[S_water + SYM_OFF_P])) {
gmap->glyphflags |= MG_BW_LAVA;
/* similar for floor [what about empty doorway?] and ice */
} else if (offset == S_ice
&& (g.showsyms[gmap->symidx]
&& (g.showsyms[gmap->sym.symidx]
== g.showsyms[S_room + SYM_OFF_P]
|| g.showsyms[gmap->symidx]
|| g.showsyms[gmap->sym.symidx]
== g.showsyms[S_darkroom
+ SYM_OFF_P])) {
gmap->glyphflags |= MG_BW_ICE;
@@ -2518,14 +2533,14 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
}
} else if ((offset = (glyph - GLYPH_ALTAR_OFF)) >= 0) {
/* unaligned, chaotic, neutral, lawful, other altar */
gmap->symidx = S_altar + SYM_OFF_P;
gmap->sym.symidx = S_altar + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_altar);
else
altar_color(offset);
} else if ((offset = (glyph - GLYPH_CMAP_A_OFF)) >= 0) {
int cmap = S_ndoor + offset;
gmap->symidx = cmap + SYM_OFF_P;
gmap->sym.symidx = cmap + SYM_OFF_P;
cmap_color(cmap);
/*
* Some speciality color mappings not hardcoded in data init
@@ -2536,36 +2551,36 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* provide a visible difference if normal and lit corridor
use the same symbol */
} else if ((cmap == S_litcorr)
&& g.showsyms[gmap->symidx]
&& g.showsyms[gmap->sym.symidx]
== g.showsyms[S_corr + SYM_OFF_P]) {
color = CLR_WHITE;
#endif
}
} else if ((offset = (glyph - GLYPH_CMAP_SOKO_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(sokoban_walls);
} else if ((offset = (glyph - GLYPH_CMAP_KNOX_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(knox_walls);
} else if ((offset = (glyph - GLYPH_CMAP_GEH_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(gehennom_walls);
} else if ((offset = (glyph - GLYPH_CMAP_MINES_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
wall_color(mines_walls);
} else if ((offset = (glyph - GLYPH_CMAP_MAIN_OFF)) >= 0) {
gmap->symidx = S_vwall + offset + SYM_OFF_P;
gmap->sym.symidx = S_vwall + offset + SYM_OFF_P;
if (has_rogue_color)
color = cmap_to_roguecolor(S_vwall + offset);
else
wall_color(main_walls);
} else if ((offset = (glyph - GLYPH_CMAP_STONE_OFF)) >= 0) {
gmap->symidx = SYM_OFF_P;
gmap->sym.symidx = SYM_OFF_P;
cmap_color(S_stone);
} else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {
gmap->symidx = objects[offset].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[offset].oc_class + SYM_OFF_O;
if (offset == BOULDER)
gmap->symidx = SYM_BOULDER + SYM_OFF_X;
gmap->sym.symidx = SYM_BOULDER + SYM_OFF_X;
if (has_rogue_color) {
switch (objects[offset].oc_class) {
case COIN_CLASS:
@@ -2581,7 +2596,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
} else
obj_color(offset);
} else if ((offset = (glyph - GLYPH_RIDDEN_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
/* This currently implies that the hero is here -- monsters */
/* don't ride (yet...). Should we set it to yellow like in */
@@ -2592,21 +2607,21 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
mon_color(offset);
gmap->glyphflags |= (MG_RIDDEN | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_RIDDEN_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
mon_color(offset);
gmap->glyphflags |= (MG_RIDDEN | MG_MALE);
} else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {
gmap->symidx = objects[CORPSE].oc_class + SYM_OFF_O;
gmap->sym.symidx = objects[CORPSE].oc_class + SYM_OFF_O;
if (has_rogue_color)
color = CLR_RED;
else
mon_color(offset);
gmap->glyphflags |= MG_CORPSE;
} else if ((offset = (glyph - GLYPH_DETECT_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
@@ -2615,7 +2630,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* is_reverse = TRUE; */
gmap->glyphflags |= (MG_DETECT | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_DETECT_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
@@ -2624,28 +2639,28 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
/* is_reverse = TRUE; */
gmap->glyphflags |= (MG_DETECT | MG_MALE);
} else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) {
gmap->symidx = SYM_INVISIBLE + SYM_OFF_X;
gmap->sym.symidx = SYM_INVISIBLE + SYM_OFF_X;
if (has_rogue_color)
color = NO_COLOR;
else
invis_color(offset);
gmap->glyphflags |= MG_INVIS;
} else if ((offset = (glyph - GLYPH_PET_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
pet_color(offset);
gmap->glyphflags |= (MG_PET | MG_FEMALE);
} else if ((offset = (glyph - GLYPH_PET_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color)
color = NO_COLOR;
else
pet_color(offset);
gmap->glyphflags |= (MG_PET | MG_MALE);
} else if ((offset = (glyph - GLYPH_MON_FEM_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color) {
color = NO_COLOR;
} else {
@@ -2653,7 +2668,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
}
gmap->glyphflags |= MG_FEMALE;
} else if ((offset = (glyph - GLYPH_MON_MALE_OFF)) >= 0) {
gmap->symidx = mons[offset].mlet + SYM_OFF_M;
gmap->sym.symidx = mons[offset].mlet + SYM_OFF_M;
if (has_rogue_color) {
color = CLR_YELLOW;
} else {
@@ -2669,7 +2684,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
: g.ov_primary_syms[SYM_PET_OVERRIDE + SYM_OFF_X]);
if (g.showsyms[pet_override] != ' ')
gmap->symidx = SYM_PET_OVERRIDE + SYM_OFF_X;
gmap->sym.symidx = SYM_PET_OVERRIDE + SYM_OFF_X;
}
#ifdef TEXTCOLOR
/* Turn off color if no color defined, or rogue level w/o PC graphics.
@@ -2679,7 +2694,7 @@ reset_glyphmap(enum glyphmap_change_triggers trigger)
&& !has_rogue_color)) || !iflags.use_color)
#endif
color = NO_COLOR;
gmap->color = color;
gmap->sym.color = color;
}
}

View File

@@ -1455,7 +1455,7 @@ goto_level(
}
if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARYSET);
check_gold_symbol();
/* record this level transition as a potential seen branch unless using
* some non-standard means of transportation (level teleport).

View File

@@ -6,6 +6,7 @@
#include "color.h"
#include "rm.h"
#include "objclass.h"
#include "wintype.h"
#include "sym.h"
/* Relevant header information in rm.h, objclass.h, sym.h, defsym.h. */

View File

@@ -165,8 +165,6 @@ static void wizkit_addinv(struct obj *);
boolean proc_wizkit_line(char *buf);
void read_wizkit(void);
static FILE *fopen_sym_file(void);
boolean proc_symset_line(char *);
static void set_symhandling(char *, int);
#ifdef SELF_RECOVER
static boolean copy_bytes(int, int);
@@ -2678,7 +2676,7 @@ parse_config_line(char *origbuf)
}
switch_symbols(TRUE);
} else if (match_varname(buf, "SYMBOLS", 4)) {
if (!parsesymbols(bufp, PRIMARY)) {
if (!parsesymbols(bufp, PRIMARYSET)) {
config_error_add("Error in SYMBOLS definition '%s'", bufp);
retval = FALSE;
}
@@ -3443,7 +3441,7 @@ fopen_sym_file(void)
}
/*
* Returns 1 if the chose symset was found and loaded.
* Returns 1 if the chosen symset was found and loaded.
* 0 if it wasn't found in the sym file or other problem.
*/
int
@@ -3492,214 +3490,6 @@ read_sym_file(int which_set)
return 1;
}
boolean
proc_symset_line(char *buf)
{
return !((boolean) parse_sym_line(buf, g.symset_which_set));
}
/* returns 0 on error */
int
parse_sym_line(char *buf, int which_set)
{
int val, i;
struct symparse *symp;
char *bufp, *commentp, *altp;
if (strlen(buf) >= BUFSZ)
buf[BUFSZ - 1] = '\0';
/* convert each instance of whitespace (tabs, consecutive spaces)
into a single space; leading and trailing spaces are stripped */
mungspaces(buf);
/* remove trailing comment, if any (this isn't strictly needed for
individual symbols, and it won't matter if "X#comment" without
separating space slips through; for handling or set description,
symbol set creator is responsible for preceding '#' with a space
and that comment itself doesn't contain " #") */
if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
commentp[-1] = '\0';
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
if (!bufp) {
if (strncmpi(buf, "finish", 6) == 0) {
/* end current graphics set */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
return 1;
}
config_error_add("No \"finish\"");
return 0;
}
/* skip '=' and space which follows, if any */
++bufp;
if (*bufp == ' ')
++bufp;
symp = match_sym(buf);
if (!symp) {
config_error_add("Unknown sym keyword");
return 0;
}
if (!g.symset[which_set].name) {
/* A null symset name indicates that we're just
building a pick-list of possible symset
values from the file, so only do that */
if (symp->range == SYM_CONTROL) {
struct symsetentry *tmpsp, *lastsp;
for (lastsp = g.symset_list; lastsp; lastsp = lastsp->next)
if (!lastsp->next)
break;
switch (symp->idx) {
case 0:
tmpsp = (struct symsetentry *) alloc(sizeof *tmpsp);
tmpsp->next = (struct symsetentry *) 0;
if (!lastsp)
g.symset_list = tmpsp;
else
lastsp->next = tmpsp;
tmpsp->idx = g.symset_count++;
tmpsp->name = dupstr(bufp);
tmpsp->desc = (char *) 0;
tmpsp->handling = H_UNK;
/* initialize restriction bits */
tmpsp->nocolor = 0;
tmpsp->primary = 0;
tmpsp->rogue = 0;
break;
case 2:
/* handler type identified */
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_handling[i]; ++i)
if (!strcmpi(known_handling[i], bufp)) {
tmpsp->handling = i;
break; /* for loop */
}
break;
case 3:
/* description:something */
tmpsp = lastsp; /* most recent symset */
if (tmpsp && !tmpsp->desc)
tmpsp->desc = dupstr(bufp);
break;
case 5:
/* restrictions: xxxx*/
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_restrictions[i]; ++i) {
if (!strcmpi(known_restrictions[i], bufp)) {
switch (i) {
case 0:
tmpsp->primary = 1;
break;
case 1:
tmpsp->rogue = 1;
break;
}
break; /* while loop */
}
}
break;
}
}
return 1;
}
if (symp->range) {
if (symp->range == SYM_CONTROL) {
switch (symp->idx) {
case 0:
/* start of symset */
if (!strcmpi(bufp, g.symset[which_set].name)) {
/* matches desired one */
g.chosen_symset_start = TRUE;
/* these init_*() functions clear symset fields too */
if (which_set == ROGUESET)
init_rogue_symbols();
else if (which_set == PRIMARY)
init_primary_symbols();
}
break;
case 1:
/* finish symset */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
break;
case 2:
/* handler type identified */
if (g.chosen_symset_start)
set_symhandling(bufp, which_set);
break;
/* case 3: (description) is ignored here */
case 4: /* color:off */
if (g.chosen_symset_start) {
if (bufp) {
if (!strcmpi(bufp, "true") || !strcmpi(bufp, "yes")
|| !strcmpi(bufp, "on"))
g.symset[which_set].nocolor = 0;
else if (!strcmpi(bufp, "false")
|| !strcmpi(bufp, "no")
|| !strcmpi(bufp, "off"))
g.symset[which_set].nocolor = 1;
}
}
break;
case 5: /* restrictions: xxxx*/
if (g.chosen_symset_start) {
int n = 0;
while (known_restrictions[n]) {
if (!strcmpi(known_restrictions[n], bufp)) {
switch (n) {
case 0:
g.symset[which_set].primary = 1;
break;
case 1:
g.symset[which_set].rogue = 1;
break;
}
break; /* while loop */
}
n++;
}
}
break;
}
} else { /* !SYM_CONTROL */
val = sym_val(bufp);
if (g.chosen_symset_start) {
if (which_set == PRIMARY) {
update_primary_symset(symp, val);
} else if (which_set == ROGUESET) {
update_rogue_symset(symp, val);
}
}
}
}
return 1;
}
static void
set_symhandling(char *handling, int which_set)
{
int i = 0;
g.symset[which_set].handling = H_UNK;
while (known_handling[i]) {
if (!strcmpi(known_handling[i], handling)) {
g.symset[which_set].handling = i;
return;
}
i++;
}
}
/* ---------- END SYMSET FILE HANDLING ----------- */
/* ---------- BEGIN SCOREBOARD CREATION ----------- */

View File

@@ -1378,4 +1378,49 @@ FITSuint_(unsigned long long i, const char *file, int line){
return (unsigned)i;
}
#ifdef ENHANCED_SYMBOLS
/* Unicode routines */
int
unicodeval_to_utf8str(int uval, uint8 *buffer, size_t bufsz)
{
// static uint8 buffer[7];
uint8 *b = buffer;
if (bufsz < 5)
return 0;
/*
* Binary Hex Comments
* 0xxxxxxx 0x00..0x7F Only byte of a 1-byte character encoding
* 10xxxxxx 0x80..0xBF Continuation byte : one of 1-3 bytes following
* first 110xxxxx 0xC0..0xDF First byte of a 2-byte character encoding
* 1110xxxx 0xE0..0xEF First byte of a 3-byte character encoding
* 11110xxx 0xF0..0xF7 First byte of a 4-byte character encoding
*/
*b = '\0';
if (uval < 0x80) {
*b++ = uval;
} else if (uval < 0x800) {
*b++ = 192 + uval / 64;
*b++ = 128 + uval % 64;
} else if (uval - 0xd800u < 0x800) {
return 0;
} else if (uval < 0x10000) {
*b++ = 224 + uval / 4096;
*b++ = 128 + uval / 64 % 64;
*b++ = 128 + uval % 64;
} else if (uval < 0x110000) {
*b++ = 240 + uval / 262144;
*b++ = 128 + uval / 4096 % 64;
*b++ = 128 + uval / 64 % 64;
*b++ = 128 + uval % 64;
} else {
return 0;
}
*b = '\0'; /* NUL terminate */
return 1;
}
#endif /* ENHANCED_SYMBOLS */
/*hacklib.c*/

View File

@@ -16,6 +16,7 @@
#include "config.h"
#include "permonst.h"
#include "objclass.h"
#include "wintype.h"
#include "sym.h"
#include "artilist.h"
#include "dungeon.h"

View File

@@ -5,6 +5,7 @@
#include "config.h"
#include "permonst.h"
#include "wintype.h"
#include "sym.h"
#ifdef C

View File

@@ -505,7 +505,7 @@ parseoptions(register char *opts, boolean tinitial, boolean tfrom_file)
if (!got_match) {
/* Is it a symbol? */
if (strstr(opts, "S_") == opts && parsesymbols(opts, PRIMARY)) {
if (strstr(opts, "S_") == opts && parsesymbols(opts, PRIMARYSET)) {
switch_symbols(TRUE);
check_gold_symbol();
optresult = optn_ok;
@@ -872,7 +872,7 @@ optfn_boulder(int optidx UNUSED, int req, boolean negated UNUSED,
if (!g.opt_initial) {
nhsym sym = get_othersym(SYM_BOULDER,
Is_rogue_level(&u.uz) ? ROGUESET
: PRIMARY);
: PRIMARYSET);
if (sym)
g.showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
@@ -946,13 +946,13 @@ optfn_cursesgraphics(int optidx, int req, boolean negated,
#ifdef BACKWARD_COMPAT
if (!negated) {
/* There is no rogue level cursesgraphics-specific set */
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
} else
switch_symbols(TRUE);
}
@@ -996,13 +996,13 @@ optfn_DECgraphics(int optidx, int req, boolean negated,
#ifdef BACKWARD_COMPAT
if (!negated) {
/* There is no rogue level DECgraphics-specific set */
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
} else
switch_symbols(TRUE);
}
@@ -1390,6 +1390,43 @@ optfn_gender(int optidx, int req, boolean negated, char *opts, char *op)
return optn_ok;
}
static int
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;
}
if (req == do_set) {
/* OPTION=glyph:G_glyph/U+NNNN/r-g-b */
if (negated) {
if (op != empty_optstr) {
bad_negation("glyph", TRUE);
return optn_err;
}
}
if (op == empty_optstr)
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) {
if (!opts)
return optn_err;
Sprintf(opts, "%s", to_be_done);
return optn_ok;
}
return optn_ok;
}
static int
optfn_hilite_status(
int optidx UNUSED,
@@ -1534,13 +1571,13 @@ optfn_MACgraphics(int optidx, int req, boolean negated, char *opts, char *op)
if (req == do_set) {
/* "MACgraphics" */
if (!negated) {
if (g.symset[PRIMARY].name) {
if (g.symset[PRIMARYSET].name) {
badflag = TRUE;
} else {
g.symset[PRIMARY].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARY)) {
g.symset[PRIMARYSET].name = dupstr(allopt[optidx].name);
if (!read_sym_file(PRIMARYSET)) {
badflag = TRUE;
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(PRIMARYSET, TRUE);
}
}
if (badflag) {
@@ -3303,25 +3340,37 @@ optfn_suppress_alert(int optidx, int req, boolean negated,
return optn_ok;
}
extern const char *known_handling[]; /* symbols.c */
extern const char *known_restrictions[]; /* symbols.c */
static int
optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED,
char *opts, char *op)
optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED, char *opts,
char *op)
{
if (req == do_init) {
return optn_ok;
}
if (req == do_set) {
if (op != empty_optstr) {
g.symset[PRIMARY].name = dupstr(op);
if (!read_sym_file(PRIMARY)) {
clear_symsetentry(PRIMARY, TRUE);
g.symset[PRIMARYSET].name = dupstr(op);
if (!read_sym_file(PRIMARYSET)) {
clear_symsetentry(PRIMARYSET, TRUE);
config_error_add(
"Unable to load symbol set \"%s\" from \"%s\"", op,
SYMBOLS);
return optn_err;
} else {
switch_symbols(g.symset[PRIMARY].name != (char *) 0);
g.opt_need_redraw = TRUE;
if (g.symset[PRIMARYSET].handling) {
#ifndef ENHANCED_SYMBOLS
if (g.symset[PRIMARYSET].handling == H_UTF8) {
config_error_add("Unavailable symset handler \"%s\" for %s",
known_handling[H_UTF8], op);
load_symset("default", PRIMARYSET);
}
#endif
switch_symbols(g.symset[PRIMARYSET].name != (char *) 0);
g.opt_need_redraw = g.opt_need_glyph_reset = TRUE;
}
}
} else
return optn_err;
@@ -3331,13 +3380,32 @@ optfn_symset(int optidx UNUSED, int req, boolean negated UNUSED,
if (!opts)
return optn_err;
Sprintf(opts, "%s",
g.symset[PRIMARY].name ? g.symset[PRIMARY].name : "default");
if (g.currentgraphics == PRIMARY && g.symset[PRIMARY].name)
g.symset[PRIMARYSET].name ? g.symset[PRIMARYSET].name : "default");
if (g.currentgraphics == PRIMARYSET && g.symset[PRIMARYSET].name)
Strcat(opts, ", active");
if (g.symset[PRIMARYSET].handling) {
Sprintf(eos(opts), ", handler=%s",
known_handling[g.symset[PRIMARYSET].handling]);
}
return optn_ok;
}
if (req == do_handler) {
return handler_symset(optidx);
int reslt;
if (g.symset[PRIMARYSET].handling == H_UTF8) {
#ifdef ENHANCED_SYMBOLS
if (!glyphid_cache_status())
fill_glyphid_cache();
#endif
}
reslt = handler_symset(optidx);
if (g.symset[PRIMARYSET].handling == H_UTF8) {
#ifdef ENHANCED_SYMBOLS
if (glyphid_cache_status())
free_glyphid_cache();
#endif
}
return reslt;
}
return optn_ok;
}
@@ -5082,187 +5150,16 @@ handler_whatis_filter(void)
return optn_ok;
}
DISABLE_WARNING_FORMAT_NONLITERAL
static int
handler_symset(int optidx)
{
winid tmpwin;
anything any;
int n;
char buf[BUFSZ];
menu_item *symset_pick = (menu_item *) 0;
boolean rogueflag = (optidx == opt_roguesymset),
ready_to_switch = FALSE,
nothing_to_do = FALSE;
char *symset_name, fmtstr[20];
struct symsetentry *sl;
int res, which_set, setcount = 0, chosen = -2, defindx = 0;
int reslt;
which_set = rogueflag ? ROGUESET : PRIMARY;
g.symset_list = (struct symsetentry *) 0;
/* clear symset[].name as a flag to read_sym_file() to build list */
symset_name = g.symset[which_set].name;
g.symset[which_set].name = (char *) 0;
res = read_sym_file(which_set);
/* put symset name back */
g.symset[which_set].name = symset_name;
if (res && g.symset_list) {
int thissize,
biggest = (int) (sizeof "Default Symbols" - sizeof ""),
big_desc = 0;
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
setcount++;
/* find biggest name */
thissize = sl->name ? (int) strlen(sl->name) : 0;
if (thissize > biggest)
biggest = thissize;
thissize = sl->desc ? (int) strlen(sl->desc) : 0;
if (thissize > big_desc)
big_desc = thissize;
}
if (!setcount) {
pline("There are no appropriate %s symbol sets available.",
rogueflag ? "rogue level" : "primary");
return TRUE;
}
Sprintf(fmtstr, "%%-%ds %%s", biggest + 2);
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
any = cg.zeroany;
any.a_int = 1; /* -1 + 2 [see 'if (sl->name) {' below]*/
if (!symset_name)
defindx = any.a_int;
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
"Default Symbols",
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
if (sl->name) {
/* +2: sl->idx runs from 0 to N-1 for N symsets;
+1 because Defaults are implicitly in slot [0];
+1 again so that valid data is never 0 */
any.a_int = sl->idx + 2;
if (symset_name && !strcmpi(sl->name, symset_name))
defindx = any.a_int;
Sprintf(buf, fmtstr, sl->name, sl->desc ? sl->desc : "");
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, buf,
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
}
}
Sprintf(buf, "Select %ssymbol set:",
rogueflag ? "rogue level " : "");
end_menu(tmpwin, buf);
n = select_menu(tmpwin, PICK_ONE, &symset_pick);
if (n > 0) {
chosen = symset_pick[0].item.a_int;
/* if picking non-preselected entry yields 2, make sure
that we're going with the non-preselected one */
if (n == 2 && chosen == defindx)
chosen = symset_pick[1].item.a_int;
chosen -= 2; /* convert menu index to symset index;
* "Default symbols" have index -1 */
free((genericptr_t) symset_pick);
} else if (n == 0 && defindx > 0) {
chosen = defindx - 2;
}
destroy_nhwindow(tmpwin);
if (chosen > -1) {
/* chose an actual symset name from file */
for (sl = g.symset_list; sl; sl = sl->next)
if (sl->idx == chosen)
break;
if (sl) {
/* free the now stale attributes */
clear_symsetentry(which_set, TRUE);
/* transfer only the name of the symbol set */
g.symset[which_set].name = dupstr(sl->name);
ready_to_switch = TRUE;
}
} else if (chosen == -1) {
/* explicit selection of defaults */
/* free the now stale symset attributes */
clear_symsetentry(which_set, TRUE);
} else
nothing_to_do = TRUE;
} else if (!res) {
/* The symbols file could not be accessed */
pline("Unable to access \"%s\" file.", SYMBOLS);
return TRUE;
} else if (!g.symset_list) {
/* The symbols file was empty */
pline("There were no symbol sets found in \"%s\".", SYMBOLS);
return TRUE;
}
/* clean up */
while ((sl = g.symset_list) != 0) {
g.symset_list = sl->next;
if (sl->name)
free((genericptr_t) sl->name), sl->name = (char *) 0;
if (sl->desc)
free((genericptr_t) sl->desc), sl->desc = (char *) 0;
free((genericptr_t) sl);
}
if (nothing_to_do)
return TRUE;
/* Set default symbols and clear the handling value */
if (rogueflag)
init_rogue_symbols();
else
init_primary_symbols();
if (g.symset[which_set].name) {
/* non-default symbols */
if (read_sym_file(which_set)) {
ready_to_switch = TRUE;
} else {
clear_symsetentry(which_set, TRUE);
return TRUE;
}
}
if (ready_to_switch)
switch_symbols(TRUE);
if (Is_rogue_level(&u.uz)) {
if (rogueflag)
assign_graphics(ROGUESET);
} else if (!rogueflag)
assign_graphics(PRIMARY);
preference_update("symset");
reslt = do_symset(optidx == opt_roguesymset); /* symbols.c */
g.opt_need_redraw = TRUE;
return optidx;
return reslt;
}
RESTORE_WARNING_FORMAT_NONLITERAL
static int
handler_autopickup_exception(void)
{
@@ -5985,6 +5882,12 @@ initoptions_init(void)
memcpy(allopt, allopt_init, sizeof(allopt));
determine_ambiguities();
#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 */
@@ -6048,8 +5951,8 @@ initoptions_init(void)
*/
/* this detects the IBM-compatible console on most 386 boxes */
if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
if (!g.symset[PRIMARY].explicitly)
load_symset("IBMGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("IBMGraphics", PRIMARYSET);
if (!g.symset[ROGUESET].explicitly)
load_symset("RogueIBM", ROGUESET);
switch_symbols(TRUE);
@@ -6065,8 +5968,8 @@ initoptions_init(void)
/* [could also check "xterm" which emulates vtXXX by default] */
&& !strncmpi(opts, "vt", 2)
&& AS && AE && index(AS, '\016') && index(AE, '\017')) {
if (!g.symset[PRIMARY].explicitly)
load_symset("DECGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("DECGraphics", PRIMARYSET);
switch_symbols(TRUE);
}
#endif
@@ -6074,14 +5977,14 @@ initoptions_init(void)
#if defined(MSDOS) || defined(WIN32)
/* Use IBM defaults. Can be overridden via config file */
if (!g.symset[PRIMARY].explicitly)
load_symset("IBMGraphics_2", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("IBMGraphics_2", PRIMARYSET);
if (!g.symset[ROGUESET].explicitly)
load_symset("RogueEpyx", ROGUESET);
#endif
#ifdef MAC_GRAPHICS_ENV
if (!g.symset[PRIMARY].explicitly)
load_symset("MACGraphics", PRIMARY);
if (!g.symset[PRIMARYSET].explicitly)
load_symset("MACGraphics", PRIMARYSET);
switch_symbols(TRUE);
#endif /* MAC_GRAPHICS_ENV */
flags.menu_style = MENU_FULL;
@@ -6206,7 +6109,7 @@ initoptions_finish(void)
obj_descr[SLIME_MOLD].oc_name = "fruit";
sym = get_othersym(SYM_BOULDER,
Is_rogue_level(&u.uz) ? ROGUESET : PRIMARY);
Is_rogue_level(&u.uz) ? ROGUESET : PRIMARYSET);
if (sym)
g.showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
reglyph_darkroom();
@@ -6229,6 +6132,11 @@ initoptions_finish(void)
}
#endif
update_rest_on_space();
#ifdef ENHANCED_SYMBOLS
if (glyphid_cache_status())
free_glyphid_cache();
apply_customizations_to_symset(g.currentgraphics);
#endif
g.opt_initial = FALSE;
return;
}
@@ -8195,128 +8103,6 @@ free_autopickup_exceptions(void)
}
}
/* bundle some common usage into one easy-to-use routine */
int
load_symset(const char *s, int which_set)
{
clear_symsetentry(which_set, TRUE);
if (g.symset[which_set].name)
free((genericptr_t) g.symset[which_set].name);
g.symset[which_set].name = dupstr(s);
if (read_sym_file(which_set)) {
switch_symbols(TRUE);
} else {
clear_symsetentry(which_set, TRUE);
return 0;
}
return 1;
}
void
free_symsets(void)
{
clear_symsetentry(PRIMARY, TRUE);
clear_symsetentry(ROGUESET, TRUE);
/* symset_list is cleaned up as soon as it's used, so we shouldn't
have to anything about it here */
/* assert( symset_list == NULL ); */
}
/* Parse the value of a SYMBOLS line from a config file */
boolean
parsesymbols(register char *opts, int which_set)
{
int val;
char *op, *symname, *strval;
struct symparse *symp;
if ((op = index(opts, ',')) != 0) {
*op++ = 0;
if (!parsesymbols(op, which_set))
return FALSE;
}
/* S_sample:string */
symname = opts;
strval = index(opts, ':');
if (!strval)
strval = index(opts, '=');
if (!strval)
return FALSE;
*strval++ = '\0';
/* strip leading and trailing white space from symname and strval */
mungspaces(symname);
mungspaces(strval);
symp = match_sym(symname);
if (!symp)
return FALSE;
if (symp->range && symp->range != SYM_CONTROL) {
val = sym_val(strval);
if (which_set == ROGUESET)
update_ov_rogue_symset(symp, val);
else
update_ov_primary_symset(symp, val);
}
return TRUE;
}
struct symparse *
match_sym(char *buf)
{
int i;
struct alternate_parse {
const char *altnm;
const char *nm;
} alternates[] = {
{ "S_armour" , "S_armor" },
{ "S_explode1" , "S_expl_tl" },
{ "S_explode2" , "S_expl_tc" },
{ "S_explode3" , "S_expl_tr" },
{ "S_explode4" , "S_expl_ml" },
{ "S_explode5" , "S_expl_mc" },
{ "S_explode6" , "S_expl_mr" },
{ "S_explode7" , "S_expl_bl" },
{ "S_explode8" , "S_expl_bc" },
{ "S_explode9" , "S_expl_br" },
};
unsigned len = Strlen(buf);
const char *p = index(buf, ':'), *q = index(buf, '=');
struct symparse *sp = loadsyms;
if (!p || (q && q < p))
p = q;
if (p) {
/* note: there will be at most one space before the '='
because caller has condensed buf[] with mungspaces() */
if (p > buf && p[-1] == ' ')
p--;
len = (int) (p - buf);
}
while (sp->range) {
if ((len >= Strlen(sp->name)) && !strncmpi(buf, sp->name, len))
return sp;
sp++;
}
for (i = 0; i < SIZE(alternates); ++i) {
if ((len >= strlen(alternates[i].altnm))
&& !strncmpi(buf, alternates[i].altnm, len)) {
sp = loadsyms;
while (sp->range) {
if (!strcmp(alternates[i].nm, sp->name))
return sp;
sp++;
}
}
}
return (struct symparse *) 0;
}
int
sym_val(const char *strval) /* up to 4*BUFSZ-1 long; only first few
chars matter */

View File

@@ -15,13 +15,18 @@ void (*decgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
void (*ascgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
#endif
#ifdef WIN32
void (*ibmgraphics_mode_callback)(void) = 0; /* set in tty_start_screen() */
#endif
#ifdef CURSES_GRAPHICS
void (*cursesgraphics_mode_callback)(void) = 0;
#endif
/*
#if defined(TTY_GRAPHICS) && defined(WIN32)
void (*ibmgraphics_mode_callback)(void) = 0;
#endif
#ifdef ENHANCED_SYMBOLS
void (*utf8graphics_mode_callback)(void) = 0; /* set in tty_start_screen and
found in unixtty, windtty, etc */
#endif
/*
* Explanations of the functions found below:
*
* init_symbols()
@@ -56,7 +61,7 @@ void (*cursesgraphics_mode_callback)(void) = 0;
* If arg is ROGUESET, this places the rogue level
* symbols from g.rogue_syms into g.showsyms.
*
* If arg is PRIMARY, this places the symbols
* If arg is PRIMARYSET, this places the symbols
* from g.primary_syms into g.showsyms.
*
* update_primary_symset()
@@ -97,7 +102,7 @@ init_showsyms(void)
for (i = 0; i < WARNCOUNT; i++)
g.showsyms[i + SYM_OFF_W] = def_warnsyms[i].sym;
for (i = 0; i < MAXOTHER; i++)
g.showsyms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
g.showsyms[i + SYM_OFF_X] = get_othersym(i, PRIMARYSET);
}
/* initialize defaults for the overrides to the rogue symset */
@@ -169,9 +174,9 @@ init_primary_symbols(void)
for (i = 0; i < WARNCOUNT; i++)
g.primary_syms[i + SYM_OFF_W] = def_warnsyms[i].sym;
for (i = 0; i < MAXOTHER; i++)
g.primary_syms[i + SYM_OFF_X] = get_othersym(i, PRIMARY);
g.primary_syms[i + SYM_OFF_X] = get_othersym(i, PRIMARYSET);
clear_symsetentry(PRIMARY, FALSE);
clear_symsetentry(PRIMARYSET, FALSE);
}
/* initialize defaults for the rogue symset */
@@ -224,7 +229,7 @@ assign_graphics(int whichset)
g.currentgraphics = ROGUESET;
break;
case PRIMARY:
case PRIMARYSET:
default:
for (i = 0; i < SYM_MAX; i++)
g.showsyms[i] = g.ov_primary_syms[i] ? g.ov_primary_syms[i]
@@ -234,7 +239,7 @@ assign_graphics(int whichset)
if (iflags.grmode)
tileview(TRUE);
#endif
g.currentgraphics = PRIMARY;
g.currentgraphics = PRIMARYSET;
break;
}
reset_glyphmap(gm_symchange);
@@ -267,6 +272,14 @@ switch_symbols(int nondefault)
if (SYMHANDLING(H_CURS) && cursesgraphics_mode_callback)
(*cursesgraphics_mode_callback)();
# endif
#endif
#ifdef WIN32
if (SYMHANDLING(H_IBM) && ibmgraphics_mode_callback)
(*ibmgraphics_mode_callback)();
#endif
#ifdef ENHANCED_SYMBOLS
if (SYMHANDLING(H_UTF8) && utf8graphics_mode_callback)
(*utf8graphics_mode_callback)();
#endif
} else {
init_primary_symbols();
@@ -275,25 +288,25 @@ switch_symbols(int nondefault)
}
void
update_ov_primary_symset(struct symparse* symp, int val)
update_ov_primary_symset(const struct symparse* symp, int val)
{
g.ov_primary_syms[symp->idx] = val;
}
void
update_ov_rogue_symset(struct symparse* symp, int val)
update_ov_rogue_symset(const struct symparse* symp, int val)
{
g.ov_rogue_syms[symp->idx] = val;
}
void
update_primary_symset(struct symparse* symp, int val)
update_primary_symset(const struct symparse* symp, int val)
{
g.primary_syms[symp->idx] = val;
}
void
update_rogue_symset(struct symparse* symp, int val)
update_rogue_symset(const struct symparse* symp, int val)
{
g.rogue_syms[symp->idx] = val;
}
@@ -318,7 +331,20 @@ clear_symsetentry(int which_set, boolean name_too)
}
}
/*
boolean symset_is_compatible(enum symset_handling_types handling, unsigned long wincap2)
{
#ifdef ENHANCED_SYMBOLS
if ((handling == H_UTF8) &&
(((wincap2 & WC2_U_UTF8STR) == 0)
|| ((wincap2 & WC2_U_24BITCOLOR) == 0)))
return FALSE;
#else
nhUse(handling);
nhUse(wincap2);
#endif
return TRUE;
}
/*
* If you are adding code somewhere to be able to recognize
* particular types of symset "handling", define a
* H_XXX macro in include/sym.h and add the name
@@ -330,6 +356,7 @@ const char *known_handling[] = {
"DEC", /* H_DEC */
"CURS", /* H_CURS */
"MAC", /* H_MAC -- pre-OSX MACgraphics */
"UTF8", /* H_UTF8 */
(const char *) 0,
};
@@ -377,4 +404,677 @@ const struct symparse loadsyms[] = {
{ 0, 0, (const char *) 0 } /* fence post */
};
boolean
proc_symset_line(char *buf)
{
return !((boolean) parse_sym_line(buf, g.symset_which_set));
}
/* returns 0 on error */
int
parse_sym_line(char *buf, int which_set)
{
int val, i;
const struct symparse *symp = (struct symparse *) 0;
char *bufp, *commentp, *altp;
int glyph = NO_GLYPH;
boolean enhanced_unavailable = FALSE, is_glyph = FALSE;
if (strlen(buf) >= BUFSZ)
buf[BUFSZ - 1] = '\0';
/* convert each instance of whitespace (tabs, consecutive spaces)
into a single space; leading and trailing spaces are stripped */
mungspaces(buf);
/* remove trailing comment, if any (this isn't strictly needed for
individual symbols, and it won't matter if "X#comment" without
separating space slips through; for handling or set description,
symbol set creator is responsible for preceding '#' with a space
and that comment itself doesn't contain " #") */
if ((commentp = rindex(buf, '#')) != 0 && commentp[-1] == ' ')
commentp[-1] = '\0';
/* find the '=' or ':' */
bufp = index(buf, '=');
altp = index(buf, ':');
if (!bufp || (altp && altp < bufp))
bufp = altp;
if (!bufp) {
if (strncmpi(buf, "finish", 6) == 0) {
/* end current graphics set */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
return 1;
}
config_error_add("No \"finish\"");
return 0;
}
/* skip '=' and space which follows, if any */
++bufp;
if (*bufp == ' ')
++bufp;
symp = match_sym(buf);
if (!symp && buf[0] == 'G' && buf[1] == '_') {
#ifdef ENHANCED_SYMBOLS
is_glyph = match_glyph(buf);
#else
enhanced_unavailable = TRUE;
#endif
}
if (!symp && !is_glyph && !enhanced_unavailable) {
config_error_add("Unknown sym keyword");
return 0;
}
if (symp) {
if (!g.symset[which_set].name) {
/* A null symset name indicates that we're just
building a pick-list of possible symset
values from the file, so only do that */
if (symp->range == SYM_CONTROL) {
struct symsetentry *tmpsp, *lastsp;
for (lastsp = g.symset_list; lastsp; lastsp = lastsp->next)
if (!lastsp->next)
break;
switch (symp->idx) {
case 0:
tmpsp = (struct symsetentry *) alloc(sizeof *tmpsp);
tmpsp->next = (struct symsetentry *) 0;
if (!lastsp)
g.symset_list = tmpsp;
else
lastsp->next = tmpsp;
tmpsp->idx = g.symset_count++;
tmpsp->name = dupstr(bufp);
tmpsp->desc = (char *) 0;
tmpsp->handling = H_UNK;
/* initialize restriction bits */
tmpsp->nocolor = 0;
tmpsp->primary = 0;
tmpsp->rogue = 0;
break;
case 2:
/* handler type identified */
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_handling[i]; ++i)
if (!strcmpi(known_handling[i], bufp)) {
tmpsp->handling = i;
break; /* for loop */
}
break;
case 3:
/* description:something */
tmpsp = lastsp; /* most recent symset */
if (tmpsp && !tmpsp->desc)
tmpsp->desc = dupstr(bufp);
break;
case 5:
/* restrictions: xxxx*/
tmpsp = lastsp; /* most recent symset */
for (i = 0; known_restrictions[i]; ++i) {
if (!strcmpi(known_restrictions[i], bufp)) {
switch (i) {
case 0:
tmpsp->primary = 1;
break;
case 1:
tmpsp->rogue = 1;
break;
}
break; /* while loop */
}
}
break;
}
}
return 1;
}
if (symp->range && symp->range == SYM_CONTROL) {
switch (symp->idx) {
case 0:
/* start of symset */
if (!strcmpi(bufp, g.symset[which_set].name)) {
/* matches desired one */
g.chosen_symset_start = TRUE;
/* these init_*() functions clear symset fields too */
if (which_set == ROGUESET)
init_rogue_symbols();
else if (which_set == PRIMARYSET)
init_primary_symbols();
}
break;
case 1:
/* finish symset */
if (g.chosen_symset_start)
g.chosen_symset_end = TRUE;
g.chosen_symset_start = FALSE;
break;
case 2:
/* handler type identified */
if (g.chosen_symset_start)
set_symhandling(bufp, which_set);
break;
/* case 3: (description) is ignored here */
case 4: /* color:off */
if (g.chosen_symset_start) {
if (bufp) {
if (!strcmpi(bufp, "true") || !strcmpi(bufp, "yes")
|| !strcmpi(bufp, "on"))
g.symset[which_set].nocolor = 0;
else if (!strcmpi(bufp, "false")
|| !strcmpi(bufp, "no")
|| !strcmpi(bufp, "off"))
g.symset[which_set].nocolor = 1;
}
}
break;
case 5: /* restrictions: xxxx*/
if (g.chosen_symset_start) {
int n = 0;
while (known_restrictions[n]) {
if (!strcmpi(known_restrictions[n], bufp)) {
switch (n) {
case 0:
g.symset[which_set].primary = 1;
break;
case 1:
g.symset[which_set].rogue = 1;
break;
}
break; /* while loop */
}
n++;
}
}
break;
}
} else {
/* Not SYM_CONTROL */
if (g.symset[which_set].handling != H_UTF8) {
val = sym_val(bufp);
if (g.chosen_symset_start) {
if (which_set == PRIMARYSET) {
update_primary_symset(symp, val);
} else if (which_set == ROGUESET) {
update_rogue_symset(symp, val);
}
}
#ifdef ENHANCED_SYMBOLS
} else {
glyphrep_to_custom_map_entries(buf, &glyph);
#endif
}
}
}
#ifndef ENHANCED_SYMBOLS
nhUse(glyph);
#endif
return 1;
}
void
set_symhandling(char *handling, int which_set)
{
int i = 0;
g.symset[which_set].handling = H_UNK;
while (known_handling[i]) {
if (!strcmpi(known_handling[i], handling)) {
g.symset[which_set].handling = i;
return;
}
i++;
}
}
/* bundle some common usage into one easy-to-use routine */
int
load_symset(const char *s, int which_set)
{
clear_symsetentry(which_set, TRUE);
if (g.symset[which_set].name)
free((genericptr_t) g.symset[which_set].name);
g.symset[which_set].name = dupstr(s);
if (read_sym_file(which_set)) {
switch_symbols(TRUE);
} else {
clear_symsetentry(which_set, TRUE);
return 0;
}
return 1;
}
void
free_symsets(void)
{
clear_symsetentry(PRIMARYSET, TRUE);
clear_symsetentry(ROGUESET, TRUE);
/* symset_list is cleaned up as soon as it's used, so we shouldn't
have to anything about it here */
/* assert( symset_list == NULL ); */
}
/* Parse the value of a SYMBOLS line from a config file */
boolean
parsesymbols(register char *opts, int which_set)
{
int val;
char *op, *symname, *strval;
const struct symparse *symp;
boolean is_glyph = FALSE;
if ((op = index(opts, ',')) != 0) {
*op++ = 0;
if (!parsesymbols(op, which_set))
return FALSE;
}
/* S_sample:string */
symname = opts;
strval = index(opts, ':');
if (!strval)
strval = index(opts, '=');
if (!strval)
return FALSE;
*strval++ = '\0';
/* strip leading and trailing white space from symname and strval */
mungspaces(symname);
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) {
#ifdef ENHANCED_SYMBOLS
int glyph;
#endif
if ((g.symset[which_set].handling == H_UTF8)
|| (strval && (lowc(strval[0]) == 'u') && (strval[1] == '+'))) {
#ifdef ENHANCED_SYMBOLS
char buf[BUFSZ];
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)
update_ov_rogue_symset(symp, val);
else
update_ov_primary_symset(symp, val);
}
}
}
return TRUE;
}
const struct symparse *
match_sym(char *buf)
{
int i;
struct alternate_parse {
const char *altnm;
const char *nm;
} alternates[] = {
{ "S_armour", "S_armor" }, { "S_explode1", "S_expl_tl" },
{ "S_explode2", "S_expl_tc" }, { "S_explode3", "S_expl_tr" },
{ "S_explode4", "S_expl_ml" }, { "S_explode5", "S_expl_mc" },
{ "S_explode6", "S_expl_mr" }, { "S_explode7", "S_expl_bl" },
{ "S_explode8", "S_expl_bc" }, { "S_explode9", "S_expl_br" },
};
size_t len = strlen(buf);
const char *p = index(buf, ':'), *q = index(buf, '=');
const struct symparse *sp = loadsyms;
if (!p || (q && q < p))
p = q;
if (p) {
/* note: there will be at most one space before the '='
because caller has condensed buf[] with mungspaces() */
if (p > buf && p[-1] == ' ')
p--;
len = (int) (p - buf);
}
while (sp->range) {
if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len))
return sp;
sp++;
}
for (i = 0; i < SIZE(alternates); ++i) {
if ((len >= strlen(alternates[i].altnm))
&& !strncmpi(buf, alternates[i].altnm, len)) {
sp = loadsyms;
while (sp->range) {
if (!strcmp(alternates[i].nm, sp->name))
return sp;
sp++;
}
}
}
return (struct symparse *) 0;
}
DISABLE_WARNING_FORMAT_NONLITERAL
/*
* this is called from options.c to do the symset work.
*/
int
do_symset(boolean rogueflag)
{
winid tmpwin;
anything any;
int n;
char buf[BUFSZ];
menu_item *symset_pick = (menu_item *) 0;
boolean ready_to_switch = FALSE,
nothing_to_do = FALSE;
char *symset_name, fmtstr[20];
struct symsetentry *sl;
int res, which_set, setcount = 0, chosen = -2, defindx = 0;
which_set = rogueflag ? ROGUESET : PRIMARYSET;
g.symset_list = (struct symsetentry *) 0;
/* clear symset[].name as a flag to read_sym_file() to build list */
symset_name = g.symset[which_set].name;
g.symset[which_set].name = (char *) 0;
res = read_sym_file(which_set);
/* put symset name back */
g.symset[which_set].name = symset_name;
if (res && g.symset_list) {
int thissize,
biggest = (int) (sizeof "Default Symbols" - sizeof ""),
big_desc = 0;
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
#ifndef ENHANCED_SYMBOLS
if (sl->handling == H_UTF8)
continue;
#endif
setcount++;
/* find biggest name */
thissize = sl->name ? (int) strlen(sl->name) : 0;
if (thissize > biggest)
biggest = thissize;
thissize = sl->desc ? (int) strlen(sl->desc) : 0;
if (thissize > big_desc)
big_desc = thissize;
}
if (!setcount) {
pline("There are no appropriate %s symbol sets available.",
rogueflag ? "rogue level" : "primary");
return TRUE;
}
Sprintf(fmtstr, "%%-%ds %%s", biggest + 2);
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
any = cg.zeroany;
any.a_int = 1; /* -1 + 2 [see 'if (sl->name) {' below]*/
if (!symset_name)
defindx = any.a_int;
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0, ATR_NONE,
"Default Symbols",
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
for (sl = g.symset_list; sl; sl = sl->next) {
/* check restrictions */
if (rogueflag ? sl->primary : sl->rogue)
continue;
#ifndef MAC_GRAPHICS_ENV
if (sl->handling == H_MAC)
continue;
#endif
#ifndef ENHANCED_SYMBOLS
if (sl->handling == H_UTF8)
continue;
#endif
if (sl->name) {
/* +2: sl->idx runs from 0 to N-1 for N symsets;
+1 because Defaults are implicitly in slot [0];
+1 again so that valid data is never 0 */
any.a_int = sl->idx + 2;
if (symset_name && !strcmpi(sl->name, symset_name))
defindx = any.a_int;
Sprintf(buf, fmtstr, sl->name, sl->desc ? sl->desc : "");
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
ATR_NONE, buf,
(any.a_int == defindx) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
}
}
Sprintf(buf, "Select %ssymbol set:",
rogueflag ? "rogue level " : "");
end_menu(tmpwin, buf);
n = select_menu(tmpwin, PICK_ONE, &symset_pick);
if (n > 0) {
chosen = symset_pick[0].item.a_int;
/* if picking non-preselected entry yields 2, make sure
that we're going with the non-preselected one */
if (n == 2 && chosen == defindx)
chosen = symset_pick[1].item.a_int;
chosen -= 2; /* convert menu index to symset index;
* "Default symbols" have index -1 */
free((genericptr_t) symset_pick);
} else if (n == 0 && defindx > 0) {
chosen = defindx - 2;
}
destroy_nhwindow(tmpwin);
if (chosen > -1) {
/* chose an actual symset name from file */
for (sl = g.symset_list; sl; sl = sl->next)
if (sl->idx == chosen)
break;
if (sl) {
/* free the now stale attributes */
clear_symsetentry(which_set, TRUE);
/* transfer only the name of the symbol set */
g.symset[which_set].name = dupstr(sl->name);
ready_to_switch = TRUE;
}
} else if (chosen == -1) {
/* explicit selection of defaults */
/* free the now stale symset attributes */
clear_symsetentry(which_set, TRUE);
} else
nothing_to_do = TRUE;
} else if (!res) {
/* The symbols file could not be accessed */
pline("Unable to access \"%s\" file.", SYMBOLS);
return TRUE;
} else if (!g.symset_list) {
/* The symbols file was empty */
pline("There were no symbol sets found in \"%s\".", SYMBOLS);
return TRUE;
}
/* clean up */
while ((sl = g.symset_list) != 0) {
g.symset_list = sl->next;
if (sl->name)
free((genericptr_t) sl->name), sl->name = (char *) 0;
if (sl->desc)
free((genericptr_t) sl->desc), sl->desc = (char *) 0;
free((genericptr_t) sl);
}
if (nothing_to_do)
return TRUE;
/* Set default symbols and clear the handling value */
if (rogueflag)
init_rogue_symbols();
else
init_primary_symbols();
if (g.symset[which_set].name) {
/* non-default symbols */
if (read_sym_file(which_set)) {
ready_to_switch = TRUE;
} else {
clear_symsetentry(which_set, TRUE);
return TRUE;
}
}
if (ready_to_switch)
switch_symbols(TRUE);
if (Is_rogue_level(&u.uz)) {
if (rogueflag)
assign_graphics(ROGUESET);
} else if (!rogueflag)
assign_graphics(PRIMARYSET);
#ifdef ENHANCED_SYMBOLS
apply_customizations_to_symset(rogueflag ? ROGUESET : PRIMARYSET);
#endif
preference_update("symset");
return TRUE;
}
#ifdef ENHANCED_SYMBOLS
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_customization(
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);
void purge_custom_entries(enum graphics_sets which_set);
extern glyph_map glyphmap[MAX_GLYPH];
static void shuffle_customizations(void);
void
apply_customizations_to_symset(enum graphics_sets which_set)
{
glyph_map *gm;
struct customization_detail *details;
if (g.symset[which_set].handling == H_UTF8
&& g.sym_customizations[UNICODESET].count
&& g.sym_customizations[UNICODESET].details) {
/* These UTF-8 customizations get applied to the glyphmap array,
not to symset entries */
details = g.sym_customizations[UNICODESET].details;
while (details) {
gm = &glyphmap[details->content.urep.glyphidx];
(void) set_map_u(gm, 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.
*/
static void
shuffle_customizations(void)
{
int i;
struct unicode_representation *tmp_u[2][NUM_OBJECTS];
for (i = 0; i < NUM_OBJECTS; i++) {
tmp_u[0][i] =
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_OFF].u;
tmp_u[1][i] =
glyphmap[objects[i].oc_descr_idx + GLYPH_OBJ_PILETOP_OFF].u;
}
for (i = 0; i < NUM_OBJECTS; i++) {
glyphmap[i + GLYPH_OBJ_OFF].u = tmp_u[0][i];
glyphmap[i + GLYPH_OBJ_PILETOP_OFF].u = tmp_u[1][i];
}
}
struct customization_detail *
find_matching_symset_customization(const char *customization_name,
int custtype,
enum graphics_sets which_set)
{
struct symset_customization *gdc = &g.sym_customizations[which_set];
if ((gdc->custtype == custtype)
&& (strcmp(customization_name, gdc->customization_name) != 0))
return gdc->details;
return (struct customization_detail *) 0;
}
void
purge_custom_entries(enum graphics_sets which_set)
{
struct symset_customization *gdc = &g.sym_customizations[which_set];
struct customization_detail *details = gdc->details, *next;
if (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;
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 = &g.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*/

1123
src/utf8map.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1375,7 +1375,7 @@ glyph2symidx(int glyph)
glyph_info glyphinfo;
map_glyphinfo(0, 0, glyph, 0, &glyphinfo);
return glyphinfo.gm.symidx;
return glyphinfo.gm.sym.symidx;
}
char *
@@ -1387,10 +1387,37 @@ encglyph(int glyph)
return encbuf;
}
int
decode_glyph(const char *str, int *glyph_ptr)
{
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
int rndchk = 0, dcount = 0, retval = 0;
const char *dp;
for (; *str && ++dcount <= 4; ++str) {
if ((dp = index(hex, *str)) != 0) {
retval++;
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
} else
break;
}
if (rndchk == g.context.rndencode) {
*glyph_ptr = dcount = 0;
for (; *str && ++dcount <= 4; ++str) {
if ((dp = index(hex, *str)) != 0) {
retval++;
*glyph_ptr = (*glyph_ptr * 16) + ((int) (dp - hex) / 2);
} else
break;
}
return retval;
}
return 0;
}
char *
decode_mixed(char *buf, const char *str)
{
static const char hex[] = "00112233445566778899aAbBcCdDeEfF";
char *put = buf;
glyph_info glyphinfo = nul_glyphinfo;
@@ -1399,27 +1426,16 @@ decode_mixed(char *buf, const char *str)
while (*str) {
if (*str == '\\') {
int rndchk, dcount, so, gv;
const char *dp, *save_str;
int dcount, so, gv;
const char *save_str;
save_str = str++;
switch (*str) {
case 'G': /* glyph value \GXXXXNNNN*/
rndchk = dcount = 0;
for (++str; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
else
break;
if (rndchk == g.context.rndencode) {
gv = dcount = 0;
for (; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
gv = (gv * 16) + ((int) (dp - hex) / 2);
else
break;
if ((dcount = decode_glyph(str + 1, &gv))) {
str += (dcount + 1);
map_glyphinfo(0, 0, gv, 0, &glyphinfo);
so = glyphinfo.gm.symidx;
so = glyphinfo.gm.sym.symidx;
*put++ = g.showsyms[so];
/* 'str' is ready for the next loop iteration and '*str'
should not be copied at the end of this iteration */
@@ -1429,25 +1445,6 @@ decode_mixed(char *buf, const char *str)
str = save_str;
}
break;
#if 0
case 'S': /* symbol offset */
so = rndchk = dcount = 0;
for (++str; *str && ++dcount <= 4; ++str)
if ((dp = index(hex, *str)) != 0)
rndchk = (rndchk * 16) + ((int) (dp - hex) / 2);
else
break;
if (rndchk == g.context.rndencode) {
dcount = 0;
for (; *str && ++dcount <= 2; ++str)
if ((dp = index(hex, *str)) != 0)
so = (so * 16) + ((int) (dp - hex) / 2);
else
break;
}
*put++ = g.showsyms[so];
break;
#endif
case '\\':
break;
case '\0':
@@ -1467,6 +1464,7 @@ decode_mixed(char *buf, const char *str)
return buf;
}
/*
* This differs from putstr() because the str parameter can
* contain a sequence of characters representing: