safe_qbuf, short_oname (trunk only)

Change safe_qbuf() so that instead of picking one of three strings
for sprintf() to plug into a prompt string, it actually constructs the
full prompt string itself.  Also pass in the unformatted object and a pair
of formatting functions instead of performing dual formatting in advance.
The actual formatting is done via new routine short_oname() which also
takes an object and a pair of formatting routines plus a target length.
It uses the first routine, typically xname() or doname(), and formats the
object, then if the result is too long it makes some transformations, and
tries again.  If truncating "called foo" and "named bar" down to 12 chars
and omitting "uncursed, rustproof, thoroughly corroded" attributes still
result in a string that's too long, it uses the other formatting routine.
The latter calls one of several jacket routines around simple_typename()
to produce a short result.

     This has been through about four incarnations now and has gotten a
bit less testing each time, but I need to get it in place before I end up
running out of gas and abandoning it.  I've got some changes to shk.c
(where safe_qbuf is needed but not currently used) that now need to be
redone and will come eventually.
This commit is contained in:
nethack.rankin
2006-10-24 05:18:00 +00:00
parent 3cc5a682c9
commit 9315307df2
10 changed files with 318 additions and 107 deletions

View File

@@ -1500,6 +1500,8 @@ E boolean FDECL(not_fully_identified, (struct obj *));
E char *FDECL(corpse_xname, (struct obj *,const char *,unsigned));
E char *FDECL(cxname, (struct obj *));
E char *FDECL(killer_xname, (struct obj *));
E char *FDECL(short_oname, (struct obj *,char *(*)(OBJ_P),char *(*)(OBJ_P),
unsigned));
E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P)));
E char *FDECL(an, (const char *));
E char *FDECL(An, (const char *));
@@ -1516,6 +1518,9 @@ E char *FDECL(yname, (struct obj *));
E char *FDECL(Yname2, (struct obj *));
E char *FDECL(ysimple_name, (struct obj *));
E char *FDECL(Ysimple_name2, (struct obj *));
E char *FDECL(simpleonames, (struct obj *));
E char *FDECL(ansimpleoname, (struct obj *));
E char *FDECL(thesimpleoname, (struct obj *));
E char *FDECL(bare_artifactname, (struct obj *));
E char *FDECL(makeplural, (const char *));
E char *FDECL(makesingular, (const char *));
@@ -1524,6 +1529,8 @@ E int FDECL(rnd_class, (int,int));
E const char *FDECL(cloak_simple_name, (struct obj *));
E const char *FDECL(helm_simple_name, (struct obj *));
E const char *FDECL(mimic_obj_name, (struct monst *));
E char *FDECL(safe_qbuf, (char *,const char *,const char *,struct obj *,
char *(*)(OBJ_P),char *(*)(OBJ_P),const char *));
/* ### options.c ### */
@@ -1645,8 +1652,6 @@ E boolean FDECL(container_gone, (int (*)(OBJ_P)));
E int FDECL(use_container, (struct obj **,int));
E int FDECL(loot_mon, (struct monst *,int *,boolean *));
E int NDECL(dotip);
E const char *FDECL(safe_qbuf, (const char *,unsigned,
const char *,const char *,const char *));
#ifdef AUTOPICKUP_EXCEPTIONS
E boolean FDECL(is_autopickup_exception, (struct obj *, BOOLEAN_P));
#endif /* AUTOPICKUP_EXCEPTIONS */

View File

