diff --git a/include/extern.h b/include/extern.h index ea4cd3193..0ac63d8c6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 */ diff --git a/src/apply.c b/src/apply.c index 416c65f87..4010540c4 100644 --- a/src/apply.c +++ b/src/apply.c @@ -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. diff --git a/src/do_name.c b/src/do_name.c index da473b964..861cca8f4 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -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 */ diff --git a/src/eat.c b/src/eat.c index e048486ad..8ccf7b6b2 100644 --- a/src/eat.c +++ b/src/eat.c @@ -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 here; it?" or + "There are here; 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') diff --git a/src/invent.c b/src/invent.c index f7aed474d..02af4b4af 100644 --- a/src/invent.c +++ b/src/invent.c @@ -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, diff --git a/src/lock.c b/src/lock.c index 88844a060..1fcd4c228 100644 --- a/src/lock.c +++ b/src/lock.c @@ -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 here; ?" */ + 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); diff --git a/src/mhitu.c b/src/mhitu.c index c54a98efc..ba943f75d 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -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 { diff --git a/src/objnam.c b/src/objnam.c index 623057ad2..cdf3a9a76 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -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*/ diff --git a/src/pickup.c b/src/pickup.c index 678c5ffb2..ae989a2ee 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -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 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; diff --git a/src/trap.c b/src/trap.c index f339b4520..87ebfc444 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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;