diff --git a/include/decl.h b/include/decl.h index 3131ee655..de6e7f339 100644 --- a/include/decl.h +++ b/include/decl.h @@ -658,7 +658,6 @@ struct _create_particular_data { }; /* some array sizes for 'g' */ -#define BSIZE 20 #define WIZKIT_MAX 128 #define CVT_BUF_SIZE 64 @@ -677,12 +676,14 @@ enum cmdq_cmdtypes { CMDQ_EXTCMD, /* extended command, cmdq_add_ec() */ CMDQ_DIR, /* direction, cmdq_add_dir() */ CMDQ_USER_INPUT, /* placeholder for user input, cmdq_add_userinput() */ + CMDQ_INT, /* integer value, cmdq_add_int() */ }; struct _cmd_queue { int typ; char key; schar dirx, diry, dirz; + int intval; const struct ext_func_tab *ec_entry; struct _cmd_queue *next; }; @@ -694,6 +695,12 @@ struct enum_dump { typedef long cmdcount_nht; /* Command counts */ +enum { + CQ_CANNED = 0, /* internal canned sequence */ + CQ_REPEAT, /* user-inputted, if g.in_doagain, replayed */ + NUM_CQS +}; + /* * 'g' -- instance_globals holds engine state that does not need to be * persisted upon game exit. The initialization state is well defined @@ -706,7 +713,7 @@ typedef long cmdcount_nht; /* Command counts */ */ struct instance_globals { - struct _cmd_queue *command_queue; + struct _cmd_queue *command_queue[NUM_CQS]; /* apply.c */ int jumping_is_magic; /* current jump result of magic */ @@ -740,12 +747,6 @@ struct instance_globals { which requires a thing and a direction), and the input prompt is not shown. Also, while in_doagain is TRUE, no keystrokes can be saved into the saveq. */ - char pushq[BSIZE]; - char saveq[BSIZE]; - int phead; - int ptail; - int shead; - int stail; coord clicklook_cc; winid en_win; boolean en_via_menu; diff --git a/include/extern.h b/include/extern.h index 15f27d001..502035219 100644 --- a/include/extern.h +++ b/include/extern.h @@ -251,17 +251,18 @@ extern boolean redraw_cmd(char); extern const char *levltyp_to_name(int); extern void reset_occupations(void); extern void set_occupation(int(*)(void), const char *, cmdcount_nht); -extern void cmdq_add_ec(int(*)(void)); -extern void cmdq_add_key(char); -extern void cmdq_add_dir(schar, schar, schar); -extern void cmdq_add_userinput(void); +extern void cmdq_add_ec(int, int(*)(void)); +extern void cmdq_add_key(int, char); +extern void cmdq_add_dir(int, schar, schar, schar); +extern void cmdq_add_userinput(int); +extern void cmdq_add_int(int, int); +extern void cmdq_shift(int); +extern struct _cmd_queue *cmdq_reverse(struct _cmd_queue *); +extern struct _cmd_queue *cmdq_copy(int); extern struct _cmd_queue *cmdq_pop(void); -extern struct _cmd_queue *cmdq_peek(void); -extern void cmdq_clear(void); +extern struct _cmd_queue *cmdq_peek(int); +extern void cmdq_clear(int); extern char pgetchar(void); -extern void pushch(char); -extern void savech(char); -extern void savech_extcmd(const char *, boolean); extern char extcmd_initiator(void); extern int doextcmd(void); extern struct ext_func_tab *extcmds_getentry(int); @@ -300,7 +301,7 @@ extern char readchar(void); extern char readchar_poskey(coordxy *, coordxy *, int *); extern void sanity_check(void); extern char* key2txt(uchar, char *); -extern char yn_function(const char *, const char *, char); +extern char yn_function(const char *, const char *, char, boolean); extern boolean paranoid_query(boolean, const char *); extern void makemap_prepost(boolean, boolean); diff --git a/include/hack.h b/include/hack.h index 60f280c6e..e6bf44f9d 100644 --- a/include/hack.h +++ b/include/hack.h @@ -443,12 +443,12 @@ typedef uint32_t mmflags_nht; /* makemon MM_ flags */ #define MMOVE_NOMOVES 4 /* monster has no valid locations to move to */ /*** some utility macros ***/ -#define yn(query) yn_function(query, ynchars, 'n') -#define ynq(query) yn_function(query, ynqchars, 'q') -#define ynaq(query) yn_function(query, ynaqchars, 'y') -#define nyaq(query) yn_function(query, ynaqchars, 'n') -#define nyNaq(query) yn_function(query, ynNaqchars, 'n') -#define ynNaq(query) yn_function(query, ynNaqchars, 'y') +#define yn(query) yn_function(query, ynchars, 'n', TRUE) +#define ynq(query) yn_function(query, ynqchars, 'q', TRUE) +#define ynaq(query) yn_function(query, ynaqchars, 'y', TRUE) +#define nyaq(query) yn_function(query, ynaqchars, 'n', TRUE) +#define nyNaq(query) yn_function(query, ynNaqchars, 'n', TRUE) +#define ynNaq(query) yn_function(query, ynNaqchars, 'y', TRUE) /* Macros for scatter */ #define VIS_EFFECTS 0x01 /* display visual effects */ diff --git a/src/allmain.c b/src/allmain.c index 97af0626a..32eefcfed 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -275,8 +275,8 @@ moveloop_core(void) check_leash(old_ux, old_uy); } /* clear doagain keystrokes */ - pushch(0); - savech(0); + cmdq_clear(CQ_CANNED); + cmdq_clear(CQ_REPEAT); } } /* delayed change may not be valid anymore */ @@ -431,7 +431,7 @@ moveloop_core(void) if ((ch = pgetchar()) == ABORT) mvl_abort_lev++; else - pushch(ch); + cmdq_push_key(CQ_CANNED, ch); } if (!mvl_abort_lev && (*g.occupation)() == 0) #else @@ -609,11 +609,10 @@ stop_occupation(void) g.occupation = 0; g.context.botl = TRUE; /* in case u.uhs changed */ nomul(0); - pushch(0); } else if (g.multi >= 0) { nomul(0); } - cmdq_clear(); + cmdq_clear(CQ_CANNED); } void diff --git a/src/apply.c b/src/apply.c index e1392934c..d5da393f1 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1721,8 +1721,8 @@ dorub(void) } if (obj != uwep) { if (wield_tool(obj, "rub")) { - cmdq_add_ec(dorub); - cmdq_add_key(obj->invlet); + cmdq_add_ec(CQ_CANNED, dorub); + cmdq_add_key(CQ_CANNED, obj->invlet); return ECMD_TIME; } return ECMD_OK; @@ -2837,8 +2837,8 @@ use_whip(struct obj *obj) if (obj != uwep) { if (wield_tool(obj, "lash")) { - cmdq_add_ec(doapply); - cmdq_add_key(obj->invlet); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, obj->invlet); return ECMD_TIME; } return ECMD_OK; @@ -3232,8 +3232,8 @@ use_pole(struct obj *obj, boolean autohit) } if (obj != uwep) { if (wield_tool(obj, "swing")) { - cmdq_add_ec(doapply); - cmdq_add_key(obj->invlet); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, obj->invlet); return ECMD_TIME; } return ECMD_OK; @@ -3509,8 +3509,8 @@ use_grapple(struct obj *obj) } if (obj != uwep) { if (wield_tool(obj, "cast")) { - cmdq_add_ec(doapply); - cmdq_add_key(obj->invlet); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, obj->invlet); return ECMD_TIME; } return ECMD_OK; diff --git a/src/cmd.c b/src/cmd.c index 4428a27b6..e093c630c 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -233,12 +233,34 @@ set_occupation(int (*fn)(void), const char *txt, cmdcount_nht xtime) return; } +/* +void +cmdq_print(int q) +{ + struct _cmd_queue *cq = g.command_queue[q]; + char buf[QBUFSZ]; + + pline("CQ:%i", q); + while (cq) { + switch (cq->typ) { + case CMDQ_KEY: pline("(key:%s)", key2txt(cq->key, buf)); break; + case CMDQ_EXTCMD: pline("(extcmd:#%s)", cq->ec_entry->ef_txt); break; + case CMDQ_DIR: pline("(dir:%i,%i,%i)", cq->dirx, cq->diry, cq->dirz); break; + case CMDQ_USER_INPUT: pline1("(userinput)"); break; + case CMDQ_INT: pline("(int:%i)", cq->intval); break; + default: pline("(ERROR:%i)",cq->typ); break; + } + cq = cq->next; + } +} +*/ + /* add extended command function to the command queue */ void -cmdq_add_ec(int (*fn)(void)) +cmdq_add_ec(int q, int (*fn)(void)) { struct _cmd_queue *tmp = (struct _cmd_queue *) alloc(sizeof *tmp); - struct _cmd_queue *cq = g.command_queue; + struct _cmd_queue *cq = g.command_queue[q]; tmp->typ = CMDQ_EXTCMD; tmp->ec_entry = ext_func_tab_from_func(fn); @@ -250,15 +272,15 @@ cmdq_add_ec(int (*fn)(void)) if (cq) cq->next = tmp; else - g.command_queue = tmp; + g.command_queue[q] = tmp; } /* add a key to the command queue */ void -cmdq_add_key(char key) +cmdq_add_key(int q, char key) { struct _cmd_queue *tmp = (struct _cmd_queue *) alloc(sizeof *tmp); - struct _cmd_queue *cq = g.command_queue; + struct _cmd_queue *cq = g.command_queue[q]; tmp->typ = CMDQ_KEY; tmp->key = key; @@ -270,15 +292,15 @@ cmdq_add_key(char key) if (cq) cq->next = tmp; else - g.command_queue = tmp; + g.command_queue[q] = tmp; } /* add a direction to the command queue */ void -cmdq_add_dir(schar dx, schar dy, schar dz) +cmdq_add_dir(int q, schar dx, schar dy, schar dz) { struct _cmd_queue *tmp = (struct _cmd_queue *) alloc(sizeof *tmp); - struct _cmd_queue *cq = g.command_queue; + struct _cmd_queue *cq = g.command_queue[q]; tmp->typ = CMDQ_DIR; tmp->dirx = dx; @@ -292,15 +314,15 @@ cmdq_add_dir(schar dx, schar dy, schar dz) if (cq) cq->next = tmp; else - g.command_queue = tmp; + g.command_queue[q] = tmp; } /* add placeholder to the command queue, allows user input there */ void -cmdq_add_userinput(void) +cmdq_add_userinput(int q) { struct _cmd_queue *tmp = (struct _cmd_queue *) alloc(sizeof *tmp); - struct _cmd_queue *cq = g.command_queue; + struct _cmd_queue *cq = g.command_queue[q]; tmp->typ = CMDQ_USER_INPUT; tmp->next = NULL; @@ -311,7 +333,80 @@ cmdq_add_userinput(void) if (cq) cq->next = tmp; else - g.command_queue = tmp; + g.command_queue[q] = tmp; +} + +/* add integer to the command queue */ +void +cmdq_add_int(int q, int val) +{ + struct _cmd_queue *tmp = (struct _cmd_queue *) alloc(sizeof *tmp); + struct _cmd_queue *cq = g.command_queue[q]; + + tmp->typ = CMDQ_INT; + tmp->intval = val; + tmp->next = NULL; + + while (cq && cq->next) + cq = cq->next; + + if (cq) + cq->next = tmp; + else + g.command_queue[q] = tmp; +} + +/* shift the last entry in command queue to first */ +void +cmdq_shift(int q) +{ + struct _cmd_queue *tmp = NULL; + struct _cmd_queue *cq = g.command_queue[q]; + + while (cq && cq->next && cq->next->next) + cq = cq->next; + + if (cq) + tmp = cq->next; + if (tmp) { + tmp->next = g.command_queue[q]; + g.command_queue[q] = tmp; + cq->next = NULL; + } +} + +struct _cmd_queue * +cmdq_reverse(struct _cmd_queue *head) +{ + struct _cmd_queue *prev = NULL, *curr = head, *next; + + while (curr) { + next = curr->next; + curr->next = prev; + prev = curr; + curr = next; + } + return prev; +} + +struct _cmd_queue * +cmdq_copy(int q) +{ + struct _cmd_queue *tmp = NULL; + struct _cmd_queue *cq = g.command_queue[q]; + + while (cq) { + struct _cmd_queue *tmp2 = (struct _cmd_queue *) alloc(sizeof *tmp2); + + *tmp2 = *cq; + tmp2->next = tmp; + tmp = tmp2; + cq = cq->next; + } + + tmp = cmdq_reverse(tmp); + + return tmp; } /* pop off the topmost command from the command queue. @@ -320,10 +415,11 @@ cmdq_add_userinput(void) struct _cmd_queue * cmdq_pop(void) { - struct _cmd_queue *tmp = g.command_queue; + int q = (g.in_doagain) ? CQ_REPEAT : CQ_CANNED; + struct _cmd_queue *tmp = g.command_queue[q]; if (tmp) { - g.command_queue = tmp->next; + g.command_queue[q] = tmp->next; tmp->next = NULL; } return tmp; @@ -331,16 +427,16 @@ cmdq_pop(void) /* get the top entry without popping it */ struct _cmd_queue * -cmdq_peek(void) +cmdq_peek(int q) { - return g.command_queue; + return g.command_queue[q]; } /* clear all commands from the command queue */ void -cmdq_clear(void) +cmdq_clear(int q) { - struct _cmd_queue *tmp = g.command_queue; + struct _cmd_queue *tmp = g.command_queue[q]; struct _cmd_queue *tmp2; while (tmp) { @@ -348,96 +444,22 @@ cmdq_clear(void) free(tmp); tmp = tmp2; } - g.command_queue = NULL; -} - -static char popch(void); - -static char -popch(void) -{ - /* If occupied, return '\0', letting tgetch know a character should - * be read from the keyboard. If the character read is not the - * ABORT character (as checked in pcmain.c), that character will be - * pushed back on the pushq. - */ - if (g.occupation) - return '\0'; - if (g.in_doagain) - return (char) ((g.shead != g.stail) ? g.saveq[g.stail++] : '\0'); - else - return (char) ((g.phead != g.ptail) ? g.pushq[g.ptail++] : '\0'); + g.command_queue[q] = NULL; } char pgetchar(void) /* courtesy of aeb@cwi.nl */ { - register int ch; + register int ch = '\0'; + if (g.occupation) + return '\0'; if (iflags.debug_fuzzer) return randomkey(); - if (!(ch = popch())) - ch = nhgetch(); + ch = nhgetch(); return (char) ch; } -/* A ch == 0 resets the pushq */ -void -pushch(char ch) -{ - if (!ch) - g.phead = g.ptail = 0; - if (g.phead < BSIZE) - g.pushq[g.phead++] = ch; - return; -} - -/* A ch == 0 resets the saveq. Only save keystrokes when not - * replaying a previous command. - */ -void -savech(char ch) -{ - if (!g.in_doagain) { - if (!ch) - g.phead = g.ptail = g.shead = g.stail = 0; - else if (g.shead < BSIZE) - g.saveq[g.shead++] = ch; - } - return; -} - -/* perform savech() for the characters of an extended command name */ -void -savech_extcmd(const char *str, boolean addnewline) -{ - unsigned j, L = Strlen(str); - - /* DEBUGFILES='cmd.c' -- for tty or other one-line message 'window' - this debuging line could be immediately erased and need ^P to read */ - debugpline1("savech_extcmd(\"%s\")", str); - - /* 'str' might be the full command name or maybe just enough to be - unambiguous depending on how the interface handles that; if it is - "repeat" (or leading substring of that), don't save it for do-again */ - if (!g.in_doagain && (L > 2 && strncmp(str, "repeat", L))) { - uchar c = (g.shead > 0) ? (uchar) (g.saveq[g.shead - 1] & 0xff) : 0; - - /* reset saveq unless it holds a prefix */ - if (!c || !g.Cmd.commands[c] - || (g.Cmd.commands[c]->flags & PREFIXCMD) == 0) - savech(0); - - /* insert the '#' first because rhack() avoids doing that when - processing doextcmd() */ - savech(g.Cmd.extcmd_char); - for (j = 0; j < L; ++j) - savech(str[j]); - if (addnewline) - savech('\n'); - } -} - /* '#' or whatever has been bound to doextcmd() in its place */ char extcmd_initiator(void) @@ -871,7 +893,7 @@ domonability(void) char c = '\0'; if (might_hide && webmaker(uptr)) { - c = yn_function("Hide [h] or spin a web [s]?", "hsq", 'q'); + c = yn_function("Hide [h] or spin a web [s]?", "hsq", 'q', TRUE); if (c == 'q' || c == '\033') return ECMD_OK; } @@ -1388,7 +1410,7 @@ wiz_flip_level(void) * as flipping is normally done only during level creation. */ if (wizard) { - char c = yn_function(prmpt, choices, '\0'); + char c = yn_function(prmpt, choices, '\0', TRUE); if (c && index(choices, c)) { c -= '0'; @@ -2409,18 +2431,18 @@ do_repeat(void) int res = ECMD_OK; if (!g.in_doagain) { - char c = g.saveq[0]; + struct _cmd_queue *repeat_copy; - if (!c || !g.Cmd.commands[c & 0xff]) { + if (!cmdq_peek(CQ_REPEAT)) { Norep("There is no command available to repeat."); - if (c) - savech(0); return ECMD_FAIL; } + repeat_copy = cmdq_copy(CQ_REPEAT); g.in_doagain = TRUE; - g.stail = 0; rhack((char *) 0); /* read and execute command */ g.in_doagain = FALSE; + cmdq_clear(CQ_REPEAT); + g.command_queue[CQ_REPEAT] = repeat_copy; iflags.menu_requested = FALSE; if (g.context.move) res = ECMD_TIME; @@ -3965,7 +3987,7 @@ list_migrating_mons( Strcat(prmpt, "a q"); if (*xtra) Sprintf(eos(prmpt), "%c%s", '\033', xtra); - c = yn_function("List which?", prmpt, 'q'); + c = yn_function("List which?", prmpt, 'q', TRUE); n = (c == 'c') ? here : (c == 'n') ? nxtlv : (c == 'o') ? other @@ -4460,8 +4482,10 @@ reset_cmd_vars(boolean reset_cmdq) selection_free(g.travelmap, TRUE); g.travelmap = NULL; } - if (reset_cmdq) - cmdq_clear(); + if (reset_cmdq) { + cmdq_clear(CQ_CANNED); + cmdq_clear(CQ_REPEAT); + } } void @@ -4495,7 +4519,7 @@ rhack(char *cmd) } else if (firsttime) { cmd = parse(); /* parse() pushed a cmd but didn't return any key */ - if (!*cmd && g.command_queue) + if (!*cmd && cmdq_peek(CQ_CANNED)) goto got_prefix_input; } @@ -4563,13 +4587,28 @@ rhack(char *cmd) if (tlist->f_text && !g.occupation && g.multi) set_occupation(func, tlist->f_text, g.multi); g.ext_tlist = NULL; + + if (!g.in_doagain && func != do_repeat && func != doextcmd) { + if (!prefix_seen) + cmdq_clear(CQ_REPEAT); + cmdq_add_ec(CQ_REPEAT, ((struct ext_func_tab *) tlist)->ef_funct); + } else { + if (func == doextcmd) { + cmdq_clear(CQ_REPEAT); + } + } res = (*func)(); /* perform the command */ /* if 'func' is doextcmd(), 'tlist' is for Cmd.commands['#'] rather than for the command that doextcmd() just ran; doextcmd() notifies us what that was via ext_tlist; other commands leave it Null */ - if (g.ext_tlist) + if (g.ext_tlist) { tlist = g.ext_tlist, g.ext_tlist = NULL; + /* Add the command post-execution */ + cmdq_add_ec(CQ_REPEAT, ((struct ext_func_tab *) tlist)->ef_funct); + /* shift the command to first */ + cmdq_shift(CQ_REPEAT); + } if ((tlist->flags & PREFIXCMD) != 0) { /* it was a prefix command, mark and get another cmd */ @@ -4654,8 +4693,8 @@ rhack(char *cmd) || !help_dir(c1, prefix_seen->key, "Invalid direction key!")) #endif Norep("Unknown command '%s'.", expcmd); - cmdq_clear(); - savech(0); /* clear do-again queue */ + cmdq_clear(CQ_CANNED); + cmdq_clear(CQ_REPEAT); } /* didn't move */ g.context.move = FALSE; @@ -4786,7 +4825,7 @@ getdir(const char *s) dirsym = g.Cmd.dirchars[(cmdq->dirz > 0) ? DIR_DOWN : DIR_UP]; } } else { - cmdq_clear(); + cmdq_clear(CQ_CANNED); dirsym = '\0'; impossible("getdir: command queue had no dir?"); } @@ -4799,7 +4838,7 @@ getdir(const char *s) dirsym = readchar(); else dirsym = yn_function((s && *s != '^') ? s : "In what direction?", - (char *) 0, '\0'); + (char *) 0, '\0', FALSE); /* remove the prompt string so caller won't have to */ clear_nhwindow(WIN_MESSAGE); @@ -4807,7 +4846,8 @@ getdir(const char *s) docrt(); /* redraw */ goto retry; } - savech(dirsym); + if (!g.in_doagain) + cmdq_add_key(CQ_REPEAT, dirsym); got_dirsym: if (dirsym == g.Cmd.spkeys[NHKF_GETDIR_SELF] @@ -5447,16 +5487,16 @@ act_on_act( clicks and shouldn't inhibit explicit travel. */ iflags.travelcc.x = u.tx = u.ux + dx; iflags.travelcc.y = u.ty = u.uy + dy; - cmdq_add_ec(dotravel_target); + cmdq_add_ec(CQ_CANNED, dotravel_target); break; case MCMD_THROW_OBJ: - cmdq_add_ec(dothrow); - cmdq_add_userinput(); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, dothrow); + cmdq_add_userinput(CQ_CANNED); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_OPEN_DOOR: - cmdq_add_ec(doopen); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, doopen); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_LOCK_DOOR: otmp = carrying(SKELETON_KEY); @@ -5465,131 +5505,131 @@ act_on_act( if (!otmp) otmp = carrying(CREDIT_CARD); if (otmp) { - cmdq_add_ec(doapply); - cmdq_add_key(otmp->invlet); - cmdq_add_dir(dx, dy, 0); - cmdq_add_key('y'); /* "Lock it?" */ + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, otmp->invlet); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); + cmdq_add_key(CQ_CANNED, 'y'); /* "Lock it?" */ } break; case MCMD_UNTRAP_DOOR: - cmdq_add_ec(dountrap); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, dountrap); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_KICK_DOOR: - cmdq_add_ec(dokick); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, dokick); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_CLOSE_DOOR: - cmdq_add_ec(doclose); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, doclose); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_SEARCH: - cmdq_add_ec(dosearch); + cmdq_add_ec(CQ_CANNED, dosearch); break; case MCMD_LOOK_TRAP: - cmdq_add_ec(doidtrap); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, doidtrap); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_UNTRAP_TRAP: - cmdq_add_ec(dountrap); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, dountrap); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_MOVE_DIR: dir = xytod(dx, dy); - cmdq_add_ec(move_funcs[dir][MV_WALK]); + cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); break; case MCMD_RIDE: - cmdq_add_ec(doride); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, doride); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_REMOVE_SADDLE: /* m-prefix for #loot: skip any floor containers */ - cmdq_add_ec(do_reqmenu); - cmdq_add_ec(doloot); - cmdq_add_dir(dx, dy, 0); - cmdq_add_key('y'); /* "Do you want to remove the saddle ..." */ + cmdq_add_ec(CQ_CANNED, do_reqmenu); + cmdq_add_ec(CQ_CANNED, doloot); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); + cmdq_add_key(CQ_CANNED, 'y'); /* "Do you want to remove the saddle ..." */ break; case MCMD_APPLY_SADDLE: if ((otmp = carrying(SADDLE)) != 0) { - cmdq_add_ec(doapply); - cmdq_add_key(otmp->invlet); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, otmp->invlet); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); } break; case MCMD_ATTACK_NEXT2U: dir = xytod(dx, dy); - cmdq_add_ec(move_funcs[dir][MV_WALK]); + cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); break; case MCMD_TALK: - cmdq_add_ec(dotalk); - cmdq_add_dir(dx, dy, 0); + cmdq_add_ec(CQ_CANNED, dotalk); + cmdq_add_dir(CQ_CANNED, dx, dy, 0); break; case MCMD_NAME: - cmdq_add_ec(docallcmd); - cmdq_add_key('m'); /* name a monster */ - cmdq_add_dir(dx, dy, 0); /* getpos() will use u.ux+dx,u.uy+dy */ + cmdq_add_ec(CQ_CANNED, docallcmd); + cmdq_add_key(CQ_CANNED, 'm'); /* name a monster */ + cmdq_add_dir(CQ_CANNED, dx, dy, 0); /* getpos() will use u.ux+dx,u.uy+dy */ break; case MCMD_QUAFF: - cmdq_add_ec(dodrink); - cmdq_add_key('y'); /* "Drink from the fountain?" */ + cmdq_add_ec(CQ_CANNED, dodrink); + cmdq_add_key(CQ_CANNED, 'y'); /* "Drink from the fountain?" */ break; case MCMD_DIP: - cmdq_add_ec(dodip); - cmdq_add_userinput(); - cmdq_add_key('y'); /* "Dip foo into the fountain?" */ + cmdq_add_ec(CQ_CANNED, dodip); + cmdq_add_userinput(CQ_CANNED); + cmdq_add_key(CQ_CANNED, 'y'); /* "Dip foo into the fountain?" */ break; case MCMD_SIT: - cmdq_add_ec(dosit); + cmdq_add_ec(CQ_CANNED, dosit); break; case MCMD_UP: - cmdq_add_ec(doup); + cmdq_add_ec(CQ_CANNED, doup); break; case MCMD_DOWN: - cmdq_add_ec(dodown); + cmdq_add_ec(CQ_CANNED, dodown); break; case MCMD_DISMOUNT: - cmdq_add_ec(doride); + cmdq_add_ec(CQ_CANNED, doride); break; case MCMD_MONABILITY: - cmdq_add_ec(domonability); + cmdq_add_ec(CQ_CANNED, domonability); break; case MCMD_PICKUP: - cmdq_add_ec(dopickup); + cmdq_add_ec(CQ_CANNED, dopickup); break; case MCMD_LOOT: - cmdq_add_ec(doloot); + cmdq_add_ec(CQ_CANNED, doloot); break; case MCMD_EAT: - cmdq_add_ec(doeat); - cmdq_add_key('y'); /* "There is foo here; eat it?" */ + cmdq_add_ec(CQ_CANNED, doeat); + cmdq_add_key(CQ_CANNED, 'y'); /* "There is foo here; eat it?" */ break; case MCMD_DROP: - cmdq_add_ec(dodrop); + cmdq_add_ec(CQ_CANNED, dodrop); break; case MCMD_INVENTORY: - cmdq_add_ec(ddoinv); + cmdq_add_ec(CQ_CANNED, ddoinv); break; case MCMD_REST: - cmdq_add_ec(donull); + cmdq_add_ec(CQ_CANNED, donull); break; case MCMD_LOOK_HERE: - cmdq_add_ec(dolook); + cmdq_add_ec(CQ_CANNED, dolook); break; case MCMD_LOOK_AT: g.clicklook_cc.x = u.ux + dx; g.clicklook_cc.y = u.uy + dy; - cmdq_add_ec(doclicklook); + cmdq_add_ec(CQ_CANNED, doclicklook); break; case MCMD_UNTRAP_HERE: - cmdq_add_ec(dountrap); - cmdq_add_dir(0, 0, 1); + cmdq_add_ec(CQ_CANNED, dountrap); + cmdq_add_dir(CQ_CANNED, 0, 0, 1); break; case MCMD_OFFER: - cmdq_add_ec(dosacrifice); - cmdq_add_userinput(); + cmdq_add_ec(CQ_CANNED, dosacrifice); + cmdq_add_userinput(CQ_CANNED); break; case MCMD_CAST_SPELL: - cmdq_add_ec(docast); + cmdq_add_ec(CQ_CANNED, docast); break; default: break; @@ -5625,11 +5665,11 @@ there_cmd_menu(coordxy x, coordxy y, int mod) if (next2u(x, y) && !test_move(u.ux, u.uy, dx, dy, TEST_MOVE)) { int dir = xytod(dx, dy); - cmdq_add_ec(move_funcs[dir][MV_WALK]); + cmdq_add_ec(CQ_CANNED, move_funcs[dir][MV_WALK]); } else if (flags.travelcmd) { iflags.travelcc.x = u.tx = x; iflags.travelcc.y = u.ty = y; - cmdq_add_ec(dotravel_target); + cmdq_add_ec(CQ_CANNED, dotravel_target); } npick = 0; ch = '\0'; @@ -5675,7 +5715,7 @@ click_to_cmd(coordxy x, coordxy y, int mod) if (!iflags.herecmd_menu && iflags.clicklook && mod == CLICK_2) { g.clicklook_cc.x = x; g.clicklook_cc.y = y; - cmdq_add_ec(doclicklook); + cmdq_add_ec(CQ_CANNED, doclicklook); return cmd; } if (iflags.herecmd_menu && isok(x, y)) { @@ -5692,7 +5732,7 @@ click_to_cmd(coordxy x, coordxy y, int mod) } else { iflags.travelcc.x = u.tx = u.ux + x; iflags.travelcc.y = u.ty = u.uy + y; - cmdq_add_ec(dotravel_target); + cmdq_add_ec(CQ_CANNED, dotravel_target); return cmd; } @@ -5893,15 +5933,6 @@ parse(void) /* g.command_count will be set again when we re-enter with g.in_doagain set true */ g.command_count = g.last_command_count; - } else { - uchar c = (g.shead > 0) ? (uchar) (g.saveq[g.shead - 1] & 0xff) : 0; - - g.last_command_count = g.command_count; - /* reset saveq unless it holds a prefix */ - if (!c || !g.Cmd.commands[c] - || (g.Cmd.commands[c]->flags & PREFIXCMD) == 0) - savech(0); - savech((char) foo); } g.multi = g.command_count; @@ -6136,7 +6167,7 @@ doclicklook(void) * window port causing a buffer overflow there. */ char -yn_function(const char *query, const char *resp, char def) +yn_function(const char *query, const char *resp, char def, boolean addcmdq) { char res = '\033', qbuf[QBUFSZ]; struct _cmd_queue cq, *cmdq; @@ -6169,9 +6200,11 @@ yn_function(const char *query, const char *resp, char def) if (cq.typ == CMDQ_KEY) res = cq.key; else - cmdq_clear(); /* 'res' is ESC */ + cmdq_clear(CQ_CANNED); /* 'res' is ESC */ } else { res = (*windowprocs.win_yn_function)(query, resp, def); + if (addcmdq) + cmdq_add_key(CQ_REPEAT, res); } #ifdef DUMPLOG diff --git a/src/decl.c b/src/decl.c index 70260c017..f51ef9a19 100644 --- a/src/decl.c +++ b/src/decl.c @@ -192,7 +192,7 @@ const struct Race urace_init_data = { const struct instance_globals g_init = { - NULL, /* command_queue */ + UNDEFINED_VALUES, /* command_queue */ /* apply.c */ 0, /* jumping_is_magic */ @@ -219,12 +219,6 @@ const struct instance_globals g_init = { /* cmd.c */ UNDEFINED_VALUES, /* Cmd */ - UNDEFINED_VALUES, /* pushq */ - UNDEFINED_VALUES, /* saveq */ - UNDEFINED_VALUE, /* phead */ - UNDEFINED_VALUE, /* ptail */ - UNDEFINED_VALUE, /* shead */ - UNDEFINED_VALUE, /* stail */ UNDEFINED_VALUES, /* clicklook_cc */ WIN_ERR, /* en_win */ FALSE, /* en_via_menu */ diff --git a/src/detect.c b/src/detect.c index 1917725a0..4336222dd 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1242,7 +1242,7 @@ use_crystal_ball(struct obj **optr) /* read a single character */ if (Verbose(0, use_crystal_ball1)) You("may look for an object, monster, or special map symbol."); - ch = yn_function("What do you look for?", (char *) 0, '\0'); + ch = yn_function("What do you look for?", (char *) 0, '\0', TRUE); /* Don't filter out ' ' here; it has a use */ if ((ch != def_monsyms[S_GHOST].sym) && index(quitchars, ch)) { if (Verbose(0, use_crystal_ball2)) diff --git a/src/dig.c b/src/dig.c index f5a9e87b9..8fe5d0fda 100644 --- a/src/dig.c +++ b/src/dig.c @@ -969,8 +969,8 @@ use_pick_axe(struct obj *obj) if (obj != uwep) { if (wield_tool(obj, "swing")) { /* we're now wielding it. next turn, apply to dig. */ - cmdq_add_ec(doapply); - cmdq_add_key(obj->invlet); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, obj->invlet); return ECMD_TIME; } return ECMD_OK; diff --git a/src/do.c b/src/do.c index fe2717023..2ca0b940e 100644 --- a/src/do.c +++ b/src/do.c @@ -627,13 +627,13 @@ static int drop(struct obj *obj) { if (!obj) - return ECMD_OK; + return ECMD_FAIL; if (!canletgo(obj, "drop")) - return ECMD_OK; + return ECMD_FAIL; if (obj == uwep) { if (welded(uwep)) { weldmsg(obj); - return ECMD_OK; + return ECMD_FAIL; } setuwep((struct obj *) 0); } diff --git a/src/do_name.c b/src/do_name.c index 95244e61d..3e16d3efb 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -711,17 +711,19 @@ getpos(coord *ccp, boolean force, const char *goal) /* temporary? if we have a queued direction, return the adjacent spot in that direction */ - if ((cmdq = cmdq_pop()) != 0) { - cq = *cmdq; - free((genericptr_t) cmdq); - if (cq.typ == CMDQ_DIR && !cq.dirz) { - ccp->x = u.ux + cq.dirx; - ccp->y = u.uy + cq.diry; - } else { - cmdq_clear(); - result = -1; + if (!g.in_doagain) { + if ((cmdq = cmdq_pop()) != 0) { + cq = *cmdq; + free((genericptr_t) cmdq); + if (cq.typ == CMDQ_DIR && !cq.dirz) { + ccp->x = u.ux + cq.dirx; + ccp->y = u.uy + cq.diry; + } else { + cmdq_clear(CQ_CANNED); + result = -1; + } + return result; } - return result; } for (i = 0; i < SIZE(pick_chars_def); i++) @@ -762,7 +764,19 @@ getpos(coord *ccp, boolean force, const char *goal) rushrun = FALSE; g.program_state.getting_a_command = 1; - c = readchar_poskey(&tx, &ty, &sidx); + if ((cmdq = cmdq_pop()) != 0) { + if (cmdq->typ == CMDQ_KEY) { + c = cmdq->key; + } else { + cmdq_clear(CQ_CANNED); + return -1; + } + free(cmdq); + } else { + c = readchar_poskey(&tx, &ty, &sidx); + if (!g.in_doagain) + cmdq_add_key(CQ_REPEAT, c); + } if (hilite_state) { (*getpos_hilitefunc)(2); @@ -1472,7 +1486,7 @@ docallcmd(void) if (cq.typ == CMDQ_KEY) ch = cq.key; else - cmdq_clear(); + cmdq_clear(CQ_CANNED); goto docallcmd; } win = create_nhwindow(NHW_MENU); diff --git a/src/do_wear.c b/src/do_wear.c index c0ee55bc4..215c1bc00 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1698,7 +1698,7 @@ dotakeoff(void) pline("Not wearing any armor or accessories."); return ECMD_OK; } - if (Narmorpieces != 1 || ParanoidRemove || cmdq_peek()) + if (Narmorpieces != 1 || ParanoidRemove || cmdq_peek(CQ_CANNED)) otmp = getobj("take off", takeoff_ok, GETOBJ_NOFLAGS); if (!otmp) return ECMD_CANCEL; @@ -1717,7 +1717,7 @@ doremring(void) pline("Not wearing any accessories or armor."); return ECMD_OK; } - if (Naccessories != 1 || ParanoidRemove || cmdq_peek()) + if (Naccessories != 1 || ParanoidRemove || cmdq_peek(CQ_CANNED)) otmp = getobj("remove", remove_ok, GETOBJ_NOFLAGS); if (!otmp) return ECMD_CANCEL; @@ -2105,7 +2105,7 @@ accessory_or_armor_on(struct obj *obj) Sprintf(qbuf, "Which %s%s, Right or Left?", humanoid(g.youmonst.data) ? "ring-" : "", body_part(FINGER)); - answer = yn_function(qbuf, "rl", '\0'); + answer = yn_function(qbuf, "rl", '\0', TRUE); switch (answer) { case '\0': case '\033': @@ -2378,13 +2378,13 @@ glibr(void) otmp = uleft; Ring_off(uleft); dropx(otmp); - cmdq_clear(); + cmdq_clear(CQ_CANNED); } if (rightfall) { otmp = uright; Ring_off(uright); dropx(otmp); - cmdq_clear(); + cmdq_clear(CQ_CANNED); } } @@ -2405,7 +2405,7 @@ glibr(void) xfl++; wastwoweap = TRUE; setuswapwep((struct obj *) 0); /* clears u.twoweap */ - cmdq_clear(); + cmdq_clear(CQ_CANNED); if (canletgo(otmp, "")) dropx(otmp); } @@ -2441,7 +2441,7 @@ glibr(void) /* xfl++; */ otmp->quan = savequan; setuwep((struct obj *) 0); - cmdq_clear(); + cmdq_clear(CQ_CANNED); if (canletgo(otmp, "")) dropx(otmp); } diff --git a/src/dokick.c b/src/dokick.c index efe4ba5a4..7f10a6c0c 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -864,7 +864,7 @@ dokick(void) You("are too small to do any kicking."); no_kick = TRUE; } else if (u.usteed) { - if (yn_function("Kick your steed?", ynchars, 'y') == 'y') { + if (yn_function("Kick your steed?", ynchars, 'y', TRUE) == 'y') { You("kick %s.", mon_nam(u.usteed)); kick_steed(); return ECMD_TIME; diff --git a/src/dothrow.c b/src/dothrow.c index 901a24e23..e751ff1e9 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -480,8 +480,8 @@ dofire(void) && !(uswapwep->cursed && uswapwep->bknown)) { /* we have a known not-cursed polearm as swap weapon. swap to it and retry */ - cmdq_add_ec(doswapweapon); - cmdq_add_ec(dofire); + cmdq_add_ec(CQ_CANNED, doswapweapon); + cmdq_add_ec(CQ_CANNED, dofire); return ECMD_OK; /* haven't taken any time yet */ } else { You("have no ammunition readied."); @@ -522,16 +522,16 @@ dofire(void) obj = uquiver; } else if (ammo_and_launcher(uquiver, uswapwep)) { /* swap weapons and retry fire */ - cmdq_add_ec(doswapweapon); - cmdq_add_ec(dofire); + cmdq_add_ec(CQ_CANNED, doswapweapon); + cmdq_add_ec(CQ_CANNED, dofire); return res; } else if ((olauncher = find_launcher(uquiver)) != 0) { /* wield launcher, retry fire */ if (uwep && !flags.pushweapon) - cmdq_add_ec(doswapweapon); - cmdq_add_ec(dowield); - cmdq_add_key(olauncher->invlet); - cmdq_add_ec(dofire); + cmdq_add_ec(CQ_CANNED, doswapweapon); + cmdq_add_ec(CQ_CANNED, dowield); + cmdq_add_key(CQ_CANNED, olauncher->invlet); + cmdq_add_ec(CQ_CANNED, dofire); return res; } } diff --git a/src/eat.c b/src/eat.c index 5dfa8c597..5e6d61c01 100644 --- a/src/eat.c +++ b/src/eat.c @@ -2576,7 +2576,7 @@ edibility_prompts(struct obj *otmp) if (*buf) { Snprintf(eos(buf), sizeof buf - strlen(buf), " Eat %s anyway?", (otmp->quan == 1L) ? "it" : "one"); - return (yn_function(buf, ynchars, 'n') == 'n') ? 1 : 2; + return (yn_function(buf, ynchars, 'n', TRUE) == 'n') ? 1 : 2; } return 0; } @@ -3437,7 +3437,7 @@ floorfood( then the trap would just get eaten on the _next_ turn... */ Sprintf(qbuf, "There is a bear trap here (%s); eat it?", u_in_beartrap ? "holding you" : "armed"); - if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { + if ((c = yn_function(qbuf, ynqchars, 'n', TRUE)) == 'y') { struct obj *beartrap; deltrap(ttmp); @@ -3473,7 +3473,7 @@ floorfood( || !on_level(&g.context.digging.level, &u.uz)) ? "; eat them?" : "; resume eating them?")); - c = yn_function(qbuf, ynqchars, 'n'); + c = yn_function(qbuf, ynqchars, 'n', TRUE); } if (c == 'y') return (struct obj *) &cg.zeroobj; /* csst away 'const' */ @@ -3488,7 +3488,7 @@ floorfood( else Sprintf(qbuf, "There are %ld gold pieces here; eat them?", gold->quan); - if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { + if ((c = yn_function(qbuf, ynqchars, 'n', TRUE)) == 'y') { return gold; } else if (c == 'q') { return (struct obj *) 0; @@ -3523,7 +3523,7 @@ floorfood( 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') + if ((c = yn_function(qbuf, ynqchars, 'n', TRUE)) == 'y') return otmp; else if (c == 'q') return (struct obj *) 0; diff --git a/src/end.c b/src/end.c index 2c5d802c5..2c53e4fa6 100644 --- a/src/end.c +++ b/src/end.c @@ -831,7 +831,7 @@ disclose(int how, boolean taken) Strcpy(qbuf, "Do you want your possessions identified?"); ask = should_query_disclose_option('i', &defquery); - c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery; + c = ask ? yn_function(qbuf, ynqchars, defquery, TRUE) : defquery; if (c == 'y') { /* caller has already ID'd everything */ (void) display_inventory((char *) 0, FALSE); @@ -844,7 +844,7 @@ disclose(int how, boolean taken) if (!done_stopprint) { ask = should_query_disclose_option('a', &defquery); c = ask ? yn_function("Do you want to see your attributes?", ynqchars, - defquery) + defquery, TRUE) : defquery; if (c == 'y') enlightenment((BASICENLIGHTENMENT | MAGICENLIGHTENMENT), @@ -876,7 +876,7 @@ disclose(int how, boolean taken) to plural vs singular for conducts but the less specific "conduct and achievements" is sufficient */ (acnt > 0) ? " and achievements" : ""); - c = yn_function(qbuf, ynqchars, defquery); + c = yn_function(qbuf, ynqchars, defquery, TRUE); } else { c = defquery; } @@ -889,7 +889,7 @@ disclose(int how, boolean taken) if (!done_stopprint) { ask = should_query_disclose_option('o', &defquery); c = ask ? yn_function("Do you want to see the dungeon overview?", - ynqchars, defquery) + ynqchars, defquery, TRUE) : defquery; if (c == 'y') show_overview((how >= PANICKED) ? 1 : 2, how); diff --git a/src/engrave.c b/src/engrave.c index 9f1a6d3e1..55c4bdbdb 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -969,7 +969,7 @@ doengrave(void) && (!Blind || oep->engr_type == BURN || oep->engr_type == ENGRAVE)) { c = yn_function("Do you want to add to the current engraving?", - ynqchars, 'y'); + ynqchars, 'y', TRUE); if (c == 'q') { pline1(Never_mind); return ECMD_OK; diff --git a/src/hack.c b/src/hack.c index 1f1ddda2c..139a15d2b 100644 --- a/src/hack.c +++ b/src/hack.c @@ -3571,7 +3571,7 @@ nomul(int nval) if (nval == 0) g.multi_reason = NULL, g.multireasonbuf[0] = '\0'; end_running(TRUE); - cmdq_clear(); + cmdq_clear(CQ_CANNED); } /* called when a non-movement, multi-turn action has completed */ diff --git a/src/insight.c b/src/insight.c index 04b1d5bff..0a1d3e73d 100644 --- a/src/insight.c +++ b/src/insight.c @@ -2684,7 +2684,7 @@ list_vanquished(char defquery, boolean ask) c = ask ? yn_function( "Do you want an account of creatures vanquished?", - ynaqchars, defquery) + ynaqchars, defquery, TRUE) : defquery; if (c == 'q') done_stopprint++; @@ -2833,7 +2833,7 @@ list_genocided(char defquery, boolean ask) (nextinct && !ngenocided) ? "extinct " : "", (ngenocided) ? " genocided" : "", (nextinct && ngenocided) ? " and extinct" : ""); - c = ask ? yn_function(buf, ynqchars, defquery) : defquery; + c = ask ? yn_function(buf, ynqchars, defquery, TRUE) : defquery; if (c == 'q') done_stopprint++; if (c == 'y') { diff --git a/src/invent.c b/src/invent.c index 20c09bf74..2440d7012 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1532,7 +1532,9 @@ getobj( boolean oneloop = FALSE; Loot *sortedinvent, *srtinv; struct _cmd_queue cq, *cmdq; + boolean need_more_cq = FALSE; + need_more_cq: if ((cmdq = cmdq_pop()) != 0) { cq = *cmdq; free(cmdq); @@ -1559,12 +1561,30 @@ getobj( break; } } + } else if (cq.typ == CMDQ_INT) { + /* getting a partial stack */ + if (!cntgiven && allowcnt) { + cnt = cq.intval; + cntgiven = TRUE; + goto need_more_cq; /* now, get CMDQ_KEY */ + } else { + cmdq_clear(CQ_CANNED); /* this should maybe clear the CQ_REPEAT too? */ + return NULL; + } } if (!otmp) /* didn't find what we were looking for, */ - cmdq_clear(); /* so discard any other queued commands */ + cmdq_clear(CQ_CANNED); /* so discard any other queued commands */ + else if (cntgiven) { + /* if stack is smaller than count, drop the whole stack */ + if (cnt < 1 || otmp->quan <= cnt) + cntgiven = FALSE; + goto split_otmp; + } return otmp; } /* !CMDQ_USER_INPUT */ - } /* cmdq */ + } else if (need_more_cq) { + return NULL; + } /* is "hands"/"self" a valid thing to do this action on? */ switch ((*obj_ok)((struct obj *) 0)) { @@ -1669,7 +1689,7 @@ getobj( Strcat(qbuf, " [*]"); else Sprintf(eos(qbuf), " [%s or ?*]", buf); - ilet = yn_function(qbuf, (char *) 0, '\0'); + ilet = yn_function(qbuf, (char *) 0, '\0', FALSE); } if (digit(ilet)) { long tmpcnt = 0; @@ -1782,7 +1802,11 @@ getobj( } } g.context.botl = 1; /* May have changed the amount of money */ - savech(ilet); + if (otmp && !g.in_doagain) { + if (cntgiven && cnt > 0) + cmdq_add_int(CQ_REPEAT, cnt); + cmdq_add_key(CQ_REPEAT, ilet); + } /* [we used to set otmp (by finding ilet in invent) here, but that's been moved above so that otmp can be checked earlier] */ /* verify the chosen object */ @@ -1803,6 +1827,7 @@ getobj( silly_thing(word, otmp); return (struct obj *) 0; } +split_otmp: if (cntgiven) { if (cnt == 0) return (struct obj *) 0; @@ -2990,110 +3015,110 @@ itemactions(struct obj *otmp) case IA_NONE: break; case IA_UNWIELD: - cmdq_add_ec((otmp == uwep) ? dowield + cmdq_add_ec(CQ_CANNED, (otmp == uwep) ? dowield : (otmp == uswapwep) ? remarm_swapwep : (otmp == uquiver) ? dowieldquiver : donull); /* can't happen */ - cmdq_add_key('-'); + cmdq_add_key(CQ_CANNED, '-'); break; case IA_APPLY_OBJ: - cmdq_add_ec(doapply); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, doapply); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_DIP_OBJ: /* #altdip instead of normal #dip - takes potion to dip into first (the inventory item instigating this) and item to be dipped second, also ignores floor features such as fountain/sink so we don't need to force m-prefix here */ - cmdq_add_ec(dip_into); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dip_into); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_NAME_OBJ: case IA_NAME_OTYP: - cmdq_add_ec(docallcmd); - cmdq_add_key((act == IA_NAME_OBJ) ? 'i' : 'o'); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, docallcmd); + cmdq_add_key(CQ_CANNED, (act == IA_NAME_OBJ) ? 'i' : 'o'); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_DROP_OBJ: - cmdq_add_ec(dodrop); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dodrop); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_EAT_OBJ: /* start with m-prefix; for #eat, it means ignore floor food if present and eat food from invent */ - cmdq_add_ec(do_reqmenu); - cmdq_add_ec(doeat); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, do_reqmenu); + cmdq_add_ec(CQ_CANNED, doeat); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_ENGRAVE_OBJ: - cmdq_add_ec(doengrave); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, doengrave); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_ADJUST_OBJ: - cmdq_add_ec(doorganize); /* #adjust */ - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, doorganize); /* #adjust */ + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_ADJUST_STACK: - cmdq_add_ec(adjust_split); /* #altadjust */ - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, adjust_split); /* #altadjust */ + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_SACRIFICE: - cmdq_add_ec(dosacrifice); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dosacrifice); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_BUY_OBJ: - cmdq_add_ec(dopay); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dopay); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_QUAFF_OBJ: /* start with m-prefix; for #quaff, it means ignore fountain or sink if present and drink a potion from invent */ - cmdq_add_ec(do_reqmenu); - cmdq_add_ec(dodrink); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, do_reqmenu); + cmdq_add_ec(CQ_CANNED, dodrink); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_QUIVER_OBJ: - cmdq_add_ec(dowieldquiver); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dowieldquiver); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_READ_OBJ: - cmdq_add_ec(doread); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, doread); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_RUB_OBJ: - cmdq_add_ec(dorub); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dorub); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_THROW_OBJ: - cmdq_add_ec(dothrow); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dothrow); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_TAKEOFF_OBJ: - cmdq_add_ec(dotakeoff); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dotakeoff); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_TIP_CONTAINER: - cmdq_add_ec(dotip); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dotip); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_INVOKE_OBJ: - cmdq_add_ec(doinvoke); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, doinvoke); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_WIELD_OBJ: - cmdq_add_ec(dowield); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dowield); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_WEAR_OBJ: - cmdq_add_ec(dowear); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dowear); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; case IA_SWAPWEAPON: - cmdq_add_ec(doswapweapon); + cmdq_add_ec(CQ_CANNED, doswapweapon); break; case IA_ZAP_OBJ: - cmdq_add_ec(dozap); - cmdq_add_key(otmp->invlet); + cmdq_add_ec(CQ_CANNED, dozap); + cmdq_add_key(CQ_CANNED, otmp->invlet); break; } } @@ -3481,7 +3506,7 @@ display_inventory(const char *lets, boolean want_reply) /* cmdq not a key, or did not find the object, abort */ free(cmdq); - cmdq_clear(); + cmdq_clear(CQ_CANNED); return '\0'; } return display_pickinv(lets, (char *) 0, (char *) 0, @@ -3911,8 +3936,7 @@ dotypeinv(void) } if (class_count > 1) { - c = yn_function(prompt, types, '\0'); - savech(c); + c = yn_function(prompt, types, '\0', TRUE); if (c == '\0') { clear_nhwindow(WIN_MESSAGE); goto doI_done; @@ -4902,7 +4926,7 @@ adjust_split(void) splitamount = 1L; } else { /* get first digit; doesn't wait for */ - dig = yn_function("Split off how many?", (char *) 0, '\0'); + dig = yn_function("Split off how many?", (char *) 0, '\0', TRUE); if (!digit(dig)) { pline1(Never_mind); return ECMD_CANCEL; @@ -5023,7 +5047,7 @@ doorganize_core(struct obj *obj) Sprintf(eos(qbuf), " to what [%s]%s?", lets, g.invent ? " (? see used letters)" : ""); for (trycnt = 1; ; ++trycnt) { - let = !isgold ? yn_function(qbuf, (char *) 0, '\0') : GOLD_SYM; + let = !isgold ? yn_function(qbuf, (char *) 0, '\0', TRUE) : GOLD_SYM; if (let == '?' || let == '*') { let = display_used_invlets(splitting ? obj->invlet : 0); if (!let) diff --git a/src/lock.c b/src/lock.c index 9c9edefff..d6f4ec1d5 100644 --- a/src/lock.c +++ b/src/lock.c @@ -855,8 +855,8 @@ doopen_indir(coordxy x, coordxy y) } else if (!u.usteed && (flags.autounlock & AUTOUNLOCK_KICK) != 0 && ynq("Kick it?") == 'y') { - cmdq_add_ec(dokick); - cmdq_add_dir(sgn(cc.x - u.ux), sgn(cc.y - u.uy), 0); + cmdq_add_ec(CQ_CANNED, dokick); + cmdq_add_dir(CQ_CANNED, sgn(cc.x - u.ux), sgn(cc.y - u.uy), 0); res = ECMD_TIME; } } diff --git a/src/nhlua.c b/src/nhlua.c index d7260de8d..ab5ccc694 100644 --- a/src/nhlua.c +++ b/src/nhlua.c @@ -1077,7 +1077,7 @@ nhl_pushkey(lua_State *L) if (argc == 1) { const char *key = luaL_checkstring(L, 1); - cmdq_add_key(key[0]); + cmdq_add_key(CQ_CANNED, key[0]); } return 0; diff --git a/src/o_init.c b/src/o_init.c index 66065fea4..00a1bb80c 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -851,8 +851,7 @@ doclassdisco(void) } } /* get the class (via its symbol character) */ - c = yn_function(prompt, discosyms, '\0'); - savech(c); + c = yn_function(prompt, discosyms, '\0', TRUE); if (!c) clear_nhwindow(WIN_MESSAGE); } else { diff --git a/src/pager.c b/src/pager.c index 114566d2f..b9a5d2b5b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2247,14 +2247,14 @@ dowhatdoes(void) #if defined(UNIX) || defined(VMS) introff(); /* disables ^C but not ^\ */ #endif - q = yn_function("What command?", (char *) 0, '\0'); + q = yn_function("What command?", (char *) 0, '\0', TRUE); #ifdef ALTMETA if (q == '\033' && iflags.altmeta) { /* in an ideal world, we would know whether another keystroke was already pending, but this is not an ideal world... if user typed ESC, we'll essentially hang until another character is typed */ - q = yn_function("]", (char *) 0, '\0'); + q = yn_function("]", (char *) 0, '\0', TRUE); if (q != '\033') q = (char) ((uchar) q | 0200); } diff --git a/src/pickup.c b/src/pickup.c index 21751d2ce..6b4405863 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1937,7 +1937,7 @@ do_loot_cont( && res != ECMD_TIME && ccount == 1 && u_have_forceable_weapon()) { /* single container, and we could #force it open... */ - cmdq_add_ec(doforce); /* doforce asks for confirmation */ + cmdq_add_ec(CQ_CANNED, doforce); /* doforce asks for confirmation */ g.abort_looting = TRUE; } } @@ -2237,7 +2237,7 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot) Sprintf(qbuf, "Do you want to remove the saddle from %s?", x_monnam(mtmp, ARTICLE_THE, (char *) 0, SUPPRESS_SADDLE, FALSE)); - if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { + if ((c = yn_function(qbuf, ynqchars, 'n', TRUE)) == 'y') { if (nolimbs(g.youmonst.data)) { You_cant("do that without limbs."); /* not body_part(HAND) */ return 0; @@ -2890,7 +2890,7 @@ use_container( Strcat(xbuf, "?"); if (*xbuf) Strcat(strcat(pbuf, "\033"), xbuf); - c = yn_function(qbuf, pbuf, more_containers ? 'n' : 'q'); + c = yn_function(qbuf, pbuf, more_containers ? 'n' : 'q', TRUE); } /* PARTIAL|FULL vs other modes */ if (c == '?') { diff --git a/src/potion.c b/src/potion.c index 5fd102e4d..798463f52 100644 --- a/src/potion.c +++ b/src/potion.c @@ -2299,7 +2299,7 @@ dip_into(void) struct obj *obj, *potion; char qbuf[QBUFSZ]; - if (!cmdq_peek()) { + if (!cmdq_peek(CQ_CANNED)) { impossible("dip_into: where is potion?"); return ECMD_FAIL; } diff --git a/src/quest.c b/src/quest.c index ad1b56949..135ee6304 100644 --- a/src/quest.c +++ b/src/quest.c @@ -164,7 +164,7 @@ is_pure(boolean talk) } else if (u.ualign.record < MIN_QUEST_ALIGN) { You("are currently %d and require %d.", u.ualign.record, MIN_QUEST_ALIGN); - if (yn_function("adjust?", (char *) 0, 'y') == 'y') + if (yn_function("adjust?", (char *) 0, 'y', TRUE) == 'y') u.ualign.record = MIN_QUEST_ALIGN; } } diff --git a/src/spell.c b/src/spell.c index f3bf59d18..7ef754713 100644 --- a/src/spell.c +++ b/src/spell.c @@ -715,7 +715,7 @@ getspell(int* spell_no) for (;;) { Snprintf(qbuf, sizeof(qbuf), "Cast which spell? [%s *?]", lets); - ilet = yn_function(qbuf, (char *) 0, '\0'); + ilet = yn_function(qbuf, (char *) 0, '\0', TRUE); if (ilet == '*' || ilet == '?') break; /* use menu mode */ if (index(quitchars, ilet)) diff --git a/win/Qt/qt_map.cpp b/win/Qt/qt_map.cpp index d55da1279..7f067093a 100644 --- a/win/Qt/qt_map.cpp +++ b/win/Qt/qt_map.cpp @@ -530,7 +530,7 @@ void NetHackQtMapViewport::Display(bool block) change.clear(); if (block) { - yn_function("Press a key when done viewing", NULL, '\0'); + yn_function("Press a key when done viewing", NULL, '\0', TRUE); } } diff --git a/win/Qt/qt_xcmd.cpp b/win/Qt/qt_xcmd.cpp index fff29e649..9fc71a15e 100644 --- a/win/Qt/qt_xcmd.cpp +++ b/win/Qt/qt_xcmd.cpp @@ -583,12 +583,6 @@ int NetHackQtExtCmdRequestor::get() exec(); int ret = result() - 1; - if (!::g.in_doagain) { - if (ret >= 0) - savech_extcmd(::extcmdlist[ret].ef_txt, FALSE); - else - savech(0); - } return ret; } diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index 2a027b094..b411510a6 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -1557,12 +1557,8 @@ X11_get_ext_cmd(void) (void) x_event(EXIT_ON_EXIT); if (extended_cmd_selected < 0) { - if (!g.in_doagain) - savech(0); return -1; } - if (!g.in_doagain) - savech_extcmd(command_list[extended_cmd_selected], TRUE); return command_indx[extended_cmd_selected]; } diff --git a/win/curses/cursdial.c b/win/curses/cursdial.c index f380fc5d4..2f5bcd0a3 100644 --- a/win/curses/cursdial.c +++ b/win/curses/cursdial.c @@ -496,20 +496,12 @@ curses_ext_cmd(void) curses_destroy_win(extwin2); if (ret != -1) { - if (!g.in_doagain) - savech_extcmd(cur_choice, TRUE); } else { char extcmd_char = extcmd_initiator(); if (*cur_choice) pline("%s%s: unknown extended command.", visctrl(extcmd_char), cur_choice); - - if (!g.in_doagain) { - savech(0); /* reset do-again buffer */ - if (letter != '\033') - savech(extcmd_char); - } } return ret; } diff --git a/win/tty/getline.c b/win/tty/getline.c index 4da3d0e6f..13309c456 100644 --- a/win/tty/getline.c +++ b/win/tty/getline.c @@ -296,12 +296,9 @@ tty_get_ext_cmd(void) if (nmatches != -1) pline("%s%.60s: unknown extended command.", visctrl(extcmd_char[0]), buf); - savech(0); /* reset do-again buffer */ - savech(extcmd_char[0]); return -1; } - savech_extcmd(buf, TRUE); /* savech() for extcmd_char+buf[...]+'\n' */ return ecmatches[0]; } diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 35667ce8c..0b409ab06 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -1848,12 +1848,6 @@ mswin_get_ext_cmd(void) ret = -1; } - if (!g.in_doagain) { - if (ret >= 0) - savech_extcmd(cmd, TRUE); - else - savech(0); - } return ret; }