window port change - putmixed() (trunk only)

Add putmixed() to the window port. It allows map symbols to
be included in the string by encoding them in a unique fashion.
This was done because Unicode symbols, for instance, could be
longer than the size of a char.

The encoding of the map symbols in this patch is done by
prefixing a glyph value with \GXXXX, where XXXX is a
random value for the current game. The reason for the random
prefix is to minimize the possibility that a player can trigger
the escape sequence processing within text under their control
(dog names, etc.) the way they could if the sequence was fixed
in the source code. The random prefix remains the same throughout
the lifetime of a game because message window strings are
saved in the save file.

(There was actually a bug present because of the embedded
character even before the recent symbol changes, because if
someone was using a  different set of characters between games,
the saved messages would reflect the original characters, rather
than the current. That bug was introduced with the ability to
save messages to the savefile.)

A window port does not have to supply an XXX_putmixed() routine,
it can use genl_putmixed() which uses the old behavior of
embedding the sequence as a character within the string
and calling putstr(). genl_putmixed() takes care of the decoding
of the escape sequence.

This also #ifdef's out code in pager.c for converting a glyph
to a character, and uses mapglyph() to do that instead. Does
anyone see a problem with doing that through mapglyph instead
of repeating similar code within pager.c?
This commit is contained in:
nethack.allison
2006-10-17 23:06:31 +00:00
parent 6873e64cf5
commit 8fc01eb6b1
16 changed files with 164 additions and 19 deletions

View File

@@ -123,6 +123,39 @@ putstr(window, attr, str)
are done consecutively the user will see the first and
then the second. In the tty port, pline() achieves this
by calling more() or displaying both on the same line.
putmixed(window, attr, str)
-- Print str on the window with the given attribute. In
addition to printable ASCII characters (040-0126),
sequences of encoded glyph values are supported.
The glyph encoding sequence is \GXXXXNNNN, where:
XXXX is a hexadecimal value. The value must match
the randomly generated value for the current
game in progress in order to be decoded.
The value for the game in progress is stored in
context.rndencode. This field minimizes
unintentional decoding of player-supplied strings
such as pet names, etc.
NNNN is a hexadecimal value representing the glyph.
If a window port does not yet support special handling of
the glyph value, it can use genl_putmixed (mapglyph.c)
which converts the encoded glyph into a character symbol.
Multiple putmixed()s are output on separate lines. Attributes
can be one of
ATR_NONE (or 0)
ATR_ULINE
ATR_BOLD
ATR_BLINK
ATR_INVERSE
If a window-port does not support all of these, it may map
unsupported attributes to a supported one (e.g. map them
all to ATR_INVERSE). putmixed() may compress spaces out of
str, break str, or truncate str, if necessary for the
display. Where putmixed() breaks a line, it has to clear
to end-of-line.
-- putstr should be implemented such that if two putmixed()s
are done consecutively the user will see the first and
then the second.
get_nh_event() -- Does window event processing (e.g. exposure events).
A noop for the tty and X window-ports.
int nhgetch() -- Returns a single character input from the user.

View File

@@ -1030,6 +1030,8 @@ E boolean FDECL(usmellmon, (struct permonst *));
/* ### mapglyph.c ### */
E int FDECL(mapglyph, (int, int *, int *, unsigned *, int, int));
E char *FDECL(encglyph, (int));
E void FDECL(genl_putmixed, (winid, int, const char *));
/* ### mcastu.c ### */

View File

