]> granicus.if.org Git - nethack/commitdiff
window port change - putmixed() (trunk only)
authornethack.allison <nethack.allison>
Tue, 17 Oct 2006 23:06:31 +0000 (23:06 +0000)
committernethack.allison <nethack.allison>
Tue, 17 Oct 2006 23:06:31 +0000 (23:06 +0000)
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?

16 files changed:
doc/window.doc
include/extern.h
include/winprocs.h
src/allmain.c
src/botl.c
src/mapglyph.c
src/pager.c
sys/amiga/winami.c
sys/mac/macwin.c
sys/wince/mswproc.c
win/Qt/qt_win.cpp
win/X11/winX.c
win/gem/wingem.c
win/gnome/gnbind.c
win/tty/wintty.c
win/win32/mswproc.c

index 6be38e2b594e39087792c0977ca708dc85f7c719..5e7bc1449d7c9ce2b235d9f1ffffcd33f2f014de 100644 (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.
index cc75d0bd19a7bfcccdfe3abfc75b79565b71517a..7ab7ffcdf4fdd97a4fd11fe5289d300b2568fa0b 100644 (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 ### */
 
index e9a07432e76df246326d1fb0def9b256a4db4704..900f37d705b5d3071c6d3e206893f9f44f758d5a 100644 (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)
index 8f9edf5f8454838be0ed6606e843cadf73bcbfee..52a7986fcad525437b1fd268fbd4a79f0bdfe154 100644 (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 {
index 49f1592886b068330c4c0aec06663b3108af4223..75598af853a3ab7c77321ceb9c0b61a0d4faea4b 100644 (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*/
index be382f3739615f8b9f78e2de1ad60972ef47da00..a21c81926193a07d4b8d8bf39c7e63e17efb88bd 100644 (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*/
index 0fc1cf00bcdcd831ff092579132924c09ce6ad84..138c254e8ca2c4e7f38972c8e0d94d48f2aec024 100644 (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",
+                               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()
 {
index 5a5dba615126b381d038c0917b6d094bd752ed8e..9b7d4130fb678edeb145698c4cf23d477e6b21ac 100644 (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,
index 67a6f169c0f8d183d14eb03b4ef2bd8d6f6f80a0..122bbdd8ff4a4e3c53e02cfddd862d22dcd71280 100644 (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,
index 41adfbd814f28d76963cd1fe09967c21399af456..3192277fe4f3d8a8341ecfdef3dc79bdb076b4e8 100644 (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,
index 0d7e2cddd132e1fff17df2e69409bb6a93972431..db2caac6e821a7217973ddd70c3ac5dfc1d91cc8 100644 (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,
index 3aba81ae017dcb7a5a6baa14954e1e5a672462e3..3186e57fcdac0dc3d7f6b007982c45ba4f32182a 100644 (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,
index 50dce814f09b45c3bcb01a23b87966d9f25cc179..29c779390de613b48846c7bcca2ffb17383268f1 100644 (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,
index 8d383b14d2c343d58af61efac7a97fe2cd5cba2c..76fb5bfe01bd80a602802c029684a96cfa07cbcf 100644 (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,
index 1c09465f280eed946363996268150d960dafebde..dc44a507a68c91fb54a7c3b9cfbaab9c7fbae30e 100644 (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,
index ff72df50777157074dfa9b0e43556012cdd4d6c3..9afe383f1c958d56357656760def7ed4da37c861 100644 (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,