@@ -1014,7 +1014,7 @@ struct obj **optr;
register struct obj *obj = *optr;
register struct obj *otmp;
const char *s = (obj->quan != 1) ? "candles" : "candle";
char qbuf[QBUFSZ];
char qbuf[QBUFSZ], qsfx[QBUFSZ], *q;
if(u.uswallow) {
You(no_elbow_room);
@@ -1031,13 +1031,16 @@ struct obj **optr;
return;
}
Sprintf(qbuf, "Attach %s", the(xname(obj)));
Sprintf(eos(qbuf), " to %s?",
safe_qbuf(qbuf, sizeof(" to ?"), the(xname(otmp)),
the(simple_typename(otmp->otyp)), "it"));
if(yn(qbuf) == 'n') {
if (!obj->lamplit)
You("try to light %s...", the(xname(obj)));
/* first, minimal candelabrum suffix for formatting candles */
Sprintf(qsfx, " to\033%s?", thesimpleoname(otmp));
/* next, format the candles as a prefix for the candelabrum */
(void)safe_qbuf(qbuf, "Attach ", qsfx,
obj, yname, thesimpleoname, s);
/* strip temporary candelabrum suffix */
if ((q = strstri(qbuf, " to\033")) != 0) Strcpy(q, " to ");
/* last, format final "attach candles to candelabrum?" query */
if (yn(safe_qbuf(qbuf, qbuf, "?",
otmp, yname, thesimpleoname, "it")) == 'n') {
use_lamp(obj);
return;
} else {
@@ -2755,23 +2758,21 @@ do_break_wand(obj)
boolean shop_damage = FALSE;
boolean fillmsg = FALSE;
int expltype = EXPL_MAGICAL;
char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ];
char confirm[QBUFSZ], buf[BUFSZ];
Strcpy(the_wand, yname(obj));
Sprintf(confirm, "Are you really sure you want to break %s?",
safe_qbuf("", sizeof("Are you really sure you want to break ?"),
the_wand, ysimple_name(obj), "the wand"));
if (yn(confirm) == 'n' ) return 0;
if (yn(safe_qbuf(confirm, "Are you really sure you want to break ", "?",
obj, yname, ysimple_name, "the wand")) == 'n')
return 0;
if (nohands(youmonst.data)) {
You_cant("break %s without hands!", the_wand);
You_cant("break %s without hands!", yname(obj));
return 0;
} else if (ACURR(A_STR) < 10) {
You("don't have the strength to break %s!", the_wand);
You("don't have the strength to break %s!", yname(obj));
return 0;
}
pline("Raising %s high above your %s, you break it in two!",
the_wand, body_part(HEAD));
yname(obj), body_part(HEAD));
/* [ALI] Do this first so that wand is removed from bill. Otherwise,
* the freeinv() below also hides it from setpaid() which causes problems.

View File

@@ -391,9 +391,7 @@ register struct obj *obj;
Sprintf(qbuf, "What do you want to name %s ",
is_plural(obj) ? "these" : "this");
Sprintf(eos(qbuf), "%s?",
safe_qbuf(qbuf, sizeof("?"),
xname(obj), simple_typename(obj->otyp), ""));
(void)safe_qbuf(qbuf, qbuf, "?", obj, xname, simpleonames, "item");
getlin(qbuf, buf);
if(!*buf || *buf == '\033') return;
/* strip leading and trailing spaces; unnames item if all spaces */

View File

