diff --git a/dat/quest.txt b/dat/quest.txt index 8887374d9..dc0c26c36 100644 --- a/dat/quest.txt +++ b/dat/quest.txt @@ -59,7 +59,7 @@ All of the windows are boarded up, and there are objects scattered around the entrance. Strange forbidding shapes seem to be moving in the distance. -%E +%E [You arrive at %H, but all is not well.] %Cp Arc 00002 Once again, you are back at %H. %E @@ -101,7 +101,7 @@ You have an odd feeling this may be the last time you ever come here. "Finally you have returned, %p. You were always my most promising student. Allow me to see if you are ready for the most difficult task of your career." -%E +%E [You have returned, %p, to a difficult task.] %Cp Arc 00016 "Again, %p, you stand before me. Let me see if you have gained experience in the interim." @@ -115,20 +115,20 @@ Are you finally ready for the task that must be accomplished?" vain. Begone! Your tenure at this college has been revoked! "You are a disgrace to the profession!" -%E +%E [%pC, you have failed us. Begone!] %Cc Arc 00019 "%p, you are yet too inexperienced to undertake such a demanding quest. A mere %r could not possibly face the rigors demanded and survive. Go forth, and come here again when your adventures have further taught you." -%E +%E [%pC, a mere %r is too inexperienced.] %Cc Arc 00020 "%pC! I've heard that you've been using sloppy techniques. Your results lately can hardly be called suitable for %ra! "How could you have strayed from the %a path? Go from here, and come back only when you have purified yourself." -%E +%E [%pC, you have strayed from the %a path. Purify yourself!] %Cc Arc 00021 "Grave times have befallen the college, for %na has stolen %o. Without it, the board of directors of @@ -144,7 +144,7 @@ to me. close this college. "May the wisdom of %d be your guide." -%E +%E [%nC has stolen %o. Locate %i, defeat %n within, and return %o.] %Cp Arc 00025 "Beware, for %n is powerful and cunning." %E @@ -182,7 +182,7 @@ A plain opens before you. Beyond the plain lies a foreboding edifice. You have the feeling that you will soon find the entrance to %i. -%E +%E [This foreboding edifice must hide the entrance to %i.] %Cp Arc 00036 Once again, you are near the entrance to %i. %E @@ -191,7 +191,7 @@ A strange feeling washes over you, and you think back to things you learned during the many lectures of %l. You realize the feeling must be the presence of %o. -%E +%E [This strange feeling must be the presence of %o.] %Cp Arc 00041 The familiar presence of %o is in the ether. %E @@ -200,14 +200,14 @@ The familiar presence of %o is in the ether. %o, when your teacher, %l, has already failed. "Come, try your best! I shall destroy you, and gnaw on your bones." -%E +%E [Come, %p, I shall destroy you!] %Cc Arc 00051 "Again you try to best me, eh %p? Well, you shall fail again. "You shall never recover %o. "I shall bear your soul to the Plane of Origins for my master's pleasure." -%E +%E [Again you try to best me, %p? You shall never recover %o.] %Cp Arc 00052 "You persist yet %p! Good. Now, you shall die!" %E @@ -250,7 +250,7 @@ falter!" The power of %o flows through your body! You feel as if you could now take on the Wizard of Yendor himself and win, but you know you must return %o to %l. -%E +%E [The power of %o flows through your body! You must return it to %l.] %Cp Arc 00080 The body of %n dissipates in a cloud of noxious fumes. %E @@ -266,18 +266,18 @@ Please take %o with you. You, %p, can guard it now far better than I. May the blessings of %d follow you and guard you." -%E +%E [%lC instructs you to guard %o from now on.] # assumes Orb of Detection (glass object) %Cc Arc 00082 "Careful, %p! %oC might break, and that would be a tragic loss. You are its keeper now, and the time has come to resume your search for the Amulet. %Z await your return through the magic portal that brought you here." -%E +%E [Resume your search for the Amulet beyond the magic portal to %Z.] %Cc Arc 00090 "Welcome back, %p. Have you progressed with your quest to regain the Amulet of Yendor for %d?" -%E +%E [Have you progressed with your quest to regain the Amulet of Yendor for %d?] %Cc Arc 00091 "Congratulations, %p. I wondered if anyone could prevail against the Wizard and the minions of Moloch. Now, you must embark on one @@ -288,7 +288,7 @@ There you must find the altar of %d and sacrifice the Amulet on that altar to fulfill your destiny. "Remember, your path now should always be upwards." -%E +%E [Take the Amulet to the Astral Plane and sacrifice it at the altar of %d.] # # Barbarian # @@ -3338,7 +3338,7 @@ from birth as the instrument of %d. You are destined to recover the Amulet for your deity, or die in the attempt. Your hour of destiny has come. For the sake of us all: Go bravely with %d! -%E +%E [%dC has chosen you to recover the Amulet of Yendor.] %Cp - 00002 You receive a faint telepathic message from %l: Your help is urgently needed at %H! @@ -3468,7 +3468,7 @@ you will never be able to enter the place where he who has the Amulet resides. Go now! You are banished from this place. -%E +%E [You are banished from %H for betraying your allegiance to %d.] # # TEST PATTERN # diff --git a/include/qtext.h b/include/qtext.h index c27566bb2..f6c18d524 100644 --- a/include/qtext.h +++ b/include/qtext.h @@ -9,11 +9,16 @@ /* (i.e., num roles + 1) */ #define LEN_HDR 3 /* Maximum length of a category name */ +/* quest text message buffer sizes; used to be hardcoded as 80 and 128, but + have been expanded to allow some slop for block message summary lines */ +#define QTEXT_IN_SIZ 100 /* used by both nethack and makedefs */ +#define QTEXT_OUTSIZ 200 /* used only by nethack */ + struct qtmsg { int msgnum; char delivery; long offset, - size; + size, summary_size; }; #ifdef MAKEDEFS_C /***** MAKEDEFS *****/ @@ -37,6 +42,10 @@ struct qthdr { #define END_NOT_IN_MSG "End record encountered before message - line %d\n" #define TEXT_NOT_IN_MSG "Text encountered outside message - line %d\n" #define UNREC_CREC "Unrecognized Control record at line %d\n" +#define MAL_SUM "Malformed summary in End record - line %d\n" +#define DUMB_SUM "Summary for single line message is useless - line %d\n" +#define CTRL_TRUNC "Control record truncated at line %d\n" +#define TEXT_TRUNC "Text record truncated at line %d\n" #define OUT_OF_HEADERS "Too many message types (line %d)\nAdjust N_HDR in qtext.h and recompile.\n" #define OUT_OF_MESSAGES "Too many messages in class (line %d)\nAdjust N_MSG in qtext.h and recompile.\n" diff --git a/src/questpgr.c b/src/questpgr.c index c5348f11b..340ab5c99 100644 --- a/src/questpgr.c +++ b/src/questpgr.c @@ -29,7 +29,7 @@ STATIC_DCL void FDECL(deliver_by_pline, (struct qtmsg *)); STATIC_DCL void FDECL(deliver_by_window, (struct qtmsg *,int)); STATIC_DCL boolean FDECL(skip_pager, (BOOLEAN_P)); -static char in_line[80], cvt_buf[64], out_line[128]; +static char in_line[QTEXT_IN_SIZ], out_line[QTEXT_OUTSIZ], cvt_buf[64]; static struct qtlists qt_list; static dlb *msg_file; /* used by ldrname() and neminame(), then copied into cvt_buf */ @@ -366,7 +366,7 @@ struct qtmsg *qt_msg; long size; for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { - (void) dlb_fgets(in_line, 80, msg_file); + (void) dlb_fgets(in_line, QTEXT_IN_SIZ, msg_file); convert_line(); pline("%s", out_line); } @@ -382,12 +382,20 @@ int how; winid datawin = create_nhwindow(how); for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) { - (void) dlb_fgets(in_line, 80, msg_file); + (void) dlb_fgets(in_line, QTEXT_IN_SIZ, msg_file); convert_line(); putstr(datawin, 0, out_line); } display_nhwindow(datawin, TRUE); destroy_nhwindow(datawin); + + /* block messages delivered by window aren't kept in message history + but can have a one-line summary which is put there for ^P recall */ + if (qt_msg->summary_size) { + (void) dlb_fgets(in_line, QTEXT_IN_SIZ, msg_file); + convert_line(); + putmsghistory(out_line, FALSE); + } } boolean diff --git a/util/makedefs.c b/util/makedefs.c index 15cb5c344..c8b82c3d1 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -181,6 +181,7 @@ static int FDECL(get_hdr, (char *)); static boolean FDECL(new_id, (char *)); static boolean FDECL(known_msg, (int,int)); static void FDECL(new_msg, (char *,int,int)); +static char *FDECL(valid_qt_summary, (char *,BOOLEAN_P)); static void FDECL(do_qt_control, (char *)); static void FDECL(do_qt_text, (char *)); static void NDECL(adjust_qt_hdrs); @@ -2011,12 +2012,60 @@ new_msg(s, num, id) qt_msg = &(msg_hdr[num].qt_msg[msg_hdr[num].n_msg++]); qt_msg->msgnum = id; qt_msg->delivery = s[2]; - qt_msg->offset = qt_msg->size = 0L; + qt_msg->offset = qt_msg->size = qt_msg->summary_size = 0L; curr_msg = qt_msg; } } +/* check %E record for "[summary text]" that nethack can stuff into the + message history buffer when delivering text via window instead of pline */ +static char * +valid_qt_summary(s, parsing) +char *s; /* end record: "%E" optionally followed by " [summary]" */ +boolean parsing; /* curr_msg is valid iff this is True */ +{ + static char summary[BUFSZ]; + char *p; + + if (*s != '%' || *(s + 1) != 'E') return (char *)0; + if ((p = index(s, '[')) == 0) return (char *)0; + /* note: opening '[' and closing ']' will be retained in the output; + anything after ']' will be discarded by putting a newline there */ + Strcpy(summary, p); + + /* have an opening bracket; summary[] holds it and all text that follows */ + p = eos(summary); + /* find closing bracket */ + while (p > summary && *(p - 1) != ']') --p; + + if (p == summary) { + /* we backed up all the way to the start without finding a bracket */ + if (parsing) /* malformed summary */ + Fprintf(stderr, MAL_SUM, qt_line); + } else if (p == summary + 1) { + ; /* ignore empty [] */ + } else { /* got something */ + /* p points one spot past ']', usually to '\n'; + we need to include the \n as part of the size */ + if (parsing) { + /* during the writing pass we won't be able to recheck + delivery, so any useless summary for a pline mode + message has to be carried along to the output file */ + if (curr_msg->delivery == 'p') + Fprintf(stderr, DUMB_SUM, qt_line); + /* +1 is for terminating newline */ + curr_msg->summary_size = (long)(p - summary) + 1L; + } else { + /* caller is writing rather than just parsing; + force newline after the closing bracket */ + Strcpy(p, "\n"); + } + return summary; + } + return (char *)0; +} + static void do_qt_control(s) char *s; @@ -2024,6 +2073,9 @@ do_qt_control(s) char code[BUFSZ]; int num, id = 0; + if (!index(s, '\n')) + Fprintf(stderr, CTRL_TRUNC, qt_line); + switch(s[1]) { case 'C': if(in_msg) { @@ -2047,8 +2099,11 @@ do_qt_control(s) case 'E': if(!in_msg) { Fprintf(stderr, END_NOT_IN_MSG, qt_line); - break; - } else in_msg = FALSE; + } else { + /* sets curr_msg->summary_size if applicable */ + (void) valid_qt_summary(s, TRUE); + in_msg = FALSE; + } break; default: Fprintf(stderr, UNREC_CREC, qt_line); @@ -2062,7 +2117,10 @@ do_qt_text(s) { if (!in_msg) { Fprintf(stderr, TEXT_NOT_IN_MSG, qt_line); + } else if (!index(s, '\n')) { + Fprintf(stderr, TEXT_TRUNC, qt_line); } + curr_msg->size += strlen(s); return; } @@ -2083,7 +2141,8 @@ adjust_qt_hdrs() for(j = 0; j < msg_hdr[i].n_msg; j++) { msg_hdr[i].qt_msg[j].offset = hdr_offset + count; - count += msg_hdr[i].qt_msg[j].size; + count += msg_hdr[i].qt_msg[j].size + + msg_hdr[i].qt_msg[j].summary_size; } return; } @@ -2126,11 +2185,16 @@ put_qt_hdrs() sizeof(struct qtmsg), msg_hdr[i].n_msg, ofp); #ifdef DEBUG { int j; - for(j = 0; j < msg_hdr[i].n_msg; j++) - Fprintf(stderr, "msg %d @ %ld (%ld)\n", + for(j = 0; j < msg_hdr[i].n_msg; j++) { + Fprintf(stderr, "msg %d @ %ld (%ld)", msg_hdr[i].qt_msg[j].msgnum, msg_hdr[i].qt_msg[j].offset, msg_hdr[i].qt_msg[j].size); + if (msg_hdr[i].qt_msg[j].summary_size) + Fprintf(stderr, " [%ld]", + msg_hdr[i].qt_msg[j].summary_size); + Fprintf(stderr, "\n"); + } } #endif } @@ -2160,7 +2224,7 @@ do_questtxt() qt_line = 0; in_msg = FALSE; - while (fgets(in_line, 80, ifp) != 0) { + while (fgets(in_line, QTEXT_IN_SIZ, ifp) != 0) { SpinCursor (3); qt_line++; @@ -2173,11 +2237,17 @@ do_questtxt() in_msg = FALSE; adjust_qt_hdrs(); put_qt_hdrs(); - while (fgets(in_line, 80, ifp) != 0) { + while (fgets(in_line, QTEXT_IN_SIZ, ifp) != 0) { if(qt_control(in_line)) { + char *summary_p = 0; + in_msg = (in_line[1] == 'C'); - continue; + if (!in_msg) summary_p = valid_qt_summary(in_line, FALSE); + /* don't write anything unless we've got a summary */ + if (!summary_p) continue; + /* we have summary text; replace raw %E record with it */ + Strcpy(in_line, summary_p); /* (guaranteed to fit) */ } else if(qt_comment(in_line)) continue; #ifdef DEBUG Fprintf(stderr, "%ld: %s", ftell(stdout), in_line); diff --git a/win/tty/topl.c b/win/tty/topl.c index ff53200df..d35e0ac46 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -701,7 +701,11 @@ boolean init; * they come from a previous session and logically precede * anything (like "Restoring save file...") that's happened now. * - * Called with a null pointer to finish up. + * Called with a null pointer to finish up restoration. + * + * It's also called by the quest pager code when a block message + * has a one-line summary specified. We put that line directly + * message history for ^P recall without having displayed it. */ void tty_putmsghistory(msg, restoring)