@@ -24,6 +24,7 @@ struct window_procs {
void FDECL((*win_destroy_nhwindow), (winid));
void FDECL((*win_curs), (winid,int,int));
void FDECL((*win_putstr), (winid, int, const char *));
void FDECL((*win_putmixed), (winid, int, const char *));
void FDECL((*win_display_file), (const char *, BOOLEAN_P));
void FDECL((*win_start_menu), (winid));
void FDECL((*win_add_menu), (winid,int,const ANY_P *,
@@ -100,6 +101,7 @@ extern NEARDATA struct window_procs windowprocs;
#define destroy_nhwindow (*windowprocs.win_destroy_nhwindow)
#define curs (*windowprocs.win_curs)
#define putstr (*windowprocs.win_putstr)
#define putmixed (*windowprocs.win_putmixed)
#define display_file (*windowprocs.win_display_file)
#define start_menu (*windowprocs.win_start_menu)
#define add_menu (*windowprocs.win_add_menu)

View File

@@ -52,6 +52,7 @@ boolean resuming;
}
if (!resuming) { /* new game */
context.rndencode = rnd(9000);
set_wear(); /* handle side-effects of worn starting gear */
(void) pickup(1); /* autopickup at initial location */
} else {

View File

@@ -331,7 +331,7 @@ struct istat_s blstats[2][MAXBLSTATS] = {
{ 0L, ANY_STR, {(genericptr_t)0L}, (char *)0, 40, 0}, /* 7 BL_ALIGN */
{ 0L, ANY_LONG, {(genericptr_t)0L}, (char *)0, 20, 0}, /* 8 BL_SCORE */
{ 0L, ANY_LONG, {(genericptr_t)0L}, (char *)0, 20, 0}, /* 9 BL_CAP */
{ 0L, ANY_LONG, {(genericptr_t)0L}, (char *)0, 10, 0}, /* 10 BL_GOLD */
{ 0L, ANY_LONG, {(genericptr_t)0L}, (char *)0, 30, 0}, /* 10 BL_GOLD */
{ 0L, ANY_INT, {(genericptr_t)0L}, (char *)0, 10, BL_ENEMAX}, /* 11 BL_ENE */
{ 0L, ANY_INT, {(genericptr_t)0L}, (char *)0, 10, 0}, /* 12 BL_ENEMAX */
{ 0L, ANY_LONG, {(genericptr_t)0L}, (char *)0, 10, 0}, /* 13 BL_XP */
@@ -727,8 +727,9 @@ bot()
* the rogue level.
*/
Sprintf(blstats[idx][BL_GOLD].val, "%c:%ld",
showsyms[COIN_CLASS + SYM_OFF_O],
Sprintf(blstats[idx][BL_GOLD].val,
"%s:%ld",
encglyph(objnum_to_glyph(GOLD_PIECE)),
blstats[idx][BL_GOLD].a.a_long);
valset[BL_GOLD] = TRUE; /* indicate val already set */
@@ -1451,7 +1452,7 @@ genericptr_t ptr;
curs(WIN_STATUS, 1, 0);
putstr(WIN_STATUS, 0, newbot1);
curs(WIN_STATUS, 1, 1);
putstr(WIN_STATUS, 0, newbot2);
putmixed(WIN_STATUS, 0, newbot2); /* putmixed() due to GOLD glyph */
}
#endif /*STATUS_VIA_WINDOWPORT*/

View File

@@ -254,4 +254,83 @@ unsigned *ospecial;
return idx;
}
char *
encglyph(glyph)
int glyph;
{
static char encbuf[20];
Sprintf(encbuf, "\\G%04X%04X", context.rndencode, glyph);
return encbuf;
}
/*
* This differs from putstr() because the str parameter can
* contain a sequence of characters representing:
* \GXXXXNNNN a glyph value, encoded by encglyph().
*
* For window ports that haven't yet written their own
* XXX_putmixed() routine, this general one can be used.
* It replaces the encoded glyph sequence with a single
* showsyms[] char, then just passes that string onto
* putstr().
*/
void
genl_putmixed(window, attr, str)
winid window;
int attr;
const char *str;
{
char buf[BUFSZ];
const char *cp = str;
char *put = buf;
while (*cp) {
if (*cp == '\\') {
int rndchk = 0, so = 0, gv = 0, ch, oc, dcount;
unsigned os;
const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF";
const char *save_cp = cp;
cp++;
switch(*cp) {
case 'G': /* glyph value \GXXXXNNNN*/
dcount = 0;
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
rndchk = (int)((rndchk * 16) + ((int)(dp - hex) / 2));
if (rndchk == context.rndencode) {
dcount = 0;
for (; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
gv = (int)((gv * 16) + ((int)(dp - hex) / 2));
so = mapglyph(gv, &ch, &oc, &os, 0, 0);
*put++ = showsyms[so];
} else {
/* possible forgery - leave it the way it is */
cp = save_cp;
}
break;
# if 0
case 'S': /* symbol offset */
dcount = 0;
for (++cp; *cp && (dp = index(hex, *cp)) && (dcount++ < 4); cp++)
rndchk = (int)((rndchk * 16) + ((int)(dp - hex) / 2));
if (rndchk == context.rndencode) {
dcount = 0;
for (; *cp && (dp = index(hex, *cp)) && (dcount++ < 2); cp++)
so = (int)((so * 16) + ((int)(dp - hex) / 2));
}
*put++ = showsyms[so];
break;
# endif
case '\\':
break;
}
}
*put++ = *cp++;
}
*put = '\0';
/* now send it to the normal putstr */
putstr(window, attr, buf);
}
/*mapglyph.c*/

View File

@@ -466,6 +466,7 @@ do_look(mode, click_cc)
char out_str[BUFSZ], look_buf[BUFSZ];
const char *x_str, *firstmatch = 0;
struct permonst *pm = 0;
int glyph; /* glyph at selected position */
int i, ans = 0;
int sym; /* typed symbol or converted glyph */
int found; /* count of matching syms found */
@@ -522,8 +523,8 @@ do_look(mode, click_cc)
out_str[0] = '\0';
if (from_screen || clicklook) {
int glyph; /* glyph at selected position */
int oc, so;
unsigned os;
if (from_screen) {
if (flags.verbose)
pline("Please move the cursor to %s.",
@@ -538,9 +539,10 @@ do_look(mode, click_cc)
}
flags.verbose = FALSE; /* only print long question once */
}
glyph = glyph_at(cc.x,cc.y);
/* Convert the glyph at the selected position to a symbol. */
glyph = glyph_at(cc.x,cc.y);
#if 0
if (glyph_is_cmap(glyph)) {
sym = showsyms[glyph_to_cmap(glyph)];
} else if (glyph_is_trap(glyph)) {
@@ -566,6 +568,8 @@ do_look(mode, click_cc)
glyph, (int)cc.x, (int)cc.y);
sym = ' ';
}
#endif
so = mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
}
/*
@@ -580,7 +584,9 @@ do_look(mode, click_cc)
def_monsyms[i].explain) {
need_to_look = TRUE;
if (!found) {
Sprintf(out_str, "%c %s", sym, an(def_monsyms[i].explain));
Sprintf(out_str, "%s %s",
encglyph(glyph),
an(def_monsyms[i].explain));
firstmatch = def_monsyms[i].explain;
found++;
} else {
@@ -604,7 +610,8 @@ do_look(mode, click_cc)
*/
if (u.uswallow && (from_screen || clicklook) && is_swallow_sym(sym)) {
if (!found) {
Sprintf(out_str, "%c %s", sym, mon_interior);
Sprintf(out_str, "%s %s",
encglyph(glyph), mon_interior);
firstmatch = mon_interior;
} else {
found += append_str(out_str, mon_interior);
@@ -622,7 +629,9 @@ do_look(mode, click_cc)
continue;
}
if (!found) {
Sprintf(out_str, "%c %s", sym, an(def_oc_syms[i].explain));
Sprintf(out_str, "%s %s",
encglyph(glyph),
an(def_oc_syms[i].explain));
firstmatch = def_oc_syms[i].explain;
found++;
} else {
@@ -633,7 +642,9 @@ do_look(mode, click_cc)
if (sym == DEF_INVISIBLE) {
if (!found) {
Sprintf(out_str, "%c %s", sym, an(invisexplain));
Sprintf(out_str, "%s %s",
encglyph(glyph),
an(invisexplain));
firstmatch = invisexplain;
found++;
} else {
@@ -656,10 +667,12 @@ do_look(mode, click_cc)
if (!found) {
if (is_cmap_trap(i)) {
Sprintf(out_str, "%c a trap", sym);
Sprintf(out_str, "%s a trap",
encglyph(glyph));
hit_trap = TRUE;
} else {
Sprintf(out_str, "%c %s", sym,
Sprintf(out_str, "%s %s",
encglyph(glyph),
article == 2 ? the(x_str) :
article == 1 ? an(x_str) : x_str);
}
@@ -684,8 +697,8 @@ do_look(mode, click_cc)
if (sym == ((from_screen || clicklook) ?
warnsyms[i] : def_warnsyms[i].sym)) {
if (!found) {
Sprintf(out_str, "%c %s",
sym, def_warnsyms[i].explanation);
Sprintf(out_str, "%s %s",
encglyph(glyph), def_warnsyms[i].explanation);
firstmatch = def_warnsyms[i].explanation;
found++;
} else {
@@ -703,7 +716,8 @@ do_look(mode, click_cc)
if (skipped_venom && found < 2) {
x_str = def_oc_syms[VENOM_CLASS].explain;
if (!found) {
Sprintf(out_str, "%c %s", sym, an(x_str));
Sprintf(out_str, "%s %s",
encglyph(glyph), an(x_str));
firstmatch = x_str;
found++;
} else {
@@ -715,7 +729,8 @@ do_look(mode, click_cc)
if (iflags.bouldersym && sym == iflags.bouldersym) {
if (!found) {
firstmatch = "boulder";
Sprintf(out_str, "%c %s", sym, an(firstmatch));
Sprintf(out_str, "%s %s",
encglyph(glyph), an(firstmatch));
found++;
} else {
found += append_str(out_str, "boulder");
@@ -747,7 +762,10 @@ do_look(mode, click_cc)
/* Finally, print out our explanation. */
if (found) {
pline("%s", out_str);
/* Used putmixed() because there may be an encoded glyph present */
putmixed(WIN_MESSAGE, 0, out_str);
/* check the data file for information about this thing */
if (found == 1 && ans != LOOK_QUICK && ans != LOOK_ONCE &&
(ans == LOOK_VERBOSE || (flags.help && !quick)) && !clicklook) {
@@ -765,7 +783,6 @@ do_look(mode, click_cc)
return 0;
}
int
dowhatis()
{

View File

@@ -44,6 +44,7 @@ struct window_procs amii_procs =
amii_destroy_nhwindow,
amii_curs,
amii_putstr,
genl_putmixed,
amii_display_file,
amii_start_menu,
amii_add_menu,
@@ -114,6 +115,7 @@ struct window_procs amiv_procs =
amii_destroy_nhwindow,
amii_curs,
amii_putstr,
genl_putmixed,
amii_display_file,
amii_start_menu,
amii_add_menu,

View File

@@ -3253,6 +3253,7 @@ struct window_procs mac_procs = {
mac_destroy_nhwindow,
mac_curs,
mac_putstr,
genl_putmixed,
mac_display_file,
mac_start_menu,
mac_add_menu,

View File

@@ -60,6 +60,7 @@ struct window_procs mswin_procs = {
mswin_destroy_nhwindow,
mswin_curs,
mswin_putstr,
genl_putmixed,
mswin_display_file,
mswin_start_menu,
mswin_add_menu,

View File

@@ -5241,6 +5241,7 @@ struct window_procs Qt_procs = {
NetHackQtBind::qt_destroy_nhwindow,
NetHackQtBind::qt_curs,
NetHackQtBind::qt_putstr,
genl_putmixed,
NetHackQtBind::qt_display_file,
NetHackQtBind::qt_start_menu,
NetHackQtBind::qt_add_menu,

View File

@@ -120,6 +120,7 @@ struct window_procs X11_procs = {
X11_destroy_nhwindow,
X11_curs,
X11_putstr,
genl_putmixed,
X11_display_file,
X11_start_menu,
X11_add_menu,

View File

@@ -57,6 +57,7 @@ struct window_procs Gem_procs = {
Gem_destroy_nhwindow,
Gem_curs,
Gem_putstr,
genl_putmixed,
Gem_display_file,
Gem_start_menu,
Gem_add_menu,

View File

@@ -41,6 +41,7 @@ struct window_procs Gnome_procs = {
gnome_destroy_nhwindow,
gnome_curs,
gnome_putstr,
genl_putmixed,
gnome_display_file,
gnome_start_menu,
gnome_add_menu,

View File

@@ -70,6 +70,7 @@ struct window_procs tty_procs = {
tty_destroy_nhwindow,
tty_curs,
tty_putstr,
genl_putmixed,
tty_display_file,
tty_start_menu,
tty_add_menu,

View File

@@ -87,6 +87,7 @@ struct window_procs mswin_procs = {
mswin_destroy_nhwindow,
mswin_curs,
mswin_putstr,
genl_putmixed,
mswin_display_file,
mswin_start_menu,
mswin_add_menu,