Index: doc/README.patch.key_rebinding =================================================================== RCS file: doc/README.patch.key_rebinding diff -N doc/README.patch.key_rebinding --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ doc/README.patch.key_rebinding 24 Aug 2005 02:50:57 -0000 @@ -0,0 +1,172 @@ +Key Rebinding patch + + +This patch will allow simple rebinding of keys (any standard keyboard +key, or a control- or meta- invocation of such) to any command. It will +allow limited changing of the regular (non-number-pad) directional and +special (e.g. "G") keys. It will allow the mapping of one key to a key +combination (e.g. macros). It will allow the changing of which extended +commands (there are now a lot of them) are autocompleted (e.g. #ride and +#quit can be turned off). Finally, it shouldn't have any detrimental +effect on players who don't wish to take advantage of its features. + + +What it does, in full: + +1. Every command has been made an extended command. Thus, there are +now almost 100 extended commands. Because of configurable auto-completion +(see below), this should not change normal game play (unless the user +desires it). + +2. Keyboard commands point to their associated extended command. For +instance, the entry for 'a' points to the #apply command. + +3. Keyboard commands can be rebound in the nethackrc file within the newly +created BINDINGS section. It goes like this: + : -> binds the key to the command +Where can be any one of + x -> regular key + mx -> meta- + cx + ^x -> ctrl- + nnn -> three-digit ascii code (in decimal). _Must_ be 3-digit. + -> the enter key, '\n'. (That's literally "".) + -> the space key, ' '. + -> the escape key, '\033'. Same as 027. +Upper or lower case may be used for m/c, and an optional '-' separator may +come between the special identifier (mc^) and the key/number. In general, +anything listed by the keyboard help (?h) should be properly interpreted (if +not, it's a bug). For example: + BINDINGS=q:quaff,Q:quiver,^x:attributes,097:apply,:wait +sets 'q' to be #quaff, 'Q' to be #quiver, 'ctrl-x' to be #attributes, ascii +char 097 ('a') to be #apply, and the space bar to be #wait (in other +words, changing nothing). Any extended command can be bound. Note that +a number of characters are not bindable without the use of ascii codes. + There is a reserved pseudo-extended command, "nothing", used to unbind +the key. I.e. + BINDINGS=q:nothing +will unbind the q key. + The binding can also be done as part of an OPTIONS line. This allows +it to be included in the NETHACKOPTIONS environment variable, for instance, +but is considerably longer if you're doing many bindings. For example: + OPTIONS=bind:q:quaff,bind:Q:quiver +will bind q to #quaff and Q to #quiver. + +4. As Dion Nicolaas suggested, directional buttons can be rebound in the +nathackrc file in the OPTIONS section. This affects only the standard +directional keys, not the number_pad ones. For instance: + OPTIONS=directionkeys:h y k u l n j b > < +Only the "dir" is significant in the option name. + The parsing for these keys is identical to that for key binding (see +#3, above). However, the 8 regular-direction keys must be lower-case +letters, since shift-letter and ctrl-letter have other meanings. + The directional keys will take priority over the command keys, and are +quite different - for instance, they're used to specify a direction for +zapping. + Note that < and > are commands *and* directional buttons - and can be +rebound to be different keys, which would probably be bad. + These directionkeys will be completely ignored if number_pad is set. + +5. Similarly, special keys can be rebound: + OPTIONS=specialkeys:g G F m M ^A +These must not be duplicated. Naturally, they are interpreted identically to +other keys (see #3 above). See the guidebook for more information on what +these keys do (or do ?h). + Notes: ^A will be ignored if REDO isn't compiled into your game. + is hard-coded into the game in many places that haven't been replaced. +There is another special key, ctrl-c, that has not been modified at all (yet). + +6. Nethack will now only autocomplete those extended commands marked to +be autocompleted - i.e. only the original commands. This is great for those +commands, but awful if you want to use any other commands - but then, those +other commands weren't there before at all, so you're not losing anything. + The autocomplete code is window-specific. I have only changed the +code for tty mode; all others will just ignore it and autocomplete +everything (those that use autocomplete at all). This shouldn't be hard to +update. (I know some window systems pop up a menu of buttons. I imagine +this menu should include only autocompleted commands, and have a "see all +commands" button that shows all of them.) + Which commands are autocompleted is shown when you get a list of +extended commands from within the game (? command). + +7. Ilkka Virta suggested that an AUTOCOMPLETE segment be added to allow +the user to choose which extended commands were auto-completed, as in: + AUTOCOMPLETE=ride,pray,!quiver +This just modifies the standard autocomplete settings that are compiled in +(see #6 above), so the AUTOCOMPLETE line above will make no changes. On the +other hand, some people might want to use + AUTOCOMPLETE=!ride,!quit +since I've heard some find it inconvienient that '#r' doesn't go straight +to rub (they never use riding), and removing quit makes it harder to +accidentally quit the game. + Just like the BINDINGS, this can be included in the OPTIONS as well. +This may come to replace the old syntax: + OPTIONS=noautocomplete:ride:!!quit + +8. The help for extended commands (formerly brought up with the ?h command +sequence) has been modified to list *all* extended commands, and mark which +of them are currently autocompleted. The descriptive texts for the new +extended commands are taken from the help entries for the commands they're +based upon. + +9. The help for keyboard commands (generally brought up with the ?b command +sequence) has not been changed. I started to do this, then realized it wasn't +worth it at all. Instead, a new help screen has been created (this idea +originally from J. Ali Harlow). It is currently labelled as "Full list of +keyboard commands" (generally ?h). This dynamically creates a full list of +commands. It's not as graphically pretty or well-organized as the original +list (which is kept around for these reasons), but since it's created +on-the-fly it will take into account changed bindings as well as (in theory) +other options (including number_pad, rest_on_space, and REDO). + +10. The same code that interprets the key lists above is now used to interpret +the MONSTER, etc. lines in the nethackrc file. This means two things: (1) all +numeric entries must include the full 3 decimal digits and (2) the extra +character values (i.e. a, m-a, ^a, ) can be used as well. + +11. Key mappings (macros) are available as well as key bindings. A key +mapping maps one key to one or more keys. For instance: + MAPPINGS=h:Z a, i:n 3 0 s, j:Z a 6, k:z z +will map the h key to Z and then a. This will automatically cast the first +spell on your list. Mapped keys are interpreted only in place of command keys +(i.e instead of h moving you, it will execute Z a; h will still work normally +when prompted about what spell to cast or item to apply). However, command +keys will take precedence over mapped keys, so you'll need to unbind the +command key you wish to map. There is no checking for infinite loops yet -- +WATCH OUT. When the mapping takes place (i.e. you hit 'h'), the mapped-to +keys will be placed in a queue. This queue will be checked almost every time +that the game wants a key entry. 'i' can therefore be used to search 30 times +(under number_pad). 'j' will cast your first spell eastward (under +number_pad); note that if you run low on magic points, the Z a will fail and +the 6 will move you east. 'k' will zap wand 'z'. + Notes: mappings may work wierdly with REDO's. For instance, I'm not +sure what n30k would do. You can also use this in an options line as + OPTIONS=map:h:n 3 0 s,bind:h:nothing +Finally, this hasn't been tested much. + + +What it doesn't do: + +1. The names for the extended commands are currently less than ideal. + +2. There are no additional key mappings available (i.e. no sample nethackrc +files). Those who use dvorak will no doubt want to make such a sample file. +Any other ideas for good mappings would also be appreciated. Send them to me +to be included along with the patch itself. + +3. There is no means for binding multi-byte escape sequences. I actually +coded this up, but the code is kept separate right now. + + +Bugs: + +1. There is no documentation in the guidebook. In the meantime, this +document serves as documentation. + +2. Key mappings are almost certainly buggy. + +3. The update for 3.4.3 is incomplete. It need a full audit. In particular, + I'm not sure if all of the new commands are included in the extended + command list (I added #travel/'_' but that's all). + +--jason short Index: include/decl.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/decl.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 decl.h --- include/decl.h 23 Aug 2005 21:43:11 -0000 1.1.1.1 +++ include/decl.h 23 Aug 2005 22:45:35 -0000 @@ -195,8 +195,33 @@ E const char *nomovemsg; E const char nul[]; E char lock[]; -E const char sdir[], ndir[]; +/* sdir is the regular direction keys (modifyable). + * ndir is the number_pad direction keys. + * xdir/ydir/zdir holds the directions of movement for each of the sdir and + * ndir keys. + * misc_cmds holds all other special keyboard commands. */ +E char sdir[]; +E const char ndir[]; E const schar xdir[], ydir[], zdir[]; +E char misc_cmds[]; + +#define DORUSH misc_cmds[0] +#define DORUN misc_cmds[1] +#define DOFORCEFIGHT misc_cmds[2] +#define DONOPICKUP misc_cmds[3] +#define DORUN_NOPICKUP misc_cmds[4] +#define DOESCAPE misc_cmds[5] +#ifdef REDO /* JDS: moved from config.h */ +# undef DOAGAIN /* remove previous definition from config.h */ +# define DOAGAIN misc_cmds[6] +#endif + +/* the number of miscellaneous commands */ +#ifdef REDO +# define MISC_CMD_COUNT 7 +#else +# define MISC_CMD_COUNT 6 +#endif E NEARDATA schar tbx, tby; /* set in mthrowu.c */ Index: include/extern.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/extern.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 extern.h --- include/extern.h 23 Aug 2005 21:43:11 -0000 1.1.1.1 +++ include/extern.h 23 Aug 2005 22:47:58 -0000 @@ -158,10 +158,9 @@ E char NDECL(pgetchar); E void FDECL(pushch, (CHAR_P)); E void FDECL(savech, (CHAR_P)); #endif -#ifdef WIZARD -E void NDECL(add_debug_extended_commands); -#endif /* WIZARD */ +E char NDECL(nhgetch); E void FDECL(rhack, (char *)); +E void NDECL(dokeylist); E int NDECL(doextlist); E int NDECL(extcmd_via_menu); E void FDECL(enlightenment, (int)); @@ -178,6 +177,14 @@ E char NDECL(readchar); #ifdef WIZARD E void NDECL(sanity_check); #endif +E void NDECL(commands_init); +E char* FDECL(stripspace, (char*)); +E void FDECL(parsebindings, (char*)); +E void FDECL(parseautocomplete, (char*,boolean)); +E void FDECL(parsemappings, (char*)); +E char FDECL(txt2key, (char*)); +E char* FDECL(key2txt, (char, char*)); +E char* FDECL(str2txt, (char*, char*)); E char FDECL(yn_function, (const char *, const char *, CHAR_P)); /* ### dbridge.c ### */ @@ -647,6 +654,7 @@ E boolean FDECL(can_read_file, (const ch #endif E void FDECL(read_config_file, (const char *)); E void FDECL(check_recordfile, (const char *)); +E int FDECL(get_uchar_list, (char*, uchar*, int)); #if defined(WIZARD) E void NDECL(read_wizkit); #endif Index: include/func_tab.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/func_tab.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 func_tab.h --- include/func_tab.h 23 Aug 2005 21:43:11 -0000 1.1.1.1 +++ include/func_tab.h 24 Aug 2005 01:52:18 -0000 @@ -5,17 +5,29 @@ #ifndef FUNC_TAB_H #define FUNC_TAB_H -struct func_tab { - char f_char; - boolean can_if_buried; - int NDECL((*f_funct)); - const char *f_text; -}; - struct ext_func_tab { const char *ef_txt, *ef_desc; int NDECL((*ef_funct)); boolean can_if_buried; + boolean autocomplete; + + /* for interrupted rpeteats; e.g., + * "searching" => "You stop searching." */ + const char *f_text; +}; + +/* Tells what to do on a command key press: either an extended command or + * mapped to another set of characters (macro) */ +struct key_tab { + struct ext_func_tab * bind_cmd; + char * map_list; +}; + +/* Linked list of bindings; see "crappy hack" in cmd.c */ +struct binding_list_tab { + char key; /* ascii code for key */ + char* extcmd; /* extended command key is going to be rebound to */ + struct binding_list_tab * next; }; extern struct ext_func_tab extcmdlist[]; Index: include/global.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/global.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 global.h --- include/global.h 23 Aug 2005 21:43:11 -0000 1.1.1.1 +++ include/global.h 24 Aug 2005 01:47:51 -0000 @@ -133,9 +133,10 @@ typedef xchar boolean; /* 0 or 1 */ #ifdef REDO #define Getchar pgetchar +#else +#define Getchar nhgetch #endif - #include "coord.h" /* * Automatic inclusions for the subsidiary files. Index: include/ntconf.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/ntconf.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 ntconf.h --- include/ntconf.h 23 Aug 2005 21:43:12 -0000 1.1.1.1 +++ include/ntconf.h 24 Aug 2005 01:48:16 -0000 @@ -174,11 +174,6 @@ int _RTLENTRY _EXPFUNC read (int __han #define ALLOCA_HACK /* used in util/panic.c */ #endif -#ifndef REDO -#undef Getchar -#define Getchar nhgetch -#endif - #ifdef _MSC_VER #if 0 #pragma warning(disable:4018) /* signed/unsigned mismatch */ Index: include/os2conf.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/os2conf.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 os2conf.h --- include/os2conf.h 23 Aug 2005 21:43:12 -0000 1.1.1.1 +++ include/os2conf.h 24 Aug 2005 01:48:29 -0000 @@ -97,11 +97,6 @@ #include #endif -#ifndef REDO -# undef Getchar -# define Getchar nhgetch -#endif - void hangup(int i); #endif /* OS2CONF_H */ #endif /* OS2 */ Index: include/pcconf.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/pcconf.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 pcconf.h --- include/pcconf.h 23 Aug 2005 21:43:12 -0000 1.1.1.1 +++ include/pcconf.h 24 Aug 2005 01:48:40 -0000 @@ -228,11 +228,6 @@ #include -#ifndef REDO -# undef Getchar -# define Getchar nhgetch -#endif - #ifdef MSDOS # define TEXTCOLOR /* */ # define PORT_HELP "msdoshlp.txt" /* msdos port specific help file */ Index: include/unixconf.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/unixconf.h,v retrieving revision 1.2 diff -p -u -r1.2 unixconf.h --- include/unixconf.h 23 Aug 2005 22:36:39 -0000 1.2 +++ include/unixconf.h 24 Aug 2005 01:48:59 -0000 @@ -265,9 +265,6 @@ #define HLOCK "perm" /* an empty file used for locking purposes */ -#ifndef REDO -#define Getchar nhgetch -#endif #define tgetch getchar #define SHELL /* do not delete the '!' command */ Index: include/vmsconf.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/vmsconf.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 vmsconf.h --- include/vmsconf.h 23 Aug 2005 21:43:13 -0000 1.1.1.1 +++ include/vmsconf.h 24 Aug 2005 01:49:07 -0000 @@ -207,9 +207,6 @@ typedef __mode_t mode_t; # define O_TRUNC 0x400 #endif -#ifndef REDO -# define Getchar nhgetch -#endif #define tgetch vms_getchar #include "system.h" Index: include/winprocs.h =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/include/winprocs.h,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 winprocs.h --- include/winprocs.h 23 Aug 2005 21:43:13 -0000 1.1.1.1 +++ include/winprocs.h 24 Aug 2005 01:49:19 -0000 @@ -105,7 +105,7 @@ extern NEARDATA struct window_procs wind #define print_glyph (*windowprocs.win_print_glyph) #define raw_print (*windowprocs.win_raw_print) #define raw_print_bold (*windowprocs.win_raw_print_bold) -#define nhgetch (*windowprocs.win_nhgetch) +#define nhwingetch (*windowprocs.win_nhgetch) #define nh_poskey (*windowprocs.win_nh_poskey) #define nhbell (*windowprocs.win_nhbell) #define nh_doprev_message (*windowprocs.win_doprev_message) Index: src/allmain.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/allmain.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 allmain.c --- src/allmain.c 23 Aug 2005 21:43:13 -0000 1.1.1.1 +++ src/allmain.c 23 Aug 2005 22:53:31 -0000 @@ -50,9 +50,7 @@ moveloop() monstr_init(); /* monster strengths */ objects_init(); -#ifdef WIZARD - if (wizard) add_debug_extended_commands(); -#endif + commands_init(); (void) encumber_msg(); /* in case they auto-picked up something */ Index: src/cmd.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/cmd.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 cmd.c --- src/cmd.c 23 Aug 2005 21:43:14 -0000 1.1.1.1 +++ src/cmd.c 24 Aug 2005 02:35:22 -0000 @@ -2,6 +2,8 @@ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ +#include + #include "hack.h" #include "func_tab.h" /* #define DEBUG */ /* uncomment for debugging */ @@ -144,6 +146,15 @@ STATIC_PTR int NDECL(doattributes); STATIC_PTR int NDECL(doconduct); /**/ STATIC_PTR boolean NDECL(minimal_enlightenment); +static void FDECL(bind_key, (unsigned char, char*)); +static void NDECL(init_bind_list); +static void NDECL(change_bind_list); +static void NDECL(verify_key_list); +#ifdef WIZARD +static void NDECL(add_debug_extended_commands); +#endif /* WIZARD */ +static void FDECL(addchar, (char)); + #ifdef OVLB STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *)); STATIC_DCL char *FDECL(enlght_combatinc, (const char *,int,int,char *)); @@ -280,6 +291,46 @@ char ch; } #endif /* REDO */ +/* mappings are held in a circular queue */ +#define CQ_SIZE 100 +static int cq_tail = 0; /* exit point; index for oldest element */ +static int cq_head = 0; /* entry point; index for next element */ +static char cq_list[CQ_SIZE]; + +/* This is intended to come "in front of" the old nhgetch so that if there's + * a mapping/macro, it will insert the necessary keys instead. + * However, most window-specific code doesn't call nhgetch, but instead calls + * _nhgetch. I've tried to change all of the appropriate + * _nhgetch's to nhgetch's in win/, but there's a good chance of + * bugs here. + */ +char +nhgetch(void) +{ + int ch; + + if (cq_head != cq_tail) { + ch = cq_list[cq_tail]; + cq_tail = (cq_tail + 1) % CQ_SIZE; + } else { + ch = nhwingetch(); /* old definition */ + } + + return ch; +} + +static void +addchar(ch) + char ch; +{ + cq_list[cq_head] = ch; + cq_head = (cq_head + 1) % CQ_SIZE; + if (cq_head == cq_tail) { + /* character dropped */ + cq_head = (cq_head + CQ_SIZE - 1) % CQ_SIZE; + } +} + #endif /* OVL1 */ #ifdef OVLB @@ -314,16 +365,23 @@ doextlist() /* here after #? - now list putstr(datawin, 0, ""); for(efp = extcmdlist; efp->ef_txt; efp++) { - Sprintf(buf, " %-15s - %s.", efp->ef_txt, efp->ef_desc); + /* Show name and text for each command. Autocompleted + * commands are marked with an asterisk ('*'). */ + Sprintf(buf, " %c %-15s - %s.", + efp->autocomplete ? '*' : ' ', + efp->ef_txt, efp->ef_desc); putstr(datawin, 0, buf); } + putstr(datawin, 0, ""); + putstr(datawin, 0, + " Commands marked with a * will be autocompleted."); display_nhwindow(datawin, FALSE); destroy_nhwindow(datawin); return 0; } #ifdef TTY_GRAPHICS -#define MAX_EXT_CMD 40 /* Change if we ever have > 40 ext cmds */ +#define MAX_EXT_CMD 200 /* Change if we have more ext cmds */ /* * This is currently used only by the tty port and is * controlled via runtime option 'extmenu' @@ -1344,6 +1402,12 @@ int final; #endif /* OVLB */ #ifdef OVL1 +/* Macros for meta and ctrl modifiers: + * M and C return the meta/ctrl code for the given character; + * e.g., (C('c') is ctrl-c + * ISMETA and ISCTRL return TRUE iff the code is a meta/ctrl code + * UNMETA and UNCTRL are the opposite of M/C and return the key for a given + * meta/ctrl code. */ #ifndef M # ifndef NHSTDC # define M(c) (0x80 | (c)) @@ -1351,209 +1415,356 @@ int final; # define M(c) ((c) - 128) # endif /* NHSTDC */ #endif +#define ISMETA(c) (((c) & 0x80) != 0) +#define UNMETA(c) ((c) & 0x7f) + #ifndef C #define C(c) (0x1f & (c)) #endif +#define ISCTRL(c) ((uchar)(c) < 0x20) +#define UNCTRL(c) (ISCTRL(c) ? (0x60 | (c)) : (c)) -static const struct func_tab cmdlist[] = { - {C('d'), FALSE, dokick}, /* "D" is for door!...? Msg is in dokick.c */ -#ifdef WIZARD - {C('e'), TRUE, wiz_detect}, - {C('f'), TRUE, wiz_map}, - {C('g'), TRUE, wiz_genesis}, - {C('i'), TRUE, wiz_identify}, -#endif - {C('l'), TRUE, doredraw}, /* if number_pad is set */ -#ifdef WIZARD - {C('o'), TRUE, wiz_where}, -#endif - {C('p'), TRUE, doprev_message}, - {C('r'), TRUE, doredraw}, - {C('t'), TRUE, dotele}, -#ifdef WIZARD - {C('v'), TRUE, wiz_level_tele}, - {C('w'), TRUE, wiz_wish}, -#endif - {C('x'), TRUE, doattributes}, -#ifdef SUSPEND - {C('z'), TRUE, dosuspend}, -#endif - {'a', FALSE, doapply}, - {'A', FALSE, doddoremarm}, - {M('a'), TRUE, doorganize}, -/* 'b', 'B' : go sw */ - {'c', FALSE, doclose}, - {'C', TRUE, do_mname}, - {M('c'), TRUE, dotalk}, - {'d', FALSE, dodrop}, - {'D', FALSE, doddrop}, - {M('d'), FALSE, dodip}, - {'e', FALSE, doeat}, - {'E', FALSE, doengrave}, - {M('e'), TRUE, enhance_weapon_skill}, - {'f', FALSE, dofire}, -/* 'F' : fight (one time) */ - {M('f'), FALSE, doforce}, -/* 'g', 'G' : multiple go */ -/* 'h', 'H' : go west */ - {'h', TRUE, dohelp}, /* if number_pad is set */ - {'i', TRUE, ddoinv}, - {'I', TRUE, dotypeinv}, /* Robert Viduya */ - {M('i'), TRUE, doinvoke}, -/* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ - {'j', FALSE, dojump}, /* if number_pad is on */ - {M('j'), FALSE, dojump}, - {'k', FALSE, dokick}, /* if number_pad is on */ - {'l', FALSE, doloot}, /* if number_pad is on */ - {M('l'), FALSE, doloot}, -/* 'n' prefixes a count if number_pad is on */ - {M('m'), TRUE, domonability}, - {'N', TRUE, ddocall}, /* if number_pad is on */ - {M('n'), TRUE, ddocall}, - {M('N'), TRUE, ddocall}, - {'o', FALSE, doopen}, - {'O', TRUE, doset}, - {M('o'), FALSE, dosacrifice}, - {'p', FALSE, dopay}, - {'P', FALSE, doputon}, - {M('p'), TRUE, dopray}, - {'q', FALSE, dodrink}, - {'Q', FALSE, dowieldquiver}, - {M('q'), TRUE, done2}, - {'r', FALSE, doread}, - {'R', FALSE, doremring}, - {M('r'), FALSE, dorub}, - {'s', TRUE, dosearch, "searching"}, - {'S', TRUE, dosave}, - {M('s'), FALSE, dosit}, - {'t', FALSE, dothrow}, - {'T', FALSE, dotakeoff}, - {M('t'), TRUE, doturn}, -/* 'u', 'U' : go ne */ - {'u', FALSE, dountrap}, /* if number_pad is on */ - {M('u'), FALSE, dountrap}, - {'v', TRUE, doversion}, - {'V', TRUE, dohistory}, - {M('v'), TRUE, doextversion}, - {'w', FALSE, dowield}, - {'W', FALSE, dowear}, - {M('w'), FALSE, dowipe}, - {'x', FALSE, doswapweapon}, - {'X', TRUE, enter_explore_mode}, -/* 'y', 'Y' : go nw */ - {'z', FALSE, dozap}, - {'Z', TRUE, docast}, - {'<', FALSE, doup}, - {'>', FALSE, dodown}, - {'/', TRUE, dowhatis}, - {'&', TRUE, dowhatdoes}, - {'?', TRUE, dohelp}, - {M('?'), TRUE, doextlist}, -#ifdef SHELL - {'!', TRUE, dosh}, -#endif - {'.', TRUE, donull, "waiting"}, - {' ', TRUE, donull, "waiting"}, - {',', FALSE, dopickup}, - {':', TRUE, dolook}, - {';', TRUE, doquickwhatis}, - {'^', TRUE, doidtrap}, - {'\\', TRUE, dodiscovered}, /* Robert Viduya */ - {'@', TRUE, dotogglepickup}, - {M('2'), FALSE, dotwoweapon}, - {WEAPON_SYM, TRUE, doprwep}, - {ARMOR_SYM, TRUE, doprarm}, - {RING_SYM, TRUE, doprring}, - {AMULET_SYM, TRUE, dopramulet}, - {TOOL_SYM, TRUE, doprtool}, - {'*', TRUE, doprinuse}, /* inventory of all equipment in use */ - {GOLD_SYM, TRUE, doprgold}, - {SPBOOK_SYM, TRUE, dovspell}, /* Mike Stephenson */ - {'#', TRUE, doextcmd}, - {'_', TRUE, dotravel}, - {0,0,0,0} -}; +/* maps extended ascii codes for key presses to either + * - extended command entries in extcmdlist + * - other key press entries */ +static struct key_tab cmdlist[256]; + +/* list built upon option loading; holds list of keys to be rebound later + * see "crappy hack" below */ +static struct binding_list_tab *bindinglist = NULL; + +#define AUTOCOMPLETE TRUE +#define IFBURIED TRUE + +#define EXTCMDLIST_SIZE (sizeof(extcmdlist) / sizeof(extcmdlist[1])) struct ext_func_tab extcmdlist[] = { - {"adjust", "adjust inventory letters", doorganize, TRUE}, - {"chat", "talk to someone", dotalk, TRUE}, /* converse? */ - {"conduct", "list which challenges you have adhered to", doconduct, TRUE}, - {"dip", "dip an object into something", dodip, FALSE}, - {"enhance", "advance or check weapons skills", enhance_weapon_skill, - TRUE}, - {"force", "force a lock", doforce, FALSE}, - {"invoke", "invoke an object's powers", doinvoke, TRUE}, - {"jump", "jump to a location", dojump, FALSE}, - {"loot", "loot a box on the floor", doloot, FALSE}, - {"monster", "use a monster's special ability", domonability, TRUE}, - {"name", "name an item or type of object", ddocall, TRUE}, - {"offer", "offer a sacrifice to the gods", dosacrifice, FALSE}, - {"pray", "pray to the gods for help", dopray, TRUE}, - {"quit", "exit without saving current game", done2, TRUE}, + + {"apply", "apply (use) a tool (pick-axe, key, lamp...)", doapply, !IFBURIED}, + {"attributes", "show your attributes (intrinsic ones included in debug or explore mode)", doattributes, IFBURIED}, + {"close", "close a door", doclose, !IFBURIED}, + {"cast", "zap (cast) a spell", docast, IFBURIED}, + {"discoveries", "show what object types have been discovered", dodiscovered, IFBURIED}, + {"down", "go down a staircase", dodown, !IFBURIED}, + {"drop", "drop an item", dodrop, !IFBURIED}, + {"dropall", "drop specific item types", doddrop, !IFBURIED}, + {"takeoffall", "remove all armor", doddoremarm, !IFBURIED}, + {"inventory", "show your inventory", ddoinv, IFBURIED}, + {"quaff", "quaff (drink) something", dodrink, !IFBURIED}, + {"#", "perform an extended command", doextcmd, IFBURIED}, + {"travel", "Travel to a specific location", dotravel, !IFBURIED}, + {"eat", "eat something", doeat, !IFBURIED}, + {"engrave", "engrave writing on the floor", doengrave, !IFBURIED}, + {"fire", "fire ammunition from quiver", dofire, !IFBURIED}, + {"history", "show long version and game history", dohistory, IFBURIED}, + {"help", "give a help message", dohelp, IFBURIED}, + {"seetrap", "show the type of a trap", doidtrap, IFBURIED}, + {"kick", "kick something", dokick, !IFBURIED}, + {"look", "loot a box on the floor", dolook, IFBURIED}, + {"call", "call (name) a particular monster", do_mname, IFBURIED}, + {"wait", "rest one move while doing nothing", donull, IFBURIED}, + {"previous", "toggle through previously displayed game messages", doprev_message, IFBURIED}, + {"open", "open a door", doopen, !IFBURIED}, + {"pickup", "pick up things at the current location", dopickup, !IFBURIED}, + {"pay", "pay your shopping bill", dopay, !IFBURIED}, + {"puton", "put on an accessory (ring amulet, etc)", doputon, !IFBURIED}, + {"seeweapon", "show the weapon currently wielded", doprwep, IFBURIED}, + {"seearmor", "show the armor currently worn", doprarm, IFBURIED}, + {"seerings", "show the ring(s) currently worn", doprring, IFBURIED}, + {"seeamulet", "show the amulet currently worn", dopramulet, IFBURIED}, + {"seetools", "show the tools currently in use", doprtool, IFBURIED}, + {"seeall", "show all equipment in use (generally, ),[,=,\",( commands", doprinuse, IFBURIED}, + {"seegold", "count your gold", doprgold, IFBURIED}, + {"glance", "show what type of thing a map symbol on the level corresponds to", doquickwhatis, IFBURIED}, + {"remove", "remove an accessory (ring, amulet, etc)", doremring, !IFBURIED}, + {"read", "read a scroll or spellbook", doread, !IFBURIED}, + {"redraw", "redraw screen", doredraw, IFBURIED}, +#ifdef SUSPEND + {"suspend", "suspend game (only if defined)", dosuspend, IFBURIED}, +#endif /* SUSPEND */ + {"setoptions", "show option settings, possibly change them", doset, IFBURIED}, + {"search", "search for traps and secret doors", dosearch, IFBURIED, !AUTOCOMPLETE, "searching"}, + {"save", "save the game", dosave, IFBURIED}, + {"swap", "swap wielded and secondary weapons", doswapweapon, !IFBURIED}, + {"shell", "do a shell escape (only if defined)", dosh, IFBURIED}, + {"throw", "throw something", dothrow, !IFBURIED}, + {"takeoff", "take off one piece of armor", dotakeoff, !IFBURIED}, + {"teleport", "teleport around level", dotele, IFBURIED}, + {"inventoryall", "inventory specific item types", dotypeinv, IFBURIED}, + {"autopickup", "toggle the pickup option on/off", dotogglepickup, IFBURIED}, + {"up", "go up a staircase", doup, !IFBURIED}, + {"version", "show version", doversion, IFBURIED}, + {"seespells", "list known spells", dovspell, IFBURIED}, + {"quiver", "select ammunition for quiver", dowieldquiver, !IFBURIED}, + {"whatis", "show what type of thing a symbol corresponds to", dowhatis, IFBURIED}, + {"whatdoes", "tell what a command does", dowhatdoes, IFBURIED}, + {"wield", "wield (put in use) a weapon", dowield, !IFBURIED}, + {"wear", "wear a piece of armor", dowear, !IFBURIED}, + {"zap", "zap a wand", dozap, !IFBURIED}, + {"explore_mode", "enter explore (discovery) mode (only if defined)", enter_explore_mode, IFBURIED}, + + {"adjust", "adjust inventory letters", doorganize, IFBURIED, AUTOCOMPLETE}, + {"chat", "talk to someone", dotalk, IFBURIED, AUTOCOMPLETE}, /* converse? */ + {"conduct", "list which challenges you have adhered to", doconduct, IFBURIED, AUTOCOMPLETE}, + {"dip", "dip an object into something", dodip, !IFBURIED, AUTOCOMPLETE}, + {"enhance", "advance or check weapons skills", enhance_weapon_skill, IFBURIED, AUTOCOMPLETE}, + {"force", "force a lock", doforce, !IFBURIED, AUTOCOMPLETE}, + {"invoke", "invoke an object's powers", doinvoke, IFBURIED, AUTOCOMPLETE}, + {"jump", "jump to a location", dojump, !IFBURIED, AUTOCOMPLETE}, + {"loot", "loot a box on the floor", doloot, !IFBURIED, AUTOCOMPLETE}, + {"monster", "use a monster's special ability", domonability, IFBURIED, AUTOCOMPLETE}, + {"name", "name an item or type of object", ddocall, IFBURIED, AUTOCOMPLETE}, + {"offer", "offer a sacrifice to the gods", dosacrifice, !IFBURIED, AUTOCOMPLETE}, + {"pray", "pray to the gods for help", dopray, IFBURIED, AUTOCOMPLETE}, + {"quit", "exit without saving current game", done2, IFBURIED, AUTOCOMPLETE}, #ifdef STEED - {"ride", "ride (or stop riding) a monster", doride, FALSE}, + {"ride", "ride (or stop riding) a monster", doride, !IFBURIED, AUTOCOMPLETE}, #endif - {"rub", "rub a lamp or a stone", dorub, FALSE}, - {"sit", "sit down", dosit, FALSE}, - {"turn", "turn undead", doturn, TRUE}, - {"twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE}, - {"untrap", "untrap something", dountrap, FALSE}, - {"version", "list compile time options for this version of NetHack", - doextversion, TRUE}, - {"wipe", "wipe off your face", dowipe, FALSE}, - {"?", "get this list of extended commands", doextlist, TRUE}, + {"rub", "rub a lamp", dorub, !IFBURIED, AUTOCOMPLETE}, + {"sit", "sit down", dosit, !IFBURIED, AUTOCOMPLETE}, +#ifdef STICKY_COMMAND + {"sticky", "set 'sticky' inventory slots", dosticky, IFBURIED, AUTOCOMPLETE}, +#endif /* STICKY_COMMAND */ + {"turn", "turn undead", doturn, IFBURIED, AUTOCOMPLETE}, + {"twoweapon", "toggle two-weapon combat", dotwoweapon, !IFBURIED, AUTOCOMPLETE}, + {"untrap", "untrap something", dountrap, !IFBURIED, AUTOCOMPLETE}, + {"versionext", "list compile time options for this version of NetHack", + doextversion, IFBURIED, AUTOCOMPLETE}, + {"wipe", "wipe off your face", dowipe, !IFBURIED, AUTOCOMPLETE}, + {"?", "get this list of extended commands", doextlist, IFBURIED, AUTOCOMPLETE}, #if defined(WIZARD) - /* - * There must be a blank entry here for every entry in the table - * below. - */ - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, -#ifdef DEBUG_MIGRATING_MONS - {(char *)0, (char *)0, donull, TRUE}, -#endif - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, -#ifdef PORT_DEBUG - {(char *)0, (char *)0, donull, TRUE}, -#endif - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, - {(char *)0, (char *)0, donull, TRUE}, + /* + * There must be a blank entry here for every entry in the table + * below. + */ + {(char *)0, (char *)0, donull, TRUE}, /* #light sources */ + {(char *)0, (char *)0, donull, TRUE}, /* #seeenv */ + {(char *)0, (char *)0, donull, TRUE}, /* #stats */ + {(char *)0, (char *)0, donull, TRUE}, /* #timeout */ +#ifdef WIZ_LEVEL_GAIN + {(char *)0, (char *)0, donull, TRUE}, /* #levelgain */ +#endif +#ifdef SHOW_MONSTERS_BORN + {(char *)0, (char *)0, donull, TRUE}, /* #showkills */ +#endif /* SHOW_MONSTERS_BORN */ +#ifdef WIZ_POLY + {(char *)0, (char *)0, donull, TRUE}, /* #poly */ +#endif /* WIZ_POLY */ #ifdef DEBUG - {(char *)0, (char *)0, donull, TRUE}, + {(char *)0, (char *)0, donull, TRUE}, /* #wizdebug */ #endif - {(char *)0, (char *)0, donull, TRUE}, -#endif - {(char *)0, (char *)0, donull, TRUE} /* sentinel */ + {(char *)0, (char *)0, donull, TRUE}, /* #vision */ + {(char *)0, (char *)0, donull, TRUE}, /* #wmode */ + {(char *)0, (char *)0, donull, TRUE}, /* #detect */ + {(char *)0, (char *)0, donull, TRUE}, /* #map */ + {(char *)0, (char *)0, donull, TRUE}, /* #genesis */ + {(char *)0, (char *)0, donull, TRUE}, /* #identify */ + {(char *)0, (char *)0, donull, TRUE}, /* #levelport */ + {(char *)0, (char *)0, donull, TRUE}, /* #wish */ + {(char *)0, (char *)0, donull, TRUE}, /* #where */ +#endif /* WIZARD */ }; #if defined(WIZARD) -static const struct ext_func_tab debug_extcmdlist[] = { - {"levelchange", "change experience level", wiz_level_change, TRUE}, - {"lightsources", "show mobile light sources", wiz_light_sources, TRUE}, +static struct ext_func_tab debug_extcmdlist[] = { + {"levelchange", "change experience level", wiz_level_change, IFBURIED, AUTOCOMPLETE}, + {"lightsources", "show mobile light sources", wiz_light_sources, IFBURIED, AUTOCOMPLETE}, #ifdef DEBUG_MIGRATING_MONS - {"migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE}, + {"migratemons", "migrate n random monsters", wiz_migrate_mons, IFBURIED, AUTOCOMPLETE}, #endif - {"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, TRUE}, - {"panic", "test panic routine (fatal to game)", wiz_panic, TRUE}, - {"polyself", "polymorph self", wiz_polyself, TRUE}, + {"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, IFBURIED, AUTOCOMPLETE}, + {"panic", "test panic routine (fatal to game)", wiz_panic, IFBURIED, AUTOCOMPLETE}, + {"polyself", "polymorph self", wiz_polyself, IFBURIED, AUTOCOMPLETE}, #ifdef PORT_DEBUG - {"portdebug", "wizard port debug command", wiz_port_debug, TRUE}, + {"portdebug", "wizard port debug command", wiz_port_debug, IFBURIED, AUTOCOMPLETE}, #endif - {"seenv", "show seen vectors", wiz_show_seenv, TRUE}, - {"stats", "show memory statistics", wiz_show_stats, TRUE}, - {"timeout", "look at timeout queue", wiz_timeout_queue, TRUE}, - {"vision", "show vision array", wiz_show_vision, TRUE}, + {"seenv", "show seen vectors", wiz_show_seenv, IFBURIED, AUTOCOMPLETE}, + {"stats", "show memory statistics", wiz_show_stats, IFBURIED, AUTOCOMPLETE}, + {"timeout", "look at timeout queue", wiz_timeout_queue, IFBURIED, AUTOCOMPLETE}, + {"vision", "show vision array", wiz_show_vision, IFBURIED, AUTOCOMPLETE}, #ifdef DEBUG - {"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE}, + {"wizdebug", "wizard debug command", wiz_debug_cmd, IFBURIED, AUTOCOMPLETE}, #endif - {"wmode", "show wall modes", wiz_show_wmodes, TRUE}, - {(char *)0, (char *)0, donull, TRUE} + {"wmode", "show wall modes", wiz_show_wmodes, IFBURIED, AUTOCOMPLETE}, + + {"detect", "detect secret doors and traps", wiz_detect, IFBURIED}, + {"map", "do magic mapping", wiz_map, IFBURIED}, + {"genesis", "create monster", wiz_genesis, IFBURIED}, + {"identify", "identify items in pack", wiz_identify, IFBURIED}, + {"levelport", "to trans-level teleport", wiz_level_tele, IFBURIED}, + {"wish", "make wish", wiz_wish, IFBURIED}, + {"where", "tell locations of special levels", wiz_where, IFBURIED}, + {(char *)0, (char *)0, donull, IFBURIED} }; +static void +bind_key(key, command) + unsigned char key; + char* command; +{ + struct ext_func_tab * extcmd; + + /* special case: "nothing" is reserved for unbinding */ + if (!strcmp(command, "nothing")) { + cmdlist[key].bind_cmd = NULL; + return; + } + + for(extcmd = extcmdlist; extcmd->ef_txt; extcmd++) { + if (strcmp(command, extcmd->ef_txt)) continue; + cmdlist[key].bind_cmd = extcmd; + return; + } + + pline("Bad command %s matched with key %c (ASCII %i). " + "Ignoring command.\n", command, key, key); +} + +static void +init_bind_list(void) +{ + bind_key(C('d'), "kick" ); /* "D" is for door!...? Msg is in dokick.c */ +#ifdef WIZARD + if (wizard) { + bind_key(C('e'), "detect" ); + bind_key(C('f'), "map" ); + bind_key(C('g'), "genesis" ); + bind_key(C('i'), "identify" ); + bind_key(C('o'), "where" ); + bind_key(C('v'), "levelport" ); + bind_key(C('w'), "wish" ); + } +#endif + bind_key(C('l'), "redraw" ); /* if number_pad is set */ + bind_key(C('p'), "previous" ); + bind_key(C('r'), "redraw" ); + bind_key(C('t'), "teleport" ); + bind_key(C('x'), "attributes" ); +#ifdef SUSPEND + bind_key(C('z'), "suspend" ); +#endif + bind_key('a', "apply" ); + bind_key('A', "takeoffall" ); + bind_key(M('a'), "adjust" ); + /* 'b', 'B' : go sw */ + bind_key('c', "close" ); + bind_key('C', "call" ); + bind_key(M('c'), "chat" ); + bind_key('d', "drop" ); + bind_key('D', "dropall" ); + bind_key(M('d'), "dip" ); + bind_key('e', "eat" ); + bind_key('E', "engrave" ); + bind_key(M('e'), "enhance" ); + bind_key('f', "fire" ); + /* 'F' : fight (one time) */ + bind_key(M('f'), "force" ); + /* 'g', 'G' : multiple go */ + /* 'h', 'H' : go west */ + bind_key('h', "help" ); /* if number_pad is set */ + bind_key('i', "inventory" ); + bind_key('I', "inventoryall" ); /* Robert Viduya */ + bind_key(M('i'), "invoke" ); + bind_key('j', "jump" ); + /* 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ + bind_key(M('j'), "jump" ); /* if number_pad is on */ + bind_key('k', "kick" ); /* if number_pad is on */ + bind_key('l', "loot" ); /* if number_pad is on */ + bind_key(M('l'), "loot" ); + bind_key(M('m'), "monster" ); + bind_key('N', "name" ); + /* 'n' prefixes a count if number_pad is on */ + bind_key(M('n'), "name" ); + bind_key(M('N'), "name" ); /* if number_pad is on */ + bind_key('o', "open" ); + bind_key('O', "setoptions" ); + bind_key(M('o'), "offer" ); + bind_key('p', "pay" ); + bind_key('P', "puton" ); + bind_key(M('p'), "pray" ); + bind_key('q', "quaff" ); + bind_key('Q', "quiver" ); + bind_key(M('q'), "quit" ); + bind_key('r', "read" ); + bind_key('R', "remove" ); + bind_key(M('r'), "rub" ); + bind_key('s', "search" ); + bind_key('S', "save" ); + bind_key(M('s'), "sit" ); + bind_key('t', "throw" ); + bind_key('T', "takeoff" ); + bind_key(M('t'), "turn" ); + /* 'u', 'U' : go ne */ + bind_key('u', "untrap" ); /* if number_pad is on */ + bind_key(M('u'), "untrap" ); + bind_key('v', "version" ); + bind_key('V', "history" ); + bind_key(M('v'), "versionext" ); + bind_key('w', "wield" ); + bind_key('W', "wear" ); + bind_key(M('w'), "wipe" ); + bind_key('x', "swap" ); + bind_key('X', "explore_mode" ); + /* 'y', 'Y' : go nw */ +#ifdef STICKY_COMMAND + bind_key(M('y'), "sticky" ); +#endif /* STICKY_COMMAND */ + bind_key('z', "zap" ); + bind_key('Z', "cast" ); + bind_key('<', "up" ); + bind_key('>', "down" ); + bind_key('/', "whatis" ); + bind_key('&', "whatdoes" ); + bind_key('?', "help" ); + bind_key(M('?'), "?" ); +#ifdef SHELL + bind_key('!', "shell" ); +#endif + bind_key('.', "wait" ); + bind_key(' ', "wait" ); + bind_key(',', "pickup" ); + bind_key(':', "look" ); + bind_key(';', "glance" ); + bind_key('^', "seetrap" ); + bind_key('\\', "discoveries" ); /* Robert Viduya */ + bind_key('@', "autopickup" ); + bind_key(M('2'), "twoweapon" ); + bind_key(WEAPON_SYM, "seeweapon" ); + bind_key(ARMOR_SYM, "seearmor" ); + bind_key(RING_SYM, "seerings" ); + bind_key(AMULET_SYM, "seeamulet" ); + bind_key(TOOL_SYM, "seetools" ); + bind_key('*', "seeall" ); /* inventory of all equipment in use */ + bind_key(GOLD_SYM, "seegold" ); + bind_key(SPBOOK_SYM, "seespells" ); /* Mike Stephenson */ + bind_key('#', "#"); + bind_key('_', "travel"); +} + +/* takes the list of bindings loaded from the options file, and changes cmdlist + * to match it */ +static void +change_bind_list(void) +{ + struct binding_list_tab *binding; + + /* TODO: they must be loaded forward, + * not backward as they are now */ + while ((binding = bindinglist)) { + bindinglist = bindinglist->next; + bind_key(binding->key, binding->extcmd); + free(binding->extcmd); + free(binding); + } +} + +/* mapping a key to itself should cause an infinite loop... */ +static void +verify_key_list() +{ + /* TODO */ +} + /* * Insert debug commands into the extended command list. This function * assumes that the last entry will be the help entry. @@ -1561,14 +1772,15 @@ static const struct ext_func_tab debug_e * You must add entries in ext_func_tab every time you add one to the * debug_extcmdlist(). */ -void +static void add_debug_extended_commands() { int i, j, k, n; /* count the # of help entries */ - for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++) + for (n = 0; extcmdlist[n].ef_txt[0]; n++) ; + n--; /* n is index of the last entry */ for (i = 0; debug_extcmdlist[i].ef_txt; i++) { for (j = 0; j < n; j++) @@ -1582,7 +1794,116 @@ add_debug_extended_commands() } } +/* list all keys and their bindings, like dat/hh but dynamic */ +void +dokeylist(void) +{ + char buf[BUFSZ], buf2[BUFSZ]; + uchar key; + boolean keys_used[256] = {0}; + register const char* dir_keys; + winid datawin; + int i; + char* dir_desc[10] = {"move west", + "move northwest", + "move north", + "move northeast", + "move east", + "move southeast", + "move south", + "move southwest", + "move downward", + "move upward"}; + char* misc_desc[MISC_CMD_COUNT] = + {"rush until something interesting is seen", + "run until something extremely interesting is seen", + "fight even if you don't see a monster", + "move without picking up objects/fighting", + "run without picking up objects/fighting", + "escape from the current query/action" +#ifdef REDO + , "redo the previous command" +#endif + }; + + datawin = create_nhwindow(NHW_TEXT); + putstr(datawin, 0, ""); + putstr(datawin, 0, " Full Current Key Bindings List"); + putstr(datawin, 0, ""); + + /* directional keys */ + if (iflags.num_pad) dir_keys = ndir; + else dir_keys = sdir; + putstr(datawin, 0, "Directional keys:"); + for (i = 0; i < 10; i++) { + key = dir_keys[i]; + keys_used[key] = TRUE; + if (!iflags.num_pad) { + keys_used[toupper(key)] = TRUE; + keys_used[C(key)] = TRUE; + } + Sprintf(buf, "%c\t%s", key, dir_desc[i]); + putstr(datawin, 0, buf); + } + if (!iflags.num_pad) { + putstr(datawin, 0, "Shift- will move in specified direction until you hit"); + putstr(datawin, 0, " a wall or run into something."); + putstr(datawin, 0, "Ctrl- will run in specified direction until something"); + putstr(datawin, 0, " very interesting is seen."); + } + putstr(datawin, 0, ""); + + /* special keys -- theoretically modifiable but many are still hard-coded*/ + putstr(datawin, 0, "Miscellaneous keys:"); + for (i = 0; i < MISC_CMD_COUNT; i++) { + key = misc_cmds[i]; + keys_used[key] = TRUE; + Sprintf(buf, "%s\t%s", key2txt(key, buf2), misc_desc[i]); + putstr(datawin, 0, buf); + } + putstr(datawin, 0, ""); + + /* more special keys -- all hard-coded */ +#ifndef NO_SIGNAL + putstr(datawin, 0, "^c\tbreak out of nethack (SIGINT)"); + keys_used[C('c')] = TRUE; + if (!iflags.num_pad) putstr(datawin, 0, ""); +#endif + if (iflags.num_pad) { + putstr(datawin, 0, "-\tforce fight (same as above)"); + putstr(datawin, 0, "5\trun (same as above)"); + putstr(datawin, 0, "0\tinventory (as #inventory)"); + keys_used['-'] = keys_used['5'] = keys_used['0'] = TRUE; + putstr(datawin, 0, ""); + } + + /* command keys - can be rebound or remapped*/ + putstr(datawin, 0, "Command keys:"); + for(i=0; i<=255; i++) { + struct ext_func_tab * extcmd; + char* mapping; + key = i; + /* JDS: not the most efficient way, perhaps */ + if (keys_used[i]) continue; + if (key == ' ' && !flags.rest_on_space) continue; + if ((extcmd = cmdlist[i].bind_cmd)) { + Sprintf(buf, "%s\t%s", key2txt(key, buf2), + extcmd->ef_desc); + putstr(datawin, 0, buf); + } else if ((mapping = cmdlist[i].map_list)) { + Sprintf(buf, "%s\tmapped to ", + key2txt(key, buf2)); + str2txt(mapping, eos(buf)); + putstr(datawin, 0, buf); + } + } + putstr(datawin, 0, ""); + + display_nhwindow(datawin, FALSE); + destroy_nhwindow(datawin); +} + static const char template[] = "%-18s %4ld %6ld"; static const char count_str[] = " count bytes"; static const char separator[] = "------------------ ----- ------"; @@ -1796,9 +2117,285 @@ wiz_migrate_mons() #endif /* WIZARD */ -#define unctrl(c) ((c) <= C('z') ? (0x60 | (c)) : (c)) -#define unmeta(c) (0x7f & (c)) +static int +compare_commands(_cmd1, _cmd2) + /* a wrapper function for strcmp. Can this be done more simply? */ + void *_cmd1, *_cmd2; +{ + struct ext_func_tab *cmd1 = _cmd1, *cmd2 = _cmd2; + + return strcmp(cmd1->ef_txt, cmd2->ef_txt); +} + +void +commands_init(void) +{ + int count = 0; + + while(extcmdlist[count].ef_txt) count++; + + qsort(extcmdlist, count, sizeof(struct ext_func_tab), + &compare_commands); + +#ifdef WIZARD + if (wizard) add_debug_extended_commands(); +#endif + init_bind_list(); /* initialize all keyboard commands */ + change_bind_list(); /* change keyboard commands based on options */ + verify_key_list(); +} + +/* returns a one-byte character from the text (it may massacre the txt + * buffer) */ +char +txt2key(txt) + char* txt; +{ + txt = stripspace(txt); + if (!*txt) return 0; + + /* simple character */ + if (!txt[1]) return txt[0]; + + /* a few special entries */ + if (!strcmp(txt, "")) return '\n'; + if (!strcmp(txt, "")) return ' '; + if (!strcmp(txt, "")) return '\033'; + + /* control and meta keys */ + switch (*txt) { + case 'm': /* can be mx, Mx, m-x, M-x */ + case 'M': + txt++; + if(*txt == '-' && txt[1]) txt++; + if (txt[1]) return 0; + return M( *txt ); + case 'c': /* can be cx, Cx, ^x, c-x, C-x, ^-x */ + case 'C': + case '^': + txt++; + if(*txt == '-' && txt[1]) txt++; + if (txt[1]) return 0; + return C( *txt ); + } + + /* ascii codes: must be three-digit decimal */ + if (*txt >= '0' && *txt <= '9') { + uchar key = 0; + int i; + for(i = 0; i < 3; i++) { + if(txt[i]<'0' || txt[i]>'9') return 0; + key = 10 * key + txt[i]-'0'; + } + return key; + } + + return 0; +} + +/* returns the text for a one-byte encoding + * must be shorter than a tab for proper formatting */ +char* +key2txt(c, txt) + char c; + char* txt; /* sufficiently long buffer */ +{ + if (c == ' ') + Sprintf(txt, ""); + else if (c == '\033') + Sprintf(txt, ""); + else if (c == '\n') + Sprintf(txt, ""); + else if (ISCTRL(c)) + Sprintf(txt, "^%c", UNCTRL(c)); + else if (ISMETA(c)) + Sprintf(txt, "M-%c", UNMETA(c)); + else if (c >= 33 && c <= 126) + Sprintf(txt, "%c", c); /* regular keys: ! through ~ */ + else + Sprintf(txt, "A-%i", c); /* arbitrary ascii combinations */ + return txt; +} + +/* returns the text for a string of one-byte encodings */ +char* +str2txt(s, txt) + char* s; + char* txt; +{ + char* buf = txt; + + while (*s) { + (void) key2txt(*s, buf); + buf = eos(buf); + *buf = ' '; + buf++; + *buf = 0; + s++; + } + return txt; +} + + +/* strips leading and trailing whitespace */ +char* +stripspace(txt) + char* txt; +{ + char* end; + while (isspace(*txt)) txt++; + end = eos(txt); + while (--end >= txt && isspace(*end)) *end = 0; + return txt; +} + +void +parsebindings(bindings) + /* closely follows parseoptions in options.c */ + char* bindings; +{ + char *bind; + char key; + struct binding_list_tab *newbinding = NULL; + + /* break off first binding from the rest; parse the rest */ + if ((bind = index(bindings, ',')) != 0) { + *bind++ = 0; + parsebindings(bind); + } + + /* parse a single binding: first split around : */ + if (! (bind = index(bindings, ':'))) return; /* it's not a binding */ + *bind++ = 0; + + /* read the key to be bound */ + key = txt2key(bindings); + if (!key) { + raw_printf("Bad binding %s.", bindings); + wait_synch(); + return; + } + + /* JDS: crappy hack because wizard mode information + * isn't read until _after_ key bindings are read, + * and to change this would cause numerous side effects. + * instead, I save a list of rebindings, which are later + * bound. */ + bind = stripspace(bind); + newbinding = (struct binding_list_tab *)alloc(sizeof(*newbinding)); + newbinding->key = key; + newbinding->extcmd = (char *)alloc(strlen(bind)+1); + strcpy(newbinding->extcmd, bind);; + newbinding->next = bindinglist; + bindinglist = newbinding; +} + +void +parseautocomplete(autocomplete,condition) + /* closesly follows parsebindings and parseoptions */ + char* autocomplete; + boolean condition; +{ + register char *autoc; + int i; + + /* break off first autocomplete from the rest; parse the rest */ + if ((autoc = index(autocomplete, ',')) + || (autoc = index(autocomplete, ':'))) { + *autoc++ = 0; + parseautocomplete(autoc, condition); + } + + /* strip leading and trailing white space */ + autocomplete = stripspace(autocomplete); + + if (!*autocomplete) return; + + /* take off negations */ + while (*autocomplete == '!') { + /* unlike most options, a leading "no" might actually be a part of + * the extended command. Thus you have to use ! */ + autocomplete++; + condition = !condition; + } + + /* find and modify the extended command */ + /* JDS: could be much faster [O(log n) vs O(n)] if done differently */ + for (i=0; extcmdlist[i].ef_txt; i++) { + if (strcmp(autocomplete, extcmdlist[i].ef_txt)) continue; + extcmdlist[i].autocomplete = condition; + return; + } + +#ifdef WIZARD + /* do the exact same thing with the wizmode list */ + /* this is a hack because wizard-mode commands haven't been loaded yet when + * this code is run. See "crappy hack" elsewhere. */ + for (i=0; debug_extcmdlist[i].ef_txt; i++) { + if (strcmp(autocomplete, debug_extcmdlist[i].ef_txt)) continue; + debug_extcmdlist[i].autocomplete = condition; + return; + } +#endif + + /* not a real extended command */ + raw_printf ("Bad autocomplete: invalid extended command '%s'.", autocomplete); + wait_synch(); +} + +void +parsemappings(mapping) + /* closely follows parsebindings and parseoptions */ + char* mapping; +{ + register char *map; + unsigned char key; + unsigned char map_to[BUFSZ] = ""; + int cnt; + struct key_tab * keytab; + + /* break off first mapping from the rest; parse the rest */ + if ((map = index(mapping, ','))) { + *map++ = 0; + parsemappings(map); + } + + /* parse a single mapping: first split around : */ + if (! (map = index(mapping, ':'))) return; /* it's not a mapping */ + *map++ = 0; + + /* read the key to be mapped */ + key = txt2key(mapping); + if (!key) { + raw_printf("Bad mapping for key %s.", mapping); + wait_synch(); + return; + } + /* read the mapping list */ + cnt = get_uchar_list(map, map_to, BUFSZ-1); + if (cnt < 0) { + cnt = -cnt - 1; + raw_printf("Bad mapping for key %s - %i at %s", + mapping, cnt, map); + wait_synch(); + return; + } + if (cnt == 0) { + raw_printf("You can't map %s to nothing (%s).", + mapping, map); + wait_synch(); + return; + + } + map_to[cnt] = 0; + + /* store in cmdlist */ + keytab = &(cmdlist[key]); + if (keytab->map_list != NULL) free(keytab->map_list); + keytab->map_list = (char*)alloc(cnt+1); + strcpy(keytab->map_list, (char *)map_to); +} void rhack(cmd) @@ -1812,7 +2409,7 @@ register char *cmd; flags.nopick = 0; cmd = parse(); } - if (*cmd == '\033') { + if (*cmd == DOESCAPE) { flags.move = FALSE; return; } @@ -1849,74 +2446,61 @@ register char *cmd; /* handle most movement commands */ do_walk = do_rush = prefix_seen = FALSE; flags.travel = iflags.travel1 = 0; - switch (*cmd) { - case 'g': if (movecmd(cmd[1])) { - flags.run = 2; - do_rush = TRUE; - } else - prefix_seen = TRUE; - break; - case '5': if (!iflags.num_pad) break; /* else FALLTHRU */ - case 'G': if (movecmd(lowc(cmd[1]))) { - flags.run = 3; - do_rush = TRUE; - } else - prefix_seen = TRUE; - break; - case '-': if (!iflags.num_pad) break; /* else FALLTHRU */ - /* Effects of movement commands and invisible monsters: - * m: always move onto space (even if 'I' remembered) - * F: always attack space (even if 'I' not remembered) - * normal movement: attack if 'I', move otherwise - */ - case 'F': if (movecmd(cmd[1])) { - flags.forcefight = 1; - do_walk = TRUE; - } else - prefix_seen = TRUE; - break; - case 'm': if (movecmd(cmd[1]) || u.dz) { - flags.run = 0; - flags.nopick = 1; - if (!u.dz) do_walk = TRUE; - else cmd[0] = cmd[1]; /* "m<" or "m>" */ - } else - prefix_seen = TRUE; - break; - case 'M': if (movecmd(lowc(cmd[1]))) { - flags.run = 1; - flags.nopick = 1; - do_rush = TRUE; - } else - prefix_seen = TRUE; - break; - case '0': if (!iflags.num_pad) break; - (void)ddoinv(); /* a convenience borrowed from the PC */ - flags.move = FALSE; - multi = 0; - return; - case CMD_TRAVEL: - if (iflags.travelcmd) { - flags.travel = 1; - iflags.travel1 = 1; - flags.run = 8; - flags.nopick = 1; - do_rush = TRUE; - break; - } - /*FALLTHRU*/ - default: if (movecmd(*cmd)) { /* ordinary movement */ - flags.run = 0; /* only matters here if it was 8 */ - do_walk = TRUE; - } else if (movecmd(iflags.num_pad ? - unmeta(*cmd) : lowc(*cmd))) { - flags.run = 1; - do_rush = TRUE; - } else if (movecmd(unctrl(*cmd))) { - flags.run = 3; - do_rush = TRUE; - } - break; + if (*cmd == DORUSH) { + if (movecmd(cmd[1])) { + flags.run = 2; + do_rush = TRUE; + } else + prefix_seen = TRUE; + } else if ( (*cmd == '5' && iflags.num_pad) + || *cmd == DORUN) { + if (movecmd(lowc(cmd[1]))) { + flags.run = 3; + do_rush = TRUE; + } else + prefix_seen = TRUE; + } else if ( (*cmd == '-' && iflags.num_pad) + || *cmd == DOFORCEFIGHT) { + /* Effects of movement commands and invisible monsters: + * m: always move onto space (even if 'I' remembered) + * F: always attack space (even if 'I' not remembered) + * normal movement: attack if 'I', move otherwise + */ + if (movecmd(cmd[1])) { + flags.forcefight = 1; + do_walk = TRUE; + } else + prefix_seen = TRUE; + } else if (*cmd == DONOPICKUP) { + if (movecmd(cmd[1]) || u.dz) { + flags.run = 0; + flags.nopick = 1; + if (!u.dz) do_walk = TRUE; + else cmd[0] = cmd[1]; /* "m<" or "m>" */ + } else + prefix_seen = TRUE; + } else if (*cmd == DORUN_NOPICKUP) { + if (movecmd(lowc(cmd[1]))) { + flags.run = 1; + flags.nopick = 1; + do_rush = TRUE; + } else + prefix_seen = TRUE; + } else if (*cmd == '0' && iflags.num_pad) { + (void)ddoinv(); /* a convenience borrowed from the PC */ + flags.move = FALSE; + multi = 0; + } else { + if (movecmd(*cmd)) { /* ordinary movement */ + do_walk = TRUE; + } else if (movecmd(iflags.num_pad ? + UNMETA(*cmd) : lowc(*cmd))) { + flags.run = 1; + do_rush = TRUE; + } else if (movecmd(UNCTRL(*cmd))) { + flags.run = 3; + do_rush = TRUE; + } } /* some special prefix handling */ @@ -1939,29 +2523,27 @@ register char *cmd; flags.mv = TRUE; domove(); return; - } else if (prefix_seen && cmd[1] == '\033') { /* */ + } else if (prefix_seen && cmd[1] == DOESCAPE) { /* */ /* don't report "unknown command" for change of heart... */ bad_command = FALSE; } else if (*cmd == ' ' && !flags.rest_on_space) { bad_command = TRUE; /* skip cmdlist[] loop */ - /* handle all other commands */ + /* handle bound/mapped commands */ } else { - register const struct func_tab *tlist; - int res, NDECL((*func)); + const struct key_tab *keytab = &cmdlist[(unsigned char)*cmd]; - for (tlist = cmdlist; tlist->f_char; tlist++) { - if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue; + if (keytab->bind_cmd != NULL) { + struct ext_func_tab *extcmd = keytab->bind_cmd; + int res, NDECL((*func)); - if (u.uburied && !tlist->can_if_buried) { + if (u.uburied && !extcmd->can_if_buried) { You_cant("do that while you are buried!"); res = 0; } else { - /* we discard 'const' because some compilers seem to have - trouble with the pointer passed to set_occupation() */ - func = ((struct func_tab *)tlist)->f_funct; - if (tlist->f_text && !occupation && multi) - set_occupation(func, tlist->f_text, multi); + func = extcmd->ef_funct; + if (extcmd->f_text && !occupation && multi) + set_occupation(func, extcmd->f_text, multi); res = (*func)(); /* perform the command */ } if (!res) { @@ -1970,6 +2552,20 @@ register char *cmd; } return; } + if (keytab->map_list != NULL) { + char buf[BUFSZ]; + char* mapping = keytab->map_list; + pline("Mapping char %s.", key2txt(*cmd, buf)); + while (*mapping) { + pline("Mapping to %s.", + key2txt(*mapping, buf)); + addchar(*mapping); + mapping++; + } + flags.move = FALSE; + return; + } + /* if we reach here, cmd wasn't found in cmdlist[] */ bad_command = TRUE; } @@ -2348,7 +2944,7 @@ parse() } else break; /* not a digit */ } - if (foo == '\033') { /* esc cancels count (TH) */ + if (foo == DOESCAPE) { /* esc cancels count (TH) */ clear_nhwindow(WIN_MESSAGE); multi = last_multi = 0; # ifdef REDO @@ -2369,8 +2965,9 @@ parse() } in_line[0] = foo; in_line[1] = '\0'; - if (foo == 'g' || foo == 'G' || foo == 'm' || foo == 'M' || - foo == 'F' || (iflags.num_pad && (foo == '5' || foo == '-'))) { + if (foo == DORUSH || foo == DORUN || foo == DOFORCEFIGHT + || foo == DONOPICKUP || foo == DORUN_NOPICKUP + || (iflags.num_pad && (foo == '5' || foo == '-'))) { foo = readchar(); #ifdef REDO savech((char)foo); @@ -2379,7 +2976,7 @@ parse() in_line[2] = 0; } clear_nhwindow(WIN_MESSAGE); - if (prezero) in_line[0] = '\033'; + if (prezero) in_line[0] = DOESCAPE; return(in_line); } Index: src/decl.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/decl.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 decl.c --- src/decl.c 23 Aug 2005 21:43:14 -0000 1.1.1.1 +++ src/decl.c 23 Aug 2005 23:54:38 -0000 @@ -98,11 +98,16 @@ struct linfo level_info[MAXLINFO]; NEARDATA struct sinfo program_state; /* 'rogue'-like direction commands (cmd.c) */ -const char sdir[] = "hykulnjb><"; +char sdir[] = "hykulnjb><"; const char ndir[] = "47896321><"; /* number pad mode */ const schar xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 }; const schar ydir[10] = { 0,-1,-1,-1, 0, 1, 1, 1, 0, 0 }; const schar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1,-1 }; +char misc_cmds[] = {'g', 'G', 'F', 'm', 'M', '\033' +#ifdef REDO + , '\001' +#endif +}; NEARDATA schar tbx = 0, tby = 0; /* mthrowu: target */ Index: src/files.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/files.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 files.c --- src/files.c 23 Aug 2005 21:43:15 -0000 1.1.1.1 +++ src/files.c 24 Aug 2005 02:35:57 -0000 @@ -1587,6 +1587,55 @@ const char *filename; } +/* + * Retrieve a list of one-byte integers from a buffer into a uchar array. + * + * It can accept 3-digit decimal integers, characters (ascii), or + * certain character symbols (see txt2key) + * + * return value of +x indicates x uchars read, -x indicates x-1 uchars read + * + * Note: there is no way to read value 0 + */ +int +get_uchar_list(buf, list, size) + char *buf; /* read buffer */ + uchar *list; /* return list */ + int size; /* return list size */ +{ + int cnt = 0; + char* next; + uchar orig; + uchar mkey; + + while (1) { /* one loop for each uchar */ + if (cnt == size) return cnt; + + /* take off leading whiltespace */ + while (isspace(*buf)) buf++; + if (!*buf) return cnt; + + /* strip trailing whitespace / other uchars */ + next = buf; + while(*next && !isspace(*next)) next++; + orig = *next; + *next = 0; + + /* interpret the character */ + mkey = (uchar)txt2key(buf); + if (!mkey) { + raw_printf("Invalid uchar %s on %i.", buf, cnt+1); + return -(cnt+1); + } + list[cnt] = mkey; + cnt++; + + /* prepare for the next uchar */ + *next = orig; + buf = next; + } + /* NOT REACHED */ +} /* * Retrieve a list of integers from a file into a uchar array. @@ -1604,48 +1653,36 @@ get_uchars(fp, buf, bufp, list, modlist, int size; /* return list size */ const char *name; /* name of option for error message */ { - unsigned int num = 0; int count = 0; - boolean havenum = FALSE; - - while (1) { - switch(*bufp) { - case ' ': case '\0': - case '\t': case '\n': - if (havenum) { - /* if modifying in place, don't insert zeros */ - if (num || !modlist) list[count] = num; - count++; - num = 0; - havenum = FALSE; - } - if (count == size || !*bufp) return count; - bufp++; - break; - - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - havenum = TRUE; - num = num*10 + (*bufp-'0'); - bufp++; - break; - - case '\\': - if (fp == (FILE *)0) - goto gi_error; - do { - if (!fgets(buf, BUFSZ, fp)) goto gi_error; - } while (buf[0] == '#'); - bufp = buf; - break; - - default: + int num_read; + char* buf_end; + boolean another; /* expect another line? */ + + while (1) { /* JDS: one loop for each line of input */ + if ((buf_end = index(bufp, '\\')) != 0) { + *buf_end = 0; + another = TRUE; + } else another = FALSE; + + num_read = get_uchar_list(bufp, list, size-count); + if (num_read < 0) { + count -= num_read + 1; gi_error: raw_printf("Syntax error in %s", name); wait_synch(); return count; } + count += num_read; + list += num_read; + + if (count == size || !another) return count; + + if (fp == (FILE*)0) + goto gi_error; + do { + if (!fgets(buf, BUFSZ, fp)) goto gi_error; + } while (buf[0] == '#'); + bufp = buf; } /*NOTREACHED*/ } @@ -1720,6 +1757,13 @@ char *tmp_levels; } else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) { add_autopickup_exception(bufp); #endif + } else if (match_varname(buf, "BINDINGS", 4)) { + /* JDS: hmmm, should these be in NOCWD_ASSUMPTIONS? */ + parsebindings(bufp); + } else if (match_varname(buf, "AUTOCOMPLETE", 5)) { + parseautocomplete(bufp, TRUE); + } else if (match_varname(buf, "MAPPINGS", 3)) { + parsemappings(bufp); #ifdef NOCWD_ASSUMPTIONS } else if (match_varname(buf, "HACKDIR", 4)) { adjust_prefix(bufp, HACKPREFIX); Index: src/options.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/options.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 options.c --- src/options.c 23 Aug 2005 21:43:17 -0000 1.1.1.1 +++ src/options.c 23 Aug 2005 23:59:23 -0000 @@ -987,9 +987,7 @@ boolean tinitial, tfrom_file; } /* strip leading and trailing white space */ - while (isspace(*opts)) opts++; - op = eos(opts); - while (--op >= opts && isspace(*op)) *op = '\0'; + opts = stripspace(opts); if (!*opts) return; negated = FALSE; Index: src/pager.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/src/pager.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 pager.c --- src/pager.c 23 Aug 2005 21:43:17 -0000 1.1.1.1 +++ src/pager.c 24 Aug 2005 00:01:30 -0000 @@ -866,8 +866,9 @@ static const char *help_menu_items[] = { /* 4*/ "Info on what a given key does.", /* 5*/ "List of game options.", /* 6*/ "Longer explanation of game options.", -/* 7*/ "List of extended commands.", -/* 8*/ "The NetHack license.", +/* 7*/ "Full list of keyboard commands.", +/* 8*/ "List of extended commands.", +/* 9*/ "The NetHack license.", #ifdef PORT_HELP "%s-specific help and commands.", #define PORT_HELP_ID 100 @@ -940,8 +941,9 @@ dohelp() case 4: (void) dowhatdoes(); break; case 5: option_help(); break; case 6: display_file(OPTIONFILE, TRUE); break; - case 7: (void) doextlist(); break; - case 8: display_file(LICENSE, TRUE); break; + case 7: dokeylist(); break; + case 8: (void) doextlist(); break; + case 9: display_file(LICENSE, TRUE); break; #ifdef WIZARD /* handle slot 9 or 10 */ default: display_file(DEBUGHELP, TRUE); break; Index: win/Qt/qt_win.cpp =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/win/Qt/qt_win.cpp,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 qt_win.cpp --- win/Qt/qt_win.cpp 23 Aug 2005 21:43:23 -0000 1.1.1.1 +++ win/Qt/qt_win.cpp 24 Aug 2005 00:09:01 -0000 @@ -4965,7 +4965,7 @@ char NetHackQtBind::qt_yn_function(const int result=-1; while (result<0) { - char ch=NetHackQtBind::qt_nhgetch(); + char ch=nh_nhgetch(); if (ch=='\033') { result=yn_esc_map; } else if (choices && !index(choices,ch)) { Index: win/gnome/gnbind.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/win/gnome/gnbind.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 gnbind.c --- win/gnome/gnbind.c 23 Aug 2005 21:43:23 -0000 1.1.1.1 +++ win/gnome/gnbind.c 24 Aug 2005 02:04:18 -0000 @@ -506,7 +506,7 @@ void gnome_display_nhwindow(winid wid, B ghack_signals[GHSIG_DISPLAY], block); if (block && (gnome_windowlist[wid].type == NHW_MAP)) - (void) gnome_nhgetch(); + (void) nhgetch(); } } @@ -1051,8 +1051,8 @@ char gnome_yn_function(const char *quest /* Only here if main window is not present */ while (result<0) { - ch=gnome_nhgetch(); - if (ch=='\033') { + ch=nhgetch(); + if (ch==DOESCAPE) { result=yn_esc_map; } else if (choices && !index(choices,ch)) { /* FYI: ch==-115 is for KP_ENTER */ Index: win/tty/getline.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/win/tty/getline.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 getline.c --- win/tty/getline.c 23 Aug 2005 21:43:24 -0000 1.1.1.1 +++ win/tty/getline.c 24 Aug 2005 02:03:36 -0000 @@ -185,7 +185,7 @@ register const char *s; /* chars allowed morc = 0; - while((c = tty_nhgetch()) != '\n') { + while((c = nhgetch()) != '\n') { if(iflags.cbreak) { if ((s && index(s,c)) || c == x) { morc = (char) c; @@ -220,6 +220,7 @@ ext_cmd_getlin_hook(base) com_index = -1; for (oindex = 0; extcmdlist[oindex].ef_txt != (char *)0; oindex++) { + if (!extcmdlist[oindex].autocomplete) continue; if (!strncmpi(base, extcmdlist[oindex].ef_txt, strlen(base))) { if (com_index == -1) /* no matches yet */ com_index = oindex; Index: win/tty/wintty.c =================================================================== RCS file: /home/jdorje/CVSROOT/nethack/win/tty/wintty.c,v retrieving revision 1.1.1.1 diff -p -u -r1.1.1.1 wintty.c --- win/tty/wintty.c 23 Aug 2005 21:43:24 -0000 1.1.1.1 +++ win/tty/wintty.c 24 Aug 2005 02:03:55 -0000 @@ -676,7 +676,7 @@ tty_askname() tty_curs(BASE_WINDOW, (int)(sizeof who_are_you), wins[BASE_WINDOW]->cury - 1); ct = 0; - while((c = tty_nhgetch()) != '\n') { + while((c = nhgetch()) != '\n') { if(c == EOF) error("End of input\n"); if (c == '\033') { ct = 0; break; } /* continue outer loop */ #if defined(WIN32CON) @@ -2569,7 +2569,7 @@ tty_nh_poskey(x, y, mod) ttyDisplay->toplin = 2; return i; # else - return tty_nhgetch(); + return nhgetch(); # endif }