@@ -2813,12 +2813,16 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */
(otmp->otyp==CORPSE && (corpsecheck == 1 || tinnable(otmp))) :
feeding ? (otmp->oclass != COIN_CLASS && is_edible(otmp)) :
otmp->oclass==FOOD_CLASS) {
char qsfx[QBUFSZ];
boolean one = (otmp->quan == 1L);
/* "There is <an object> here; <verb> it?" or
"There are <N objects> here; <verb> one?" */
Sprintf(qbuf, "There %s ", otense(otmp, "are"));
Sprintf(eos(qbuf), "%s here; %s %s?",
safe_qbuf(qbuf, sizeof(" here; ...?") + strlen(verb),
doname(otmp), simple_typename(otmp->otyp),
"something"),
verb, (otmp->quan == 1L) ? "it" : "one");
Sprintf(qsfx, " here; %s %s?", verb, one ? "it" : "one");
(void)safe_qbuf(qbuf, qbuf, qsfx,
otmp, doname, ansimpleoname,
one ? something : (const char *)"things");
if ((c = yn_function(qbuf,ynqchars,'n')) == 'y')
return(otmp);
else if (c == 'q')

View File

@@ -17,6 +17,8 @@ STATIC_DCL boolean FDECL(taking_off, (const char *));
STATIC_DCL boolean FDECL(putting_on, (const char *));
STATIC_PTR int FDECL(ckunpaid,(struct obj *));
STATIC_PTR int FDECL(ckvalidcat,(struct obj *));
STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
STATIC_DCL char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
@@ -1162,6 +1164,32 @@ register struct obj *otmp;
W_WEP | W_SWAPWEP | W_QUIVER))));
}
/* extra xprname() input that askchain() can't pass through safe_qbuf() */
STATIC_VAR struct xprnctx {
char let;
boolean dot;
} safeq_xprn_ctx;
/* safe_qbuf() -> short_oname() callback */
STATIC_PTR char *
safeq_xprname(obj)
struct obj *obj;
{
return xprname(obj, (char *)0,
safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
0L, 0L);
}
/* alternate safe_qbuf() -> short_oname() callback */
STATIC_PTR char *
safeq_shortxprname(obj)
struct obj *obj;
{
return xprname(obj, ansimpleoname(obj),
safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
0L, 0L);
}
static NEARDATA const char removeables[] =
{ ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
@@ -1396,20 +1424,16 @@ nextclass:
if (ident && !not_fully_identified(otmp)) continue;
if (ckfn && !(*ckfn)(otmp)) continue;
if (!allflag) {
Strcpy(qbuf, !ininv ? doname(otmp) :
xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L));
/* this code seemed too complex to use safe_qbuf */
if (strlen(qbuf) > QBUFSZ - 20) {
Strcpy(qbuf,
!ininv ? an(simple_typename(otmp->otyp)) :
xprname(otmp, simple_typename(otmp->otyp),
ilet, !nodot, 0L, 0L));
}
Strcat(qbuf, "?");
safeq_xprn_ctx.let = ilet;
safeq_xprn_ctx.dot = !nodot;
(void)safe_qbuf(qbuf, (char *)0, "?",
otmp, ininv ? safeq_xprname : doname,
ininv ? safeq_shortxprname : ansimpleoname,
"item");
sym = (takeoff || ident || otmp->quan < 2L) ?
nyaq(qbuf) : nyNaq(qbuf);
}
else sym = 'y';
} else
sym = 'y';
otmpo = otmp;
if (sym == '#') {
@@ -3045,9 +3069,8 @@ register struct obj *obj;
int n;
menu_item *selected = 0;
Sprintf(qbuf,"Contents of %s:",
safe_qbuf("", sizeof("Contents of :"),
doname(obj), simple_typename(obj->otyp), ""));
(void)safe_qbuf(qbuf, "Contents of ", ":",
obj, doname, ansimpleoname, "that");
if (obj->cobj) {
n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,

View File

@@ -271,6 +271,7 @@ pick_lock(pick) /* pick a lock with a given object */
if(!get_adjacent_loc((char *)0, "Invalid location!", u.ux, u.uy, &cc)) return 0;
if (cc.x == u.ux && cc.y == u.uy) { /* pick lock on a container */
const char *verb;
char qsfx[QBUFSZ];
boolean it;
int count;
@@ -300,10 +301,12 @@ pick_lock(pick) /* pick a lock with a given object */
else if (!otmp->olocked) verb = "lock", it = 1;
else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
else verb = "pick";
Sprintf(qbuf, "There is %s here, %s %s?",
safe_qbuf("", sizeof("There is here, unlock its lock?"),
doname(otmp), an(simple_typename(otmp->otyp)), "a box"),
/* "There is <a box> here; <verb> <it|its lock>?" */
Sprintf(qsfx, " here; %s %s?",
verb, it ? "it" : "its lock");
(void)safe_qbuf(qbuf, "There is ", qsfx,
otmp, doname, ansimpleoname, "a box");
otmp->lknown = 1;
c = ynq(qbuf);
@@ -397,8 +400,8 @@ pick_lock(pick) /* pick a lock with a given object */
}
#endif
Sprintf(qbuf,"%sock it?",
(door->doormask & D_LOCKED) ? "Unl" : "L" );
Sprintf(qbuf,"%s it?",
(door->doormask & D_LOCKED) ? "Unlock" : "Lock");
c = yn(qbuf);
if(c == 'n') return(0);
@@ -466,10 +469,8 @@ doforce() /* try to force a chest with your weapon */
otmp->lknown = 1;
continue;
}
Sprintf(qbuf,"There is %s here, force its lock?",
safe_qbuf("", sizeof("There is here, force its lock?"),
doname(otmp), an(simple_typename(otmp->otyp)),
"a box"));
(void)safe_qbuf(qbuf, "There is ", " here; force its lock?",
otmp, doname, ansimpleoname, "a box");
otmp->lknown = 1;
c = ynq(qbuf);

View File

@@ -2170,9 +2170,9 @@ register struct monst *mon;
if (uarmg) continue; /* next ring might not be worn */
}
if (rn2(20) < ACURR(A_CHA)) {
Sprintf(qbuf, "\"That %s looks pretty. May I have it?\"",
safe_qbuf("",sizeof("\"That looks pretty. May I have it?\""),
xname(ring), simple_typename(ring->otyp), "ring"));
(void)safe_qbuf(qbuf, "\"That ",
" looks pretty. May I have it?\"",
ring, xname, simpleonames, "ring");
makeknown(RIN_ADORNMENT);
if (yn(qbuf) == 'n') continue;
} else pline("%s decides she'd like %s, and takes it.",
@@ -2195,10 +2195,9 @@ register struct monst *mon;
if (uarmg) break; /* no point trying further rings */
}
if (rn2(20) < ACURR(A_CHA)) {
Sprintf(qbuf,"\"That %s looks pretty. Would you wear it for me?\"",
safe_qbuf("",
sizeof("\"That looks pretty. Would you wear it for me?\""),
xname(ring), simple_typename(ring->otyp), "ring"));
(void)safe_qbuf(qbuf, "\"That ",
" looks pretty. Would you wear it for me?\"",
ring, xname, simpleonames, "ring");
makeknown(RIN_ADORNMENT);
if (yn(qbuf) == 'n') continue;
} else {

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)objnam.c 3.5 2006/05/08 */
/* SCCS Id: @(#)objnam.c 3.5 2006/10/16 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -12,6 +12,7 @@
STATIC_DCL char *FDECL(strprepend,(char *,const char *));
STATIC_DCL boolean FDECL(wishymatch, (const char *,const char *,BOOLEAN_P));
STATIC_DCL char *NDECL(nextobuf);
STATIC_DCL void FDECL(releaseobuf, (char *));
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
struct Jitem {
@@ -62,14 +63,25 @@ register const char *pref;
}
/* manage a pool of BUFSZ buffers, so callers don't have to */
static char NEARDATA obufs[NUMOBUF][BUFSZ];
static int obufidx = 0;
STATIC_OVL char *
nextobuf()
{
static char NEARDATA bufs[NUMOBUF][BUFSZ];
static int bufidx = 0;
obufidx = (obufidx + 1) % NUMOBUF;
return obufs[obufidx];
}
bufidx = (bufidx + 1) % NUMOBUF;
return bufs[bufidx];
/* put the most recently allocated buffer back if possible */
STATIC_OVL void
releaseobuf(bufp)
char *bufp;
{
/* caller may not know whether bufp is the most recently allocated
buffer; if it isn't, do nothing */
if (bufp == obufs[obufidx])
obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
}
char *
@@ -1030,6 +1042,82 @@ struct obj *obj;
return buf;
}
/* xname,doname,&c with long results reformatted to omit some stuff */
char *
short_oname(obj, func, altfunc, lenlimit)
struct obj *obj;
char *FDECL((*func), (OBJ_P)), /* main formatting routine */
*FDECL((*altfunc), (OBJ_P)); /* alternate for shortest result */
unsigned lenlimit;
{
struct obj save_obj;
char unamebuf[12], onamebuf[12],
*save_oname, *save_uname, *outbuf;
outbuf = (*func)(obj);
if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
/* shorten called string to fairly small amount */
save_uname = objects[obj->otyp].oc_uname;
if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
(void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
Strcpy(unamebuf + sizeof unamebuf - 4, "...");
objects[obj->otyp].oc_uname = unamebuf;
releaseobuf(outbuf);
outbuf = (*func)(obj);
objects[obj->otyp].oc_uname = save_uname; /* restore called string */
if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
}
/* shorten named string to fairly small amount */
save_oname = has_oname(obj) ? ONAME(obj) : 0;
if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
(void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
Strcpy(onamebuf + sizeof onamebuf - 4, "...");
ONAME(obj) = onamebuf;
releaseobuf(outbuf);
outbuf = (*func)(obj);
ONAME(obj) = save_oname; /* restore named string */
if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
}
/* shorten both called and named strings;
unamebuf and onamebuf have both already been populated */
if (save_uname && strlen(save_uname) >= sizeof unamebuf &&
save_oname && strlen(save_oname) >= sizeof onamebuf) {
objects[obj->otyp].oc_uname = unamebuf;
ONAME(obj) = onamebuf;
releaseobuf(outbuf);
outbuf = (*func)(obj);
if ((unsigned)strlen(outbuf) <= lenlimit) {
objects[obj->otyp].oc_uname = save_uname;
ONAME(obj) = save_oname;
return outbuf;
}
}
/* still long; strip several name-lengthening attributes;
called and named strings are still in truncated form */
save_obj = *obj;
obj->bknown = obj->rknown = obj->greased = 0;
obj->oeroded = obj->oeroded2 = 0;
releaseobuf(outbuf);
outbuf = (*func)(obj);
if (altfunc && (unsigned)strlen(outbuf) > lenlimit) {
/* still long; use the alternate function (usually one of
the jackets around simple_typename()) */
releaseobuf(outbuf);
outbuf = (*altfunc)(obj);
}
/* restore the object */
*obj = save_obj;
if (save_oname) ONAME(obj) = save_oname;
if (save_uname) objects[obj->otyp].oc_uname = save_uname;
/* use whatever we've got, whether it's too long or not */
return outbuf;
}
/*
* Used if only one of a collection of objects is named (e.g. in eat.c).
*/
@@ -1413,6 +1501,48 @@ struct obj *obj;
return s;
}
/* "scroll" or "scrolls" */
char *
simpleonames(obj)
struct obj *obj;
{
char *simpleoname = simple_typename(obj->otyp);
if (obj->quan != 1L) simpleoname = makeplural(simpleoname);
return simpleoname;
}
/* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
char *
ansimpleoname(obj)
struct obj *obj;
{
char *simpleoname = simpleonames(obj);
int otyp = obj->otyp;
/* prefix with "the" if a unique item, or a fake one imitating same,
has been formatted with its actual name (we let typename() handle
any `known' and `dknown' checking necessary) */
if (otyp == FAKE_AMULET_OF_YENDOR) otyp = AMULET_OF_YENDOR;
if (objects[otyp].oc_unique &&
!strcmp(simpleoname, OBJ_NAME(objects[otyp])))
return the(simpleoname);
/* simpleoname is singular if quan==1, plural otherwise */
if (obj->quan == 1L) simpleoname = an(simpleoname);
return simpleoname;
}
/* "the scroll" or "the scrolls" */
char *
thesimpleoname(obj)
struct obj *obj;
{
char *simpleoname = simpleonames(obj);
return the(simpleoname);
}
char *
bare_artifactname(obj)
struct obj *obj;
@@ -3038,4 +3168,84 @@ struct monst *mtmp;
return "whatcha-may-callit";
}
/*
* Construct a query prompt string, based around an object name, which is
* guaranteed to fit within [QBUFSZ]. Takes an optional prefix, three
* choices for filling in the middle (two object formatting functions and a
* last resort literal which should be very short), and an optional suffix.
*/
char *
safe_qbuf(qbuf, qprefix, qsuffix, obj, func, altfunc, lastR)
char *qbuf; /* output buffer */
const char *qprefix, *qsuffix;
struct obj *obj;
char *FDECL((*func), (OBJ_P)), *FDECL((*altfunc), (OBJ_P));
const char *lastR;
{
char *bufp, *endp;
/* convert size_t (or int for ancient systems) to ordinary unsigned */
unsigned len, lenlimit,
len_qpfx = (unsigned)(qprefix ? strlen(qprefix) : 0),
len_qsfx = (unsigned)(qsuffix ? strlen(qsuffix) : 0),
len_lastR = (unsigned)strlen(lastR);
lenlimit = QBUFSZ - 1;
endp = qbuf + lenlimit;
/* sanity check, aimed mainly at paniclog (it's conceivable for
the result of short_oname() to be shorter than the length of
the last resort string, but we ignore that possibility here) */
if (len_qpfx > lenlimit)
impossible("safe_qbuf: prefix too long (%u characters).",
len_qpfx);
else if (len_qpfx + len_qsfx > lenlimit)
impossible("safe_qbuf: suffix too long (%u + %u characters).",
len_qpfx, len_qsfx);
else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
len_qpfx, len_lastR, len_qsfx);
/* the output buffer might be the same as the prefix if caller
has already partially filled it */
if (qbuf == qprefix) {
/* prefix is already in the buffer */
*endp = '\0';
} else if (qprefix) {
/* put prefix into the buffer */
(void)strncpy(qbuf, qprefix, lenlimit);
*endp = '\0';
} else {
/* no prefix; output buffer starts out empty */
qbuf[0] = '\0';
}
len = (unsigned)strlen(qbuf);
if (len + len_lastR + len_qsfx > lenlimit) {
/* too long; skip formatting, last resort output is truncated */
if (len < lenlimit) {
(void)strncpy(&qbuf[len], lastR, lenlimit - len);
*endp = '\0';
len = (unsigned)strlen(qbuf);
if (qsuffix && len < lenlimit) {
(void)strncpy(&qbuf[len], qsuffix, lenlimit - len);
*endp = '\0';
/* len = (unsigned)strlen(qbuf); */
}
}
} else {
/* suffix and last resort are guaranteed to fit */
len += len_qsfx; /* include the pending suffix */
/* format the object */
bufp = short_oname(obj, func, altfunc, lenlimit - len);
if (len + strlen(bufp) <= lenlimit)
Strcat(qbuf, bufp); /* formatted name fits */
else
Strcat(qbuf, lastR); /* use last resort */
releaseobuf(bufp);
if (qsuffix) Strcat(qbuf, qsuffix);
}
/* assert( strlen(qbuf) < QBUFSZ ); */
return qbuf;
}
/*objnam.c*/

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)pickup.c 3.5 2006/07/08 */
/* SCCS Id: @(#)pickup.c 3.5 2006/10/16 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -580,9 +580,9 @@ menu_pickup:
if (!all_of_a_type) {
char qbuf[BUFSZ];
Sprintf(qbuf, "Pick up %s?",
safe_qbuf("", sizeof("Pick up ?"), doname(obj),
an(simple_typename(obj->otyp)), "something"));
(void)safe_qbuf(qbuf, "Pick up ", "?",
obj, doname, ansimpleoname, something);
switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
case 'q': goto end_query; /* out 2 levels */
case 'n': continue;
@@ -1219,9 +1219,9 @@ boolean telekinesis;
(next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
moderateloadmsg);
if (container) (void) strsubst(qbuf,"lifting","removing");
Sprintf(eos(qbuf), " %s. Continue?",
safe_qbuf(qbuf, sizeof(" . Continue?"),
doname(obj), an(simple_typename(obj->otyp)), "something"));
Strcat(qbuf, " ");
(void)safe_qbuf(qbuf, qbuf, ". Continue?",
obj, doname, ansimpleoname, something);
obj->quan = savequan;
switch (ynq(qbuf)) {
case 'q': result = -1; break;
@@ -1238,32 +1238,6 @@ boolean telekinesis;
return result;
}
/* To prevent qbuf overflow in prompts use planA only
* if it fits, or planB if PlanA doesn't fit,
* finally using the fallback as a last resort.
* last_restort is expected to be very short.
*/
const char *
safe_qbuf(qbuf, padlength, planA, planB, last_resort)
const char *qbuf, *planA, *planB, *last_resort;
unsigned padlength;
{
/* convert size_t (or int for ancient systems) to ordinary unsigned */
unsigned len_qbuf = (unsigned)strlen(qbuf),
len_planA = (unsigned)strlen(planA),
len_planB = (unsigned)strlen(planB),
len_lastR = (unsigned)strlen(last_resort);
unsigned textleft = QBUFSZ - (len_qbuf + padlength);
if (len_lastR >= textleft) {
impossible("safe_qbuf: last_resort too large at %u characters.",
len_lastR);
return "";
}
return (len_planA < textleft) ? planA :
(len_planB < textleft) ? planB : last_resort;
}
/*
* Pick up <count> of obj from the ground and add it to the hero's inventory.
* Returns -1 if caller should break out of its loop, 0 if nothing picked
@@ -1566,11 +1540,8 @@ lootcont:
nobj = cobj->nexthere;
if (Is_container(cobj)) {
Sprintf(qbuf, "There is %s here, loot it?",
safe_qbuf("", sizeof("There is here, loot it?"),
doname(cobj), an(simple_typename(cobj->otyp)),
"a container"));
c = ynq(qbuf);
c = ynq(safe_qbuf(qbuf, "There is ", " here, loot it?",
cobj, doname, ansimpleoname, "a container"));
if (c == 'q') return (timepassed);
if (c == 'n') continue;
any = TRUE;
@@ -2155,9 +2126,8 @@ int held;
}
if (cnt || flags.menu_style == MENU_FULL) {
Strcpy(qbuf, "Do you want to take something out of ");
Sprintf(eos(qbuf), "%s?",
safe_qbuf(qbuf, 1, yname(obj), ysimple_name(obj), "it"));
(void)safe_qbuf(qbuf, "Do you want to take something out of ", "?",
obj, yname, ysimple_name, "it");
if (flags.menu_style != MENU_TRADITIONAL) {
if (flags.menu_style == MENU_FULL) {
int t;

View File

@@ -3818,9 +3818,9 @@ boolean force;
if(!u.dx && !u.dy) {
for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
if(Is_box(otmp)) {
Sprintf(qbuf, "There is %s here. Check it for traps?",
safe_qbuf("", sizeof("There is here. Check it for traps?"),
doname(otmp), an(simple_typename(otmp->otyp)), "a box"));
(void)safe_qbuf(qbuf, "There is ",
" here. Check it for traps?",
otmp, doname, ansimpleoname, "a box");
switch (ynq(qbuf)) {
case 'q': return(0);
case 'n': continue;