diff --git a/doc/window.doc b/doc/window.doc index 6be38e2b5..5e7bc1449 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -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. diff --git a/include/extern.h b/include/extern.h index cc75d0bd1..7ab7ffcdf 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/include/winprocs.h b/include/winprocs.h index e9a07432e..900f37d70 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -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) diff --git a/src/allmain.c b/src/allmain.c index 8f9edf5f8..52a7986fc 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -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 { diff --git a/src/botl.c b/src/botl.c index 49f159288..75598af85 100644 --- a/src/botl.c +++ b/src/botl.c @@ -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*/ diff --git a/src/mapglyph.c b/src/mapglyph.c index be382f373..a21c81926 100644 --- a/src/mapglyph.c +++ b/src/mapglyph.c @@ -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*/ diff --git a/src/pager.c b/src/pager.c index 0fc1cf00b..138c254e8 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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() { diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c index 5a5dba615..9b7d4130f 100644 --- a/sys/amiga/winami.c +++ b/sys/amiga/winami.c @@ -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, diff --git a/sys/mac/macwin.c b/sys/mac/macwin.c index 67a6f169c..122bbdd8f 100644 --- a/sys/mac/macwin.c +++ b/sys/mac/macwin.c @@ -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, diff --git a/sys/wince/mswproc.c b/sys/wince/mswproc.c index 41adfbd81..3192277fe 100644 --- a/sys/wince/mswproc.c +++ b/sys/wince/mswproc.c @@ -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, diff --git a/win/Qt/qt_win.cpp b/win/Qt/qt_win.cpp index 0d7e2cddd..db2caac6e 100644 --- a/win/Qt/qt_win.cpp +++ b/win/Qt/qt_win.cpp @@ -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, diff --git a/win/X11/winX.c b/win/X11/winX.c index 3aba81ae0..3186e57fc 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -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, diff --git a/win/gem/wingem.c b/win/gem/wingem.c index 50dce814f..29c779390 100644 --- a/win/gem/wingem.c +++ b/win/gem/wingem.c @@ -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, diff --git a/win/gnome/gnbind.c b/win/gnome/gnbind.c index 8d383b14d..76fb5bfe0 100644 --- a/win/gnome/gnbind.c +++ b/win/gnome/gnbind.c @@ -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, diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 1c09465f2..dc44a507a 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -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, diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index ff72df507..9afe383f1 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -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,