diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 25d25c065..d5c846454 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -35,7 +35,7 @@ .ds vr "NetHack 3.7 .ds f0 "\*(vr .ds f1 -.ds f2 "October 11, 2021 +.ds f2 "November 16, 2021 . .\" A note on some special characters: .\" \(lq = left double quote @@ -4588,11 +4588,10 @@ Platform-specific Customization options .pg Here are explanations of options that are used by specific platforms or ports to customize and change the port behavior. -.lp altkeyhandler -Select an alternate keystroke handler dll to load (Win32 tty NetHack only). -The name of the handler is specified without the .dll extension and without -any path information. -Cannot be set with the \(oqO\(cq command. +.lp altkeyhandling +Select an alternate way to handle keystrokes (Win32 tty NetHack only). +The name of the handling type is one of \(lqdefault\(rq, \(lqray\(rq, +\(lq340\(rq. .lp altmeta On Amiga, this option controls whether typing \(lqAlt\(rq plus another key functions as a meta-shift for that key (default on). diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index c713cf712..43790bd3e 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -45,7 +45,7 @@ %.au \author{Original version - Eric S. Raymond\\ (Edited and expanded for 3.7 by Mike Stephenson and others)} -\date{October 11, 2021} +\date{November 16, 2021} \maketitle @@ -5052,11 +5052,9 @@ or ports to customize and change the port behavior. \blist{} %.lp -\item[\ib{altkeyhandler}] -Select an alternate keystroke handler dll to load ({\it Win32 tty\/ NetHack\/} only). -The name of the handler is specified without the .dll extension and without any -path information. -Cannot be set with the `{\tt O}' command. +\item[\ib{altkeyhandling}] +Select an alternate way to handle keystrokes ({\it Win32 tty\/ NetHack\/} only). +The name of the handling type is one of {\it default}, {\it ray}, {\it 340} %.lp \item[\ib{altmeta}] On Amiga, this option controls whether typing ``Alt'' plus another key diff --git a/include/extern.h b/include/extern.h index 62ee6ee64..b42c42112 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1746,6 +1746,7 @@ extern void set_output_mode(int); extern void synch_cursor(void); extern void nethack_enter_consoletty(void); extern void consoletty_exit(void); +extern int set_keyhandling_via_option(void); #endif /* WIN32 */ /* ### o_init.c ### */ diff --git a/include/flag.h b/include/flag.h index 3c5f62320..2eac1a04b 100644 --- a/include/flag.h +++ b/include/flag.h @@ -157,6 +157,14 @@ enum getloc_filters { NUM_GFILTER }; +#ifdef WIN32 +enum windows_key_handling { + default_keyhandling, + ray_keyhandling, + nh340_keyhandling +}; +#endif + struct debug_flags { boolean test; #ifdef TTY_GRAPHICS @@ -364,8 +372,9 @@ struct instance_flags { int wc2_windowborders; /* display borders on NetHack windows */ int wc2_petattr; /* text attributes for pet */ #ifdef WIN32 -#define MAX_ALTKEYHANDLER 25 - char altkeyhandler[MAX_ALTKEYHANDLER]; +#define MAX_ALTKEYHANDLING 25 + char altkeyhandling[MAX_ALTKEYHANDLING]; + enum windows_key_handling key_handling; #endif /* copies of values in struct u, used during detection when the originals are temporarily cleared; kept here rather than diff --git a/include/optlist.h b/include/optlist.h index 1af7e2f59..1f0d22a72 100644 --- a/include/optlist.h +++ b/include/optlist.h @@ -88,8 +88,8 @@ opt_##a, "message window alignment") NHOPTC(align_status, 20, opt_in, set_gameview, No, Yes, No, Yes, NoAlias, "status window alignment") - NHOPTC(altkeyhandler, 20, opt_in, set_in_game, No, Yes, No, No, NoAlias, - "alternate key handler") + NHOPTC(altkeyhandling, 20, opt_in, set_in_game, No, Yes, No, Yes, + "altkeyhandler", "alternative key handling") #ifdef ALTMETA NHOPTB(altmeta, 0, opt_out, set_in_game, Off, Yes, No, No, NoAlias, &iflags.altmeta) diff --git a/include/windconf.h b/include/windconf.h index ee5f45082..21619199f 100644 --- a/include/windconf.h +++ b/include/windconf.h @@ -229,7 +229,7 @@ extern void consoletty_preference_update(const char *); extern void toggle_mouse_support(void); extern void map_subkeyvalue(char *); #if defined(WIN32CON) -extern void set_altkeyhandler(const char *); +extern void set_altkeyhandling(const char *); #endif extern void raw_clear_screen(void); diff --git a/src/options.c b/src/options.c index 99577e573..552a60d12 100644 --- a/src/options.c +++ b/src/options.c @@ -637,18 +637,18 @@ optfn_align_status(int optidx, int req, boolean negated, char *opts, char *op) } static int -optfn_altkeyhandler(int optidx UNUSED, int req, boolean negated UNUSED, +optfn_altkeyhandling(int optidx UNUSED, int req, boolean negated UNUSED, char *opts, char *op UNUSED) { if (req == do_init) { return optn_ok; } if (req == do_set) { - /* altkeyhandler:string */ + /* altkeyhandling:string */ #if defined(WIN32) && defined(TTY_GRAPHICS) if (op != empty_optstr) { - set_altkeyhandler(op); + set_altkeyhandling(op); } else { return optn_err; } @@ -661,10 +661,19 @@ optfn_altkeyhandler(int optidx UNUSED, int req, boolean negated UNUSED, opts[0] = '\0'; #ifdef WIN32 Sprintf(opts, "%s", - iflags.altkeyhandler[0] ? iflags.altkeyhandler : "default"); + (iflags.key_handling == nh340_keyhandling) + ? "340" + : (iflags.key_handling == ray_keyhandling) + ? "ray" + : "default"); #endif return optn_ok; } +#ifdef WIN32 + if (req == do_handler) { + return set_keyhandling_via_option(); + } +#endif return optn_ok; } diff --git a/sys/windows/.nethackrc.template b/sys/windows/.nethackrc.template index 053e48358..2f3de0d0a 100644 --- a/sys/windows/.nethackrc.template +++ b/sys/windows/.nethackrc.template @@ -27,13 +27,11 @@ OPTIONS=symset:IBMGraphics_2,roguesymset:RogueEpyx #OPTIONS=windowtype:curses # # Keyboard handling -# Different keyboard handlers can be loaded. -# Default is nhdefkey.dll but you can override that. -# Ray Chason's keyboard handler -# OPTIONS=altkeyhandler:nhraykey.dll +# Ray Chason's keyboard handling +# OPTIONS=altkeyhandling:ray # # NetHack 3.4.0 keyboard handling -# OPTIONS=altkeyhandler:nh340key.dll +# OPTIONS=altkeyhandling:340 # *** Personal Preferences *** # Some options to set personal preferences. Uncomment and change these to diff --git a/sys/windows/Makefile.gcc b/sys/windows/Makefile.gcc index c81a116ae..2204c1d90 100644 --- a/sys/windows/Makefile.gcc +++ b/sys/windows/Makefile.gcc @@ -441,9 +441,6 @@ endif COMCTRL = comctl32.lib -KEYDLLS = $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll \ - $(GAMEDIR)/nhraykey.dll - TILEUTIL16 = $(UTIL)/tile2bmp.exe TILEBMP16 = $(SRC)/tiles.bmp @@ -892,7 +889,7 @@ gamedir.tag: test -d $(GAMEDIR) && echo directory created > $@ $(GAMEDIR)/NetHack.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)consoletty.o $(O)guistub.o \ - $(ALLOBJ) $(TTYOBJ) $(O)date.o $(GUIOBJ) $(O)conres.o $(KEYDLLS) \ + $(ALLOBJ) $(TTYOBJ) $(O)date.o $(GUIOBJ) $(O)conres.o \ $(LUATARGETS) @echo Linking $@... $(link) $(lflags) -o$@ $(ALLOBJ) $(TTYOBJ) $(O)consoletty.o $(O)tile.o \ @@ -910,7 +907,7 @@ $(GAMEDIR)/NetHack.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)consoletty.o $(O)g ifneq "$(SKIP_NETHACKW)" "Y" $(GAMEDIR)/NetHackW.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)ttystub.o \ - $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)winres.o $(KEYDLLS) \ + $(ALLOBJ) $(TTYOBJ) $(GUIOBJ) $(O)winres.o \ $(LUATARGETS) @echo Linking $@... $(link) $(lflags) -mwindows -o$@ $(ALLOBJ) $(GUIOBJ) $(O)tile.o \ @@ -919,30 +916,6 @@ $(GAMEDIR)/NetHackW.exe : gamedir.tag $(PDCLIB) $(O)tile.o $(O)ttystub.o \ $(subst /,\,@if exist $(O)install.tag del $(O)install.tag) endif -$(O)nhdefkey.o: - $(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(MSWSYS)/nhdefkey.c - -$(GAMEDIR)/nhdefkey.dll : $(O)nhdefkey.o gamedir.tag - @echo Linking $@ - $(cc) -shared -Wl,--export-all-symbols \ - -Wl,--add-stdcall-alias -o $@ $< - -$(O)nh340key.o: - $(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(MSWSYS)/nh340key.c - -$(GAMEDIR)/nh340key.dll : $(O)nh340key.o gamedir.tag - @echo Linking $@ - $(cc) -shared -Wl,--export-all-symbols \ - -Wl,--add-stdcall-alias -o $@ $< - -$(O)nhraykey.o: - $(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(MSWSYS)/nhraykey.c - -$(GAMEDIR)/nhraykey.dll : $(O)nhraykey.o gamedir.tag - @echo Linking $@ - $(cc) -shared -Wl,--export-all-symbols \ - -Wl,--add-stdcall-alias -o $@ $< - $(GAME)_.ico : $(MSWSYS)/$(GAME).ico $(subst /,\,@copy $(MSWSYS)/$(GAME).ico $@) @@ -1268,9 +1241,6 @@ spotless: clean if exist gamedir.tag del gamedir.tag ifneq "$(W_GAMEDIR)" "" if exist $(W_GAMEDIR)\NetHack.exe del $(W_GAMEDIR)\NetHack.exe - if exist $(W_GAMEDIR)\nhdefkey.dll del $(W_GAMEDIR)\nhdefkey.dll - if exist $(W_GAMEDIR)\nh340key.dll del $(W_GAMEDIR)\nh340key.dll - if exist $(W_GAMEDIR)\nhraykey.dll del $(W_GAMEDIR)\nhraykey.dll if exist $(W_GAMEDIR)\NetHack.exe del $(W_GAMEDIR)\NetHack.exe if exist $(W_GAMEDIR)\NetHack.pdb del $(W_GAMEDIR)\NetHack.pdb if exist $(W_GAMEDIR)\nhdat$(NHV) del $(W_GAMEDIR)\nhdat$(NHV) @@ -1334,9 +1304,6 @@ ifneq "$(W_OBJ)" "" endif endif if exist $(W_GAMEDIR)\license. del $(W_GAMEDIR)\license. - if exist $(W_GAMEDIR)\nh340key.dll del $(W_GAMEDIR)\nh340key.dll - if exist $(W_GAMEDIR)\nhdefkey.dll del $(W_GAMEDIR)\nhdefkey.dll - if exist $(W_GAMEDIR)\nhraykey.dll del $(W_GAMEDIR)\nhraykey.dll -test -d ..\binary && rd ..\binary clean: @@ -1362,21 +1329,6 @@ ifneq "$(W_OBJ)" "" if exist $(W_OBJ)\makedefs.MAP del $(W_OBJ)\makedefs.MAP if exist $(W_OBJ)\makedefs.PDB del $(W_OBJ)\makedefs.PDB if exist $(W_OBJ)\NetHack.MAP del $(W_OBJ)\NetHack.MAP - if exist $(W_OBJ)\nh340key.def del $(W_OBJ)\nh340key.def - if exist $(W_OBJ)\nh340key.exp del $(W_OBJ)\nh340key.exp - if exist $(W_OBJ)\nh340key.lib del $(W_OBJ)\nh340key.lib - if exist $(W_OBJ)\nh340key.map del $(W_OBJ)\nh340key.map - if exist $(W_OBJ)\nh340key.PDB del $(W_OBJ)\nh340key.PDB - if exist $(W_OBJ)\nhdefkey.def del $(W_OBJ)\nhdefkey.def - if exist $(W_OBJ)\nhdefkey.exp del $(W_OBJ)\nhdefkey.exp - if exist $(W_OBJ)\nhdefkey.lib del $(W_OBJ)\nhdefkey.lib - if exist $(W_OBJ)\nhdefkey.map del $(W_OBJ)\nhdefkey.map - if exist $(W_OBJ)\nhdefkey.PDB del $(W_OBJ)\nhdefkey.PDB - if exist $(W_OBJ)\nhraykey.def del $(W_OBJ)\nhraykey.def - if exist $(W_OBJ)\nhraykey.exp del $(W_OBJ)\nhraykey.exp - if exist $(W_OBJ)\nhraykey.lib del $(W_OBJ)\nhraykey.lib - if exist $(W_OBJ)\nhraykey.map del $(W_OBJ)\nhraykey.map - if exist $(W_OBJ)\nhraykey.PDB del $(W_OBJ)\nhraykey.PDB if exist $(W_OBJ)\envchk.tag del $(W_OBJ)\envchk.tag if exist $(W_OBJ)\obj.tag del $(W_OBJ)\obj.tag if exist $(W_OBJ)\sp_lev.tag del $(W_OBJ)\sp_lev.tag diff --git a/sys/windows/Makefile.msc b/sys/windows/Makefile.msc index 53830bc1d..198c73cd2 100644 --- a/sys/windows/Makefile.msc +++ b/sys/windows/Makefile.msc @@ -427,8 +427,6 @@ ALL_GUIHDR = $(MSWIN)\mhaskyn.h $(MSWIN)\mhdlg.h $(MSWIN)\mhfont.h \ COMCTRL = comctl32.lib -KEYDLLS = $(GAMEDIR)\nhdefkey.dll $(GAMEDIR)\nh340key.dll $(GAMEDIR)\nhraykey.dll - SOUND = $(OBJ)\ntsound.o VVOBJ = $(O)version.o @@ -979,7 +977,7 @@ GAMEOBJ=$(GAMEOBJ:^ =^ $(GAMEDIR)\NetHack.exe : $(O)gamedir.tag $(O)tile.o $(O)consoletty.o $(O)guistub.o \ - $(ALLOBJ) $(TTYOBJ) $(O)date.o $(O)console.res $(KEYDLLS) \ + $(ALLOBJ) $(TTYOBJ) $(O)date.o $(O)console.res \ $(LUATARGETS) $(PDCLIB) @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @echo Linking $(@:\=/) @@ -1006,7 +1004,7 @@ $(GAMEDIR)\NetHack.exe : $(O)gamedir.tag $(O)tile.o $(O)consoletty.o $(O)guistub $(GAMEDIR)\NetHackW.exe : $(O)gamedir.tag $(O)tile.o $(O)ttystub.o \ $(ALLOBJ) $(GUIOBJ) $(O)date.o $(O)NetHackW.res \ - $(O)gamedir.tag $(KEYDLLS) \ + $(O)gamedir.tag \ $(LUATARGETS) @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @echo Linking $(@:\=/) @@ -1026,63 +1024,6 @@ $(O)gamedir.tag: @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) @echo directory created > $@ -$(O)nhdefkey.def: - @echo LIBRARY $(@B) >$@ -! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64" -! ELSE - @echo EXPORTS >>$@ - @echo ProcessKeystroke >>$@ - @echo NHkbhit >>$@ - @echo CheckInput >>$@ - @echo SourceWhere >>$@ - @echo SourceAuthor >>$@ - @echo KeyHandlerName >>$@ -! ENDIF - -$(GAMEDIR)\nhdefkey.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def - @echo Linking $(@:\=/) - @$(link) $(ldebug) /RELEASE /DLL user32.lib \ - /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \ - /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o - -$(O)nh340key.def: - @echo LIBRARY $(@B) >$@ -! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64" -! ELSE - @echo EXPORTS >>$@ - @echo ProcessKeystroke >>$@ - @echo NHkbhit >>$@ - @echo CheckInput >>$@ - @echo SourceWhere >>$@ - @echo SourceAuthor >>$@ - @echo KeyHandlerName >>$@ -! ENDIF - -$(GAMEDIR)\nh340key.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def - @echo Linking $(@:\=/) - @$(link) $(ldebug) /RELEASE /NOLOGO /DLL user32.lib \ - /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \ - /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o - -$(O)nhraykey.def: - @echo LIBRARY $(@B) >$@ -! IF "$(TARGET_CPU)"=="x64" || "$(PROCESSOR_ARCHITECTURE)"=="x64" -! ELSE - @echo EXPORTS >>$@ - @echo ProcessKeystroke >>$@ - @echo NHkbhit >>$@ - @echo CheckInput >>$@ - @echo SourceWhere >>$@ - @echo SourceAuthor >>$@ - @echo KeyHandlerName >>$@ -! ENDIF - -$(GAMEDIR)\nhraykey.dll : $(O)$(@B).o $(O)gamedir.tag $(O)$(@B).def - @echo Linking $(@:\=/) - @$(link) $(ldebug) /RELEASE /NOLOGO /DLL user32.lib \ - /PDB:"$(O)$(@B).PDB" /MAP:"$(O)$(@B).map" /DEF:$(O)$(@B).def \ - /IMPLIB:$(O)$(@B).lib -out:$@ $(O)$(@B).o - $(O)install.tag: $(DAT)\data $(DAT)\rumors $(DAT)\oracles \ $(O)sp_lev.tag $(DLB) ! IF ("$(USE_DLB)"=="Y") @@ -1744,9 +1685,6 @@ $(DAT)\bogusmon: $(U)makedefs.exe $(DAT)\bogusmon.txt spotless: clean ! IF ("$(OBJ)"!="") if exist $(OBJ)\* rmdir $(OBJ) /s /Q - if exist $(GAMEDIR)\nhdefkey.dll del $(GAMEDIR)\nhdefkey.dll - if exist $(GAMEDIR)\nh340key.dll del $(GAMEDIR)\nh340key.dll - if exist $(GAMEDIR)\nhraykey.dll del $(GAMEDIR)\nhraykey.dll if exist $(GAMEDIR)\NetHack.exe del $(GAMEDIR)\NetHack.exe if exist $(GAMEDIR)\NetHack.pdb del $(GAMEDIR)\NetHack.pdb if exist $(GAMEDIR)\nhdat$(NHV) del $(GAMEDIR)\nhdat$(NHV) @@ -1808,21 +1746,6 @@ clean: if exist $(O)makedefs.MAP del $(O)makedefs.MAP if exist $(O)makedefs.PDB del $(O)makedefs.PDB if exist $(O)NetHack.MAP del $(O)NetHack.MAP - if exist $(O)nh340key.def del $(O)nh340key.def - if exist $(O)nh340key.exp del $(O)nh340key.exp - if exist $(O)nh340key.lib del $(O)nh340key.lib - if exist $(O)nh340key.map del $(O)nh340key.map - if exist $(O)nh340key.PDB del $(O)nh340key.PDB - if exist $(O)nhdefkey.def del $(O)nhdefkey.def - if exist $(O)nhdefkey.exp del $(O)nhdefkey.exp - if exist $(O)nhdefkey.lib del $(O)nhdefkey.lib - if exist $(O)nhdefkey.map del $(O)nhdefkey.map - if exist $(O)nhdefkey.PDB del $(O)nhdefkey.PDB - if exist $(O)nhraykey.def del $(O)nhraykey.def - if exist $(O)nhraykey.exp del $(O)nhraykey.exp - if exist $(O)nhraykey.lib del $(O)nhraykey.lib - if exist $(O)nhraykey.map del $(O)nhraykey.map - if exist $(O)nhraykey.PDB del $(O)nhraykey.PDB if exist $(O)envchk.tag del $(O)envchk.tag if exist $(O)obj.tag del $(O)obj.tag if exist $(O)sp_lev.tag del $(O)sp_lev.tag diff --git a/sys/windows/consoletty.c b/sys/windows/consoletty.c index e8f1c60d3..e76616fc8 100644 --- a/sys/windows/consoletty.c +++ b/sys/windows/consoletty.c @@ -8,8 +8,8 @@ * Initial Creation M. Allison 1993/01/31 * Switch to low level console output routines M. Allison 2003/10/01 * Restrict cursor movement until input pending M. Lehotay 2003/10/02 - * Call Unicode version of output API on NT R. Chason 2005/10/28 - * Use of back buffer to improve performance B. House 2018/05/06 + * Call Unicode version of output API on NT R. Chason 2005/10/28 + * Use of back buffer to improve performance B. House 2018/05/06 * */ @@ -279,33 +279,36 @@ static char nullstr[] = ""; char erase_char, kill_char; #define DEFTEXTCOLOR ttycolors[7] -/* dynamic keystroke handling .DLL support */ -typedef int(__stdcall *PROCESS_KEYSTROKE)(HANDLE, INPUT_RECORD *, boolean *, +int default_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int); +int default_kbhit(HANDLE, INPUT_RECORD *); +int default_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean, + int, int *, coord *); + +int ray_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int); +int ray_kbhit(HANDLE, INPUT_RECORD *); +int ray_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean, + int, int *, coord *); + +int nh340_processkeystroke(HANDLE, INPUT_RECORD *, boolean *, boolean, int); +int nh340_kbhit(HANDLE, INPUT_RECORD *); +int nh340_checkinput(HANDLE, INPUT_RECORD *, DWORD *, boolean, + int, int *, coord *); + +struct keyboard_handling_t { + char *pKeyHandlingName; + int (*pProcessKeystroke)(HANDLE, INPUT_RECORD *, boolean *, boolean, int); - -typedef int(__stdcall *NHKBHIT)(HANDLE, INPUT_RECORD *); - -typedef int(__stdcall *CHECKINPUT)(HANDLE, INPUT_RECORD *, DWORD *, boolean, + int (*pNHkbhit)(HANDLE, INPUT_RECORD *); + int (*pCheckInput)(HANDLE, INPUT_RECORD *, DWORD *, boolean, int, int *, coord *); +} keyboard_handling = { + 0, + default_processkeystroke, + default_kbhit, + default_checkinput +}; -typedef int(__stdcall *SOURCEWHERE)(char **); - -typedef int(__stdcall *SOURCEAUTHOR)(char **); - -typedef int(__stdcall *KEYHANDLERNAME)(char **, int); - -typedef struct { - char * name; // name without DLL extension - HANDLE hLibrary; - PROCESS_KEYSTROKE pProcessKeystroke; - NHKBHIT pNHkbhit; - CHECKINPUT pCheckInput; - SOURCEWHERE pSourceWhere; - SOURCEAUTHOR pSourceAuthor; - KEYHANDLERNAME pKeyHandlerName; -} keyboard_handler_t; - -keyboard_handler_t keyboard_handler; +static INPUT_RECORD bogus_key; #ifdef VIRTUAL_TERMINAL_SEQUENCES long customcolors[CLR_MAX]; @@ -1015,7 +1018,7 @@ process_keystroke( if (g.Cmd.swap_yz) numberpad |= 0x10; #endif - ch = keyboard_handler.pProcessKeystroke( + ch = keyboard_handling.pProcessKeystroke( console.hConIn, ir, valid, numberpad, portdebug); #ifdef QWERTZ_SUPPORT numberpad &= ~0x10; @@ -1029,7 +1032,7 @@ process_keystroke( int consoletty_kbhit() { - return keyboard_handler.pNHkbhit(console.hConIn, &ir); + return keyboard_handling.pNHkbhit(console.hConIn, &ir); } int @@ -1050,7 +1053,7 @@ tgetch() return (g.program_state.done_hup) ? '\033' - : keyboard_handler.pCheckInput( + : keyboard_handling.pCheckInput( console.hConIn, &ir, &count, numpad, 0, &mod, &cc); } @@ -1078,7 +1081,7 @@ console_poskey(int *x, int *y, int *mod) #endif ch = (g.program_state.done_hup) ? '\033' - : keyboard_handler.pCheckInput( + : keyboard_handling.pCheckInput( console.hConIn, &ir, &count, numpad, 1, mod, &cc); #ifdef QWERTZ_SUPPORT numpad &= ~0x10; @@ -1749,38 +1752,6 @@ win32con_debug_keystrokes(void) } (void) doredraw(); } -void -win32con_handler_info(void) -{ - char *buf; - int ci; - if (!keyboard_handler.pSourceAuthor && !keyboard_handler.pSourceWhere) - pline("Keyboard handler source info and author unavailable."); - else { - if (keyboard_handler.pKeyHandlerName && - keyboard_handler.pKeyHandlerName(&buf, 1)) { - xputs("\n"); - xputs("Keystroke handler loaded: \n "); - xputs(buf); - } - if (keyboard_handler.pSourceAuthor && - keyboard_handler.pSourceAuthor(&buf)) { - xputs("\n"); - xputs("Keystroke handler Author: \n "); - xputs(buf); - } - if (keyboard_handler.pSourceWhere && - keyboard_handler.pSourceWhere(&buf)) { - xputs("\n"); - xputs("Keystroke handler source code available at:\n "); - xputs(buf); - } - xputs("\nPress any key to resume."); - ci = nhgetch(); - (void) doredraw(); - } -} - void win32con_toggle_cursor_info(void) { @@ -1821,81 +1792,6 @@ map_subkeyvalue(char* op) key_overrides[idx] = val; } -void unload_keyboard_handler(void) -{ - nhassert(keyboard_handler.hLibrary != NULL); - - FreeLibrary(keyboard_handler.hLibrary); - memset(&keyboard_handler, 0, sizeof(keyboard_handler_t)); -} - -boolean -load_keyboard_handler(const char * inName) -{ - char path[MAX_ALTKEYHANDLER + 4]; - strcpy(path, inName); - strcat(path, ".dll"); - - HANDLE hLibrary = LoadLibrary(path); - - if (hLibrary == NULL) - return FALSE; - - PROCESS_KEYSTROKE pProcessKeystroke = (PROCESS_KEYSTROKE) GetProcAddress( - hLibrary, TEXT("ProcessKeystroke")); - NHKBHIT pNHkbhit = (NHKBHIT) GetProcAddress( - hLibrary, TEXT("NHkbhit")); - CHECKINPUT pCheckInput = - (CHECKINPUT) GetProcAddress(hLibrary, TEXT("CheckInput")); - - if (!pProcessKeystroke || !pNHkbhit || !pCheckInput) - { - return FALSE; - } else { - if (keyboard_handler.hLibrary != NULL) - unload_keyboard_handler(); - - keyboard_handler.hLibrary = hLibrary; - - keyboard_handler.pProcessKeystroke = pProcessKeystroke; - keyboard_handler.pNHkbhit = pNHkbhit; - keyboard_handler.pCheckInput = pCheckInput; - - keyboard_handler.pSourceWhere = - (SOURCEWHERE) GetProcAddress(hLibrary, TEXT("SourceWhere")); - keyboard_handler.pSourceAuthor = - (SOURCEAUTHOR) GetProcAddress(hLibrary, TEXT("SourceAuthor")); - keyboard_handler.pKeyHandlerName = (KEYHANDLERNAME) GetProcAddress( - hLibrary, TEXT("KeyHandlerName")); - } - - return TRUE; -} - -void set_altkeyhandler(const char * inName) -{ - if (strlen(inName) >= MAX_ALTKEYHANDLER) { - config_error_add("altkeyhandler name '%s' is too long", inName); - return; - } - - char name[MAX_ALTKEYHANDLER]; - strcpy(name, inName); - - /* We support caller mistakenly giving name with '.dll' extension */ - char * ext = strchr(name, '.'); - if (ext != NULL) *ext = '\0'; - - if (load_keyboard_handler(name)) - strcpy(iflags.altkeyhandler, name); - else { - config_error_add("unable to load altkeyhandler '%s'", name); - return; - } - - return; -} - /* fatal error */ /*VARARGS1*/ @@ -2822,13 +2718,11 @@ void nethack_enter_consoletty(void) /* This was overriding the handler that had already been loaded during options parsing. Needs to check first */ - if (!iflags.altkeyhandler[0]) { + if (!iflags.key_handling) { if (primary_language == LANG_ENGLISH) { - if (!load_keyboard_handler("nhdefkey")) - error("Unable to load nhdefkey.dll"); + set_altkeyhandling("default"); } else { - if (!load_keyboard_handler("nhraykey")) - error("Unable to load nhraykey.dll"); + set_altkeyhandling("ray"); } } #ifdef VIRTUAL_TERMINAL_SEQUENCES @@ -2876,4 +2770,1270 @@ VA_DECL(const char *, fmt) #ifndef VIRTUAL_TERMINAL_SEQUENCES #endif /* ! VIRTUAL_TERMINAL_SEQUENCES */ + +/* + * Keyboard translation tables. + * (Adopted from the MSDOS port) + */ + +#define KEYPADLO 0x47 +#define KEYPADHI 0x53 + +#define PADKEYS (KEYPADHI - KEYPADLO + 1) +#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI) +#define isnumkeypad(x) \ + (KEYPADLO <= (x) && (x) <= 0x51 && (x) != 0x4A && (x) != 0x4E) + +#ifdef QWERTZ_SUPPORT +/* when 'numberpad' is 0 and Cmd.swap_yz is True + (signaled by setting 0x10 on boolean numpad argument) + treat keypress of numpad 7 as 'z' rather than 'y' */ +static boolean qwertz = FALSE; +#endif +#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2') + +const struct pad { + uchar normal, shift, cntrl; +}; + +/* + * default key handling + * + * This is the default NetHack keystroke processing. + * Use the .nethackrc "altkeyhandling" option to set a + * different handling type. + * + */ +/* + * Keypad keys are translated to the normal values below. + * Shifted keypad keys are translated to the + * shift values below. + */ + +static const struct pad default_keypad[PADKEYS] = { + { 'y', 'Y', C('y') }, /* 7 */ + { 'k', 'K', C('k') }, /* 8 */ + { 'u', 'U', C('u') }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { 'h', 'H', C('h') }, /* 4 */ + { 'g', 'G', 'g' }, /* 5 */ + { 'l', 'L', C('l') }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { 'b', 'B', C('b') }, /* 1 */ + { 'j', 'J', C('j') }, /* 2 */ + { 'n', 'N', C('n') }, /* 3 */ + { 'i', 'I', C('i') }, /* Ins */ + { '.', ':', ':' } /* Del */ +}, default_numpad[PADKEYS] = { + { '7', M('7'), '7' }, /* 7 */ + { '8', M('8'), '8' }, /* 8 */ + { '9', M('9'), '9' }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { '4', M('4'), '4' }, /* 4 */ + { '5', M('5'), '5' }, /* 5 */ + { '6', M('6'), '6' }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { '1', M('1'), '1' }, /* 1 */ + { '2', M('2'), '2' }, /* 2 */ + { '3', M('3'), '3' }, /* 3 */ + { '0', M('0'), '0' }, /* Ins */ + { '.', ':', ':' } /* Del */ +}; + +/* + * Keypad keys are translated to the normal values below. + * Shifted keypad keys are translated to the + * shift values below. + */ + +static const struct pad +ray_keypad[PADKEYS] = { + { 'y', 'Y', C('y') }, /* 7 */ + { 'k', 'K', C('k') }, /* 8 */ + { 'u', 'U', C('u') }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { 'h', 'H', C('h') }, /* 4 */ + { 'g', 'G', 'g' }, /* 5 */ + { 'l', 'L', C('l') }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { 'b', 'B', C('b') }, /* 1 */ + { 'j', 'J', C('j') }, /* 2 */ + { 'n', 'N', C('n') }, /* 3 */ + { 'i', 'I', C('i') }, /* Ins */ + { '.', ':', ':' } /* Del */ +}, +ray_numpad[PADKEYS] = { + { '7', M('7'), '7' }, /* 7 */ + { '8', M('8'), '8' }, /* 8 */ + { '9', M('9'), '9' }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { '4', M('4'), '4' }, /* 4 */ + { 'g', 'G', 'g' }, /* 5 */ + { '6', M('6'), '6' }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { '1', M('1'), '1' }, /* 1 */ + { '2', M('2'), '2' }, /* 2 */ + { '3', M('3'), '3' }, /* 3 */ + { 'i', 'I', C('i') }, /* Ins */ + { '.', ':', ':' } /* Del */ +}; + +static const struct pad +nh340_keypad[PADKEYS] = { + { 'y', 'Y', C('y') }, /* 7 */ + { 'k', 'K', C('k') }, /* 8 */ + { 'u', 'U', C('u') }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { 'h', 'H', C('h') }, /* 4 */ + { 'g', 'G', 'g' }, /* 5 */ + { 'l', 'L', C('l') }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { 'b', 'B', C('b') }, /* 1 */ + { 'j', 'J', C('j') }, /* 2 */ + { 'n', 'N', C('n') }, /* 3 */ + { 'i', 'I', C('i') }, /* Ins */ + { '.', ':', ':' } /* Del */ +}, +nh340_numpad[PADKEYS] = { + { '7', M('7'), '7' }, /* 7 */ + { '8', M('8'), '8' }, /* 8 */ + { '9', M('9'), '9' }, /* 9 */ + { 'm', C('p'), C('p') }, /* - */ + { '4', M('4'), '4' }, /* 4 */ + { 'g', 'G', 'g' }, /* 5 */ + { '6', M('6'), '6' }, /* 6 */ + { '+', 'P', C('p') }, /* + */ + { '1', M('1'), '1' }, /* 1 */ + { '2', M('2'), '2' }, /* 2 */ + { '3', M('3'), '3' }, /* 3 */ + { 'i', 'I', C('i') }, /* Ins */ + { '.', ':', ':' } /* Del */ +}; + +static struct pad keypad[PADKEYS], numpad[PADKEYS]; +static BYTE KeyState[256]; +static const char default_name[] = "default"; +const char *const legal_key_handling[] = { + "default", + "ray", + "340", +}; +enum windows_key_handling keyh[] = { default_keyhandling, ray_keyhandling, + nh340_keyhandling }; + +void set_altkeyhandling(const char *inName) +{ + int i, k; + /*backward compatibility - so people's existing config files + may work as is */ + if (!strcmpi(inName, "nhraykey.dll")) + inName = legal_key_handling[ray_keyhandling]; + else if (!strcmpi(inName, "nh340key.dll")) + inName = legal_key_handling[nh340_keyhandling]; + else if (!strcmpi(inName, "nhdefkey.dll")) + inName = legal_key_handling[default_keyhandling]; + + for (i = 0; i < SIZE(legal_key_handling); i++) { + if (!strcmpi(inName, legal_key_handling[i])) { + iflags.key_handling = keyh[i]; + if (keyboard_handling.pKeyHandlingName) { + free((genericptr_t) keyboard_handling.pKeyHandlingName); + keyboard_handling.pKeyHandlingName = (char *) 0; + } + switch(iflags.key_handling) { + case ray_keyhandling: + keyboard_handling.pKeyHandlingName = strdup("ray"); + keyboard_handling.pProcessKeystroke = ray_processkeystroke; + keyboard_handling.pNHkbhit = ray_kbhit; + keyboard_handling.pCheckInput = ray_checkinput; + /* A bogus key that will be filtered when received, to keep ReadConsole + * from blocking */ + bogus_key.EventType = KEY_EVENT; + bogus_key.Event.KeyEvent.bKeyDown = 1; + bogus_key.Event.KeyEvent.wRepeatCount = 1; + bogus_key.Event.KeyEvent.wVirtualKeyCode = 0; + bogus_key.Event.KeyEvent.wVirtualScanCode = 0; + bogus_key.Event.KeyEvent.uChar.AsciiChar = (uchar) 0x80; + bogus_key.Event.KeyEvent.dwControlKeyState = 0; + for (k = 0; k < SIZE(keypad); ++k) { + keypad[k] = ray_keypad[k]; + numpad[k] = ray_numpad[k]; + } + break; + case nh340_keyhandling: + keyboard_handling.pKeyHandlingName = strdup("340"); + keyboard_handling.pProcessKeystroke = nh340_processkeystroke; + keyboard_handling.pNHkbhit = nh340_kbhit; + keyboard_handling.pCheckInput = nh340_checkinput; + for (k = 0; k < SIZE(keypad); ++k) { + keypad[k] = nh340_keypad[k]; + numpad[k] = nh340_numpad[k]; + } + break; + case default_keyhandling: + default: + keyboard_handling.pKeyHandlingName = strdup("default"); + keyboard_handling.pProcessKeystroke + = default_processkeystroke; + keyboard_handling.pNHkbhit = default_kbhit; + keyboard_handling.pCheckInput = default_checkinput; + for (k = 0; k < SIZE(keypad); ++k) { + keypad[k] = default_keypad[k]; + numpad[k] = default_numpad[k]; + } + break; + } + return; + } + } + config_error_add("invalid altkeyhandling '%s'", inName); + return; +} + +int +set_keyhandling_via_option(void) +{ + winid tmpwin; + anything any; + int i; + menu_item *console_key_handling_pick = (menu_item *) 0; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin, MENU_BEHAVE_STANDARD); + any = cg.zeroany; + for (i = 0; i < SIZE(legal_key_handling); i++) { + any.a_int = i + 1; + add_menu(tmpwin, &nul_glyphinfo, &any, 'a' + i, + 0, ATR_NONE, + legal_key_handling[i], MENU_ITEMFLAGS_NONE); + } + end_menu(tmpwin, "Select windows console key handling:"); + if (select_menu(tmpwin, PICK_ONE, &console_key_handling_pick) > 0) { + iflags.key_handling = keyh[console_key_handling_pick->item.a_int - 1]; + free((genericptr_t) console_key_handling_pick); + } + destroy_nhwindow(tmpwin); + set_altkeyhandling(legal_key_handling[iflags.key_handling]); + return 1; /* optn_ok */ +} + +int +default_processkeystroke( + HANDLE hConIn, + INPUT_RECORD* ir, + boolean* valid, + boolean numberpad, + int portdebug) +{ + int k = 0; + int keycode, vk; + unsigned char ch, pre_ch; + unsigned short int scan; + unsigned long shiftstate; + int altseq = 0; + const struct pad *kpad; + +#ifdef QWERTZ_SUPPORT + if (numberpad & 0x10) { + numberpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + shiftstate = 0L; + ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + keycode = MapVirtualKey(vk, 2); + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + KeyState[VK_SHIFT] = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0; + KeyState[VK_CONTROL] = + (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ? 0x81 : 0; + KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0; + + if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || (iskeypad(scan)) || (altseq > 0)) + *valid = TRUE; + /* if (!valid) return 0; */ + /* + * shiftstate can be checked to see if various special + * keys were pressed at the same time as the key. + * Currently we are using the ALT & SHIFT & CONTROLS. + * + * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, + * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, + * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, + * CAPSLOCK_ON, ENHANCED_KEY + * + * are all valid bit masks to use on shiftstate. + * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the + * left control key was pressed with the keystroke. + */ + if (iskeypad(scan)) { + kpad = numberpad ? numpad : keypad; + if (shiftstate & SHIFT_PRESSED) { + ch = kpad[scan - KEYPADLO].shift; + } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { + ch = kpad[scan - KEYPADLO].cntrl; + } else { + ch = kpad[scan - KEYPADLO].normal; + } +#ifdef QWERTZ_SUPPORT + /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, + 'numberpad' will be 0; core swaps y to zap, z to move northwest; + we want numpad 7 to move northwest, so when qwertz is set, + tell core that user who types numpad 7 typed z rather than y */ + if (qwertz && kpad[scan - KEYPADLO].normal == 'y') + ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ +#endif /*QWERTZ_SUPPORT*/ + } else if (altseq > 0) { /* ALT sequence */ + if (vk == 0xBF) + ch = M('?'); + else + ch = M(tolower((uchar) keycode)); + } + /* Attempt to work better with international keyboards. */ + else { + WORD chr[2]; + k = ToAscii(vk, scan, KeyState, chr, 0); + if (k <= 2) + switch (k) { + case 2: /* two characters */ + ch = (unsigned char) chr[1]; + *valid = TRUE; + break; + case 1: /* one character */ + ch = (unsigned char) chr[0]; + *valid = TRUE; + break; + case 0: /* no translation */ + default: /* negative */ + *valid = FALSE; + } + } + if (ch == '\r') + ch = '\n'; +#ifdef PORT_DEBUG + if (portdebug) { + char buf[BUFSZ]; + Sprintf(buf, "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%lX, " + "ta=%d (ESC to end)", + "default", ch, scan, vk, pre_ch, shiftstate, k); + fprintf(stdout, "\n%s", buf); + } +#endif + return ch; +} + +int +default_kbhit(HANDLE hConIn, INPUT_RECORD *ir) +{ + int done = 0; /* true = "stop searching" */ + int retval; /* true = "we had a match" */ + DWORD count; + unsigned short int scan; + unsigned char ch; + unsigned long shiftstate; + int altseq = 0, keycode, vk; + done = 0; + retval = 0; + while (!done) { + count = 0; + PeekConsoleInput(hConIn, ir, 1, &count); + if (count > 0) { + if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { + ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + keycode = MapVirtualKey(vk, 2); + if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || iskeypad(scan) || altseq) { + done = 1; /* Stop looking */ + retval = 1; /* Found what we sought */ + } else { + /* Strange Key event; let's purge it to avoid trouble */ + ReadConsoleInput(hConIn, ir, 1, &count); + } + + } else if ((ir->EventType == MOUSE_EVENT + && (ir->Event.MouseEvent.dwButtonState + & MOUSEMASK))) { + done = 1; + retval = 1; + } + + else /* Discard it, it's an insignificant event */ + ReadConsoleInput(hConIn, ir, 1, &count); + } else /* There are no events in console event queue */ { + done = 1; /* Stop looking */ + retval = 0; + } + } + return retval; +} + +int +default_checkinput( + HANDLE hConIn, + INPUT_RECORD *ir, + DWORD* count, + boolean numpad, + int mode, + int *mod, + coord *cc) +{ +#if defined(SAFERHANGUP) + DWORD dwWait; +#endif + int ch = 0; + boolean valid = 0, done = 0; + +#ifdef QWERTZ_SUPPORT + if (numpad & 0x10) { + numpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + while (!done) { +#if defined(SAFERHANGUP) + dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for + INFINITE, // waits indefinitely + TRUE); // alertable wait enabled + if (dwWait == WAIT_FAILED) + return '\033'; +#endif + ReadConsoleInput(hConIn, ir, 1, count); + if (mode == 0) { + if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { + ch = default_processkeystroke(hConIn, ir, &valid, numpad, 0); + done = valid; + } + } else { + if (count > 0) { + if (ir->EventType == KEY_EVENT + && ir->Event.KeyEvent.bKeyDown) { +#ifdef QWERTZ_SUPPORT + if (qwertz) + numpad |= 0x10; +#endif + ch = default_processkeystroke(hConIn, ir, &valid, numpad, 0); +#ifdef QWERTZ_SUPPORT + numpad &= ~0x10; +#endif + if (valid) + return ch; + } else if (ir->EventType == MOUSE_EVENT) { + if ((ir->Event.MouseEvent.dwEventFlags == 0) + && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) { + cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1; + cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1; + + if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON) + *mod = CLICK_1; + else if (ir->Event.MouseEvent.dwButtonState + & RIGHTBUTTON) + *mod = CLICK_2; +#if 0 /* middle button */ + else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) + *mod = CLICK_3; +#endif + return 0; + } + } + } else + done = 1; + } + } + return mode ? 0 : ch; +} + +/* + * Keystroke handling contributed by Ray Chason. + * The following text was written by Ray Chason. + * + * The problem + * =========== + * + * The console-mode Nethack wants both keyboard and mouse input. The + * problem is that the Windows API provides no easy way to get mouse input + * and also keyboard input properly translated according to the user's + * chosen keyboard layout. + * + * The ReadConsoleInput function returns a stream of keyboard and mouse + * events. Nethack is interested in those events that represent a key + * pressed, or a click on a mouse button. The keyboard events from + * ReadConsoleInput are not translated according to the keyboard layout, + * and do not take into account the shift, control, or alt keys. + * + * The PeekConsoleInput function works similarly to ReadConsoleInput, + * except that it does not remove an event from the queue and it returns + * instead of blocking when the queue is empty. + * + * A program can also use ReadConsole to get a properly translated stream + * of characters. Unfortunately, ReadConsole does not return mouse events, + * does not distinguish the keypad from the main keyboard, does not return + * keys shifted with Alt, and does not even return the ESC key when + * pressed. + * + * We want both the functionality of ReadConsole and the functionality of + * ReadConsoleInput. But Microsoft didn't seem to think of that. + * + * + * The solution, in the original code + * ================================== + * + * The original 3.4.1 distribution tries to get proper keyboard translation + * by passing keyboard events to the ToAscii function. This works, to some + * extent -- it takes the shift key into account, and it processes dead + * keys properly. But it doesn't take non-US keyboards into account. It + * appears that ToAscii is meant for windowed applications, and does not + * have enough information to do its job properly in a console application. + * + * + * The Finnish keyboard patch + * ========================== + * + * This patch adds the "subkeyvalue" option to the defaults.nh file. The + * user can then add OPTIONS=sukeyvalue:171/92, for instance, to replace + * the 171 character with 92, which is \. This works, once properly + * configured, but places too much burden on the user. It also bars the + * use of the substituted characters in naming objects or monsters. + * + * + * The solution presented here + * =========================== + * + * The best way I could find to combine the functionality of ReadConsole + * with that of ReadConsoleInput is simple in concept. First, call + * PeekConsoleInput to get the first event. If it represents a key press, + * call ReadConsole to retrieve the key. Otherwise, pop it off the queue + * with ReadConsoleInput and, if it's a mouse click, return it as such. + * + * But the Devil, as they say, is in the details. The problem is in + * recognizing an event that ReadConsole will return as a key. We don't + * want to call ReadConsole unless we know that it will immediately return: + * if it blocks, the mouse and the Alt sequences will cease to function + * until it returns. + * + * Separating process_keystroke into two functions, one for commands and a + * new one, process_keystroke2, for answering prompts, makes the job a lot + * easier. process_keystroke2 doesn't have to worry about mouse events or + * Alt sequences, and so the consequences are minor if ReadConsole blocks. + * process_keystroke, OTOH, never needs to return a non-ASCII character + * that was read from ReadConsole; it returns bytes with the high bit set + * only in response to an Alt sequence. + * + * So in process_keystroke, before calling ReadConsole, a bogus key event + * is pushed on the queue. This event causes ReadConsole to return, even + * if there was no other character available. Because the bogus key has + * the eighth bit set, it is filtered out. This is not done in + * process_keystroke2, because that would render dead keys unusable. + * + * A separate process_keystroke2 can also process the numeric keypad in a + * way that makes sense for prompts: just return the corresponding symbol, + * and pay no mind to number_pad or the num lock key. + * + * The recognition of Alt sequences is modified, to support the use of + * characters generated with the AltGr key. A keystroke is an Alt sequence + * if an Alt key is seen that can't be an AltGr (since an AltGr sequence + * could be a character, and in some layouts it could even be an ASCII + * character). This recognition is different on NT-based and 95-based + * Windows: + * + * * On NT-based Windows, AltGr signals as right Alt and left Ctrl + * together. So an Alt sequence is recognized if either Alt key is + * pressed and if right Alt and left Ctrl are not both present. This + * is true even if the keyboard in use does not have an AltGr key, and + * uses right Alt for AltGr. + * + * * On 95-based Windows, with a keyboard that lacks the AltGr key, the + * right Alt key is used instead. But it still signals as right Alt, + * without left Ctrl. There is no way for the application to know + * whether right Alt is Alt or AltGr, and so it is always assumed + * to be AltGr. This means that Alt sequences must be formed with + * left Alt. + * + * So the patch processes keystrokes as follows: + * + * * If the scan and virtual key codes are both 0, it's the bogus key, + * and we ignore it. + * + * * Keys on the numeric keypad are processed for commands as in the + * unpatched Nethack, and for prompts by returning the ASCII + * character, even if the num lock is off. + * + * * Alt sequences are processed for commands as in the unpatched + * Nethack, and ignored for prompts. + * + * * Control codes are returned as received, because ReadConsole will + * not return the ESC key. + * + * * Other key-down events are passed to ReadConsole. The use of + * ReadConsole is different for commands than for prompts: + * + * o For commands, the bogus key is pushed onto the queue before + * ReadConsole is called. On return, non-ASCII characters are + * filtered, so they are not mistaken for Alt sequences; this also + * filters the bogus key. + * + * o For prompts, the bogus key is not used, because that would + * interfere with dead keys. Eight bit characters may be returned, + * and are coded in the configured code page. + * + * + * Possible improvements + * ===================== + * + * Some possible improvements remain: + * + * * Integrate the existing Finnish keyboard patch, for use with non- + * QWERTY layouts such as the German QWERTZ keyboard or Dvorak. + * + * * Fix the keyboard glitches in the graphical version. Namely, dead + * keys don't work, and input comes in as ISO-8859-1 but is displayed + * as code page 437 if IBMgraphics is set on startup. + * + * * Transform incoming text to ISO-8859-1, for full compatibility with + * the graphical version. + * + * * After pushing the bogus key and calling ReadConsole, check to see + * if we got the bogus key; if so, and an Alt is pressed, process the + * event as an Alt sequence. + * + */ + +#if 0 +static char where_to_get_source[] = "http://www.nethack.org/"; +static char author[] = "Ray Chason"; +#endif + +int process_keystroke2(HANDLE hConIn, INPUT_RECORD *ir, boolean *valid); + +/* Use ray_processkeystroke for key commands, process_keystroke2 for prompts */ +/* int ray_processkeystroke(INPUT_RECORD *ir, boolean *valid, int + * portdebug); + */ + +int process_keystroke2(HANDLE, INPUT_RECORD *ir, boolean *valid); +static int is_altseq(unsigned long shiftstate); + +static int +is_altseq(unsigned long shiftstate) +{ + /* We need to distinguish the Alt keys from the AltGr key. + * On NT-based Windows, AltGr signals as right Alt and left Ctrl together; + * on 95-based Windows, AltGr signals as right Alt only. + * So on NT, we signal Alt if either Alt is pressed and left Ctrl is not, + * and on 95, we signal Alt for left Alt only. */ + switch (shiftstate + & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { + case LEFT_ALT_PRESSED: + case LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED: + return 1; + + case RIGHT_ALT_PRESSED: + case RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED: + return (GetVersion() & 0x80000000) == 0; + + default: + return 0; + } +} + +int ray_processkeystroke( + HANDLE hConIn, + INPUT_RECORD *ir, + boolean *valid, + boolean numberpad, + int portdebug) +{ + int keycode, vk; + unsigned char ch, pre_ch; + unsigned short int scan; + unsigned long shiftstate; + int altseq = 0; + const struct pad *kpad; + DWORD count; + +#ifdef QWERTZ_SUPPORT + if (numberpad & 0x10) { + numberpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + shiftstate = 0L; + ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + keycode = MapVirtualKey(vk, 2); + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + if (scan == 0 && vk == 0) { + /* It's the bogus_key */ + ReadConsoleInput(hConIn, ir, 1, &count); + *valid = FALSE; + return 0; + } + + if (is_altseq(shiftstate)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || (iskeypad(scan)) || (altseq > 0)) + *valid = TRUE; + /* if (!valid) return 0; */ + /* + * shiftstate can be checked to see if various special + * keys were pressed at the same time as the key. + * Currently we are using the ALT & SHIFT & CONTROLS. + * + * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, + * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, + * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, + * CAPSLOCK_ON, ENHANCED_KEY + * + * are all valid bit masks to use on shiftstate. + * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the + * left control key was pressed with the keystroke. + */ + if (iskeypad(scan)) { + ReadConsoleInput(hConIn, ir, 1, &count); + kpad = numberpad ? numpad : keypad; + if (shiftstate & SHIFT_PRESSED) { + ch = kpad[scan - KEYPADLO].shift; + } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { + ch = kpad[scan - KEYPADLO].cntrl; + } else { + ch = kpad[scan - KEYPADLO].normal; + } +#ifdef QWERTZ_SUPPORT + /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, + 'numberpad' will be 0; core swaps y to zap, z to move northwest; + we want numpad 7 to move northwest, so when qwertz is set, + tell core that user who types numpad 7 typed z rather than y */ + if (qwertz && kpad[scan - KEYPADLO].normal == 'y') + ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ +#endif /*QWERTZ_SUPPORT*/ + } else if (altseq > 0) { /* ALT sequence */ + ReadConsoleInput(hConIn, ir, 1, &count); + if (vk == 0xBF) + ch = M('?'); + else + ch = M(tolower((uchar) keycode)); + } else if (ch < 32 && !isnumkeypad(scan)) { + /* Control code; ReadConsole seems to filter some of these, + * including ESC */ + ReadConsoleInput(hConIn, ir, 1, &count); + } + /* Attempt to work better with international keyboards. */ + else { + CHAR ch2; + DWORD written; + /* The bogus_key guarantees that ReadConsole will return, + * and does not itself do anything */ + WriteConsoleInput(hConIn, &bogus_key, 1, &written); + ReadConsole(hConIn, &ch2, 1, &count, NULL); + /* Prevent high characters from being interpreted as alt + * sequences; also filter the bogus_key */ + if (ch2 & 0x80) + *valid = FALSE; + else + ch = ch2; + if (ch == 0) + *valid = FALSE; + } + if (ch == '\r') + ch = '\n'; +#ifdef PORT_DEBUG + if (portdebug) { + char buf[BUFSZ]; + Sprintf(buf, "PORTDEBUG: ch=%u, scan=%u, vk=%d, pre=%d, " + "shiftstate=0x%lX (ESC to end)\n", + ch, scan, vk, pre_ch, shiftstate); + fprintf(stdout, "\n%s", buf); + } +#endif + return ch; +} + +int +process_keystroke2( + HANDLE hConIn, + INPUT_RECORD *ir, + boolean *valid) +{ + /* Use these values for the numeric keypad */ + static const char keypad_nums[] = "789-456+1230."; + + unsigned char ch; + int vk; + unsigned short int scan; + unsigned long shiftstate; + int altseq; + DWORD count; + + ch = ir->Event.KeyEvent.uChar.AsciiChar; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + scan = ir->Event.KeyEvent.wVirtualScanCode; + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + + if (scan == 0 && vk == 0) { + /* It's the bogus_key */ + ReadConsoleInput(hConIn, ir, 1, &count); + *valid = FALSE; + return 0; + } + + altseq = is_altseq(shiftstate); + if (ch || (iskeypad(scan)) || altseq) + *valid = TRUE; + /* if (!valid) return 0; */ + /* + * shiftstate can be checked to see if various special + * keys were pressed at the same time as the key. + * Currently we are using the ALT & SHIFT & CONTROLS. + * + * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, + * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, + * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, + * CAPSLOCK_ON, ENHANCED_KEY + * + * are all valid bit masks to use on shiftstate. + * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the + * left control key was pressed with the keystroke. + */ + if (iskeypad(scan) && !altseq) { + ReadConsoleInput(hConIn, ir, 1, &count); + ch = keypad_nums[scan - KEYPADLO]; + } else if (ch < 32 && !isnumkeypad(scan)) { + /* Control code; ReadConsole seems to filter some of these, + * including ESC */ + ReadConsoleInput(hConIn, ir, 1, &count); + } + /* Attempt to work better with international keyboards. */ + else { + CHAR ch2; + ReadConsole(hConIn, &ch2, 1, &count, NULL); + ch = ch2 & 0xFF; + if (ch == 0) + *valid = FALSE; + } + if (ch == '\r') + ch = '\n'; + return ch; +} + +int +ray_checkinput( + HANDLE hConIn, + INPUT_RECORD *ir, + DWORD *count, + boolean numpad, + int mode, + int *mod, + coord *cc) +{ +#if defined(SAFERHANGUP) + DWORD dwWait; +#endif + int ch = 0; + boolean valid = 0, done = 0; + +#ifdef QWERTZ_SUPPORT + if (numpad & 0x10) { + numpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + while (!done) { + *count = 0; + dwWait = WaitForSingleObject(hConIn, INFINITE); +#if defined(SAFERHANGUP) + if (dwWait == WAIT_FAILED) + return '\033'; +#endif + PeekConsoleInput(hConIn, ir, 1, count); + if (mode == 0) { + if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { + ch = process_keystroke2(hConIn, ir, &valid); + done = valid; + } else + ReadConsoleInput(hConIn, ir, 1, count); + } else { + ch = 0; + if (count > 0) { + if (ir->EventType == KEY_EVENT + && ir->Event.KeyEvent.bKeyDown) { +#ifdef QWERTZ_SUPPORT + if (qwertz) + numpad |= 0x10; +#endif + ch = ray_processkeystroke(hConIn, ir, &valid, numpad, +#ifdef PORTDEBUG + 1); +#else + 0); +#endif +#ifdef QWERTZ_SUPPORT + numpad &= ~0x10; +#endif + if (valid) + return ch; + } else { + ReadConsoleInput(hConIn, ir, 1, count); + if (ir->EventType == MOUSE_EVENT) { + if ((ir->Event.MouseEvent.dwEventFlags == 0) + && (ir->Event.MouseEvent.dwButtonState + & MOUSEMASK)) { + cc->x = + ir->Event.MouseEvent.dwMousePosition.X + 1; + cc->y = + ir->Event.MouseEvent.dwMousePosition.Y - 1; + + if (ir->Event.MouseEvent.dwButtonState + & LEFTBUTTON) + *mod = CLICK_1; + else if (ir->Event.MouseEvent.dwButtonState + & RIGHTBUTTON) + *mod = CLICK_2; +#if 0 /* middle button */ + else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) + *mod = CLICK_3; +#endif + return 0; + } + } +#if 0 + /* We ignore these types of console events */ + else if (ir->EventType == FOCUS_EVENT) { + } + else if (ir->EventType == MENU_EVENT) { + } +#endif + } + } else + done = 1; + } + } + *mod = 0; + return ch; +} + +int +ray_kbhit( + HANDLE hConIn, + INPUT_RECORD *ir) +{ + int done = 0; /* true = "stop searching" */ + int retval; /* true = "we had a match" */ + DWORD count; + unsigned short int scan; + unsigned char ch; + unsigned long shiftstate; + int altseq = 0, keycode, vk; + + done = 0; + retval = 0; + while (!done) { + count = 0; + PeekConsoleInput(hConIn, ir, 1, &count); + if (count > 0) { + if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { + ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + if (scan == 0 && vk == 0) { + /* It's the bogus_key. Discard it */ + ReadConsoleInput(hConIn,ir,1,&count); + } else { + keycode = MapVirtualKey(vk, 2); + if (is_altseq(shiftstate)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || iskeypad(scan) || altseq) { + done = 1; /* Stop looking */ + retval = 1; /* Found what we sought */ + } else { + /* Strange Key event; let's purge it to avoid trouble */ + ReadConsoleInput(hConIn, ir, 1, &count); + } + } + + } else if ((ir->EventType == MOUSE_EVENT + && (ir->Event.MouseEvent.dwButtonState + & MOUSEMASK))) { + done = 1; + retval = 1; + } + + else /* Discard it, it's an insignificant event */ + ReadConsoleInput(hConIn, ir, 1, &count); + } else /* There are no events in console event queue */ { + done = 1; /* Stop looking */ + retval = 0; + } + } + return retval; +} + +/* + * nh340 key handling + * + * This is the NetHack keystroke processing from NetHack 3.4.0. + * It can be built as a run-time loadable dll (nh340key.dll), + * placed in the same directory as the nethack.exe executable, + * and loaded by specifying OPTIONS=altkeyhandler:nh340key + * in defaults.nh + * + * Keypad keys are translated to the normal values below. + * Shifted keypad keys are translated to the + * shift values below. + */ + +int +nh340_processkeystroke( + HANDLE hConIn, + INPUT_RECORD *ir, + boolean *valid, + boolean numberpad, + int portdebug) +{ + int keycode, vk; + unsigned char ch, pre_ch; + unsigned short int scan; + unsigned long shiftstate; + int altseq = 0; + const struct pad *kpad; + +#ifdef QWERTZ_SUPPORT + if (numberpad & 0x10) { + numberpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + + shiftstate = 0L; + ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + keycode = MapVirtualKey(vk, 2); + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + + if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || (iskeypad(scan)) || (altseq > 0)) + *valid = TRUE; + /* if (!valid) return 0; */ + /* + * shiftstate can be checked to see if various special + * keys were pressed at the same time as the key. + * Currently we are using the ALT & SHIFT & CONTROLS. + * + * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, + * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, + * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, + * CAPSLOCK_ON, ENHANCED_KEY + * + * are all valid bit masks to use on shiftstate. + * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the + * left control key was pressed with the keystroke. + */ + if (iskeypad(scan)) { + kpad = numberpad ? numpad : keypad; + if (shiftstate & SHIFT_PRESSED) { + ch = kpad[scan - KEYPADLO].shift; + } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { + ch = kpad[scan - KEYPADLO].cntrl; + } else { + ch = kpad[scan - KEYPADLO].normal; + } +#ifdef QWERTZ_SUPPORT + /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, + 'numberpad' will be 0; core swaps y to zap, z to move northwest; + we want numpad 7 to move northwest, so when qwertz is set, + tell core that user who types numpad 7 typed z rather than y */ + if (qwertz && kpad[scan - KEYPADLO].normal == 'y') + ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ +#endif /*QWERTZ_SUPPORT*/ + } else if (altseq > 0) { /* ALT sequence */ + if (vk == 0xBF) + ch = M('?'); + else + ch = M(tolower((uchar) keycode)); + } + if (ch == '\r') + ch = '\n'; +#ifdef PORT_DEBUG + if (portdebug) { + char buf[BUFSZ]; + Sprintf(buf, + "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, sh=0x%lX (ESC to end)", + "nh340", ch, scan, vk, shiftstate); + fprintf(stdout, "\n%s", buf); + } +#endif + return ch; +} + +int +nh340_kbhit( + HANDLE hConIn, + INPUT_RECORD *ir) +{ + int done = 0; /* true = "stop searching" */ + int retval; /* true = "we had a match" */ + DWORD count; + unsigned short int scan; + unsigned char ch; + unsigned long shiftstate; + int altseq = 0, keycode, vk; + done = 0; + retval = 0; + while (!done) { + count = 0; + PeekConsoleInput(hConIn, ir, 1, &count); + if (count > 0) { + if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { + ch = ir->Event.KeyEvent.uChar.AsciiChar; + scan = ir->Event.KeyEvent.wVirtualScanCode; + shiftstate = ir->Event.KeyEvent.dwControlKeyState; + vk = ir->Event.KeyEvent.wVirtualKeyCode; + keycode = MapVirtualKey(vk, 2); + if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { + if (ch || inmap(keycode, vk)) + altseq = 1; + else + altseq = -1; /* invalid altseq */ + } + if (ch || iskeypad(scan) || altseq) { + done = 1; /* Stop looking */ + retval = 1; /* Found what we sought */ + } else { + /* Strange Key event; let's purge it to avoid trouble */ + ReadConsoleInput(hConIn, ir, 1, &count); + } + + } else if ((ir->EventType == MOUSE_EVENT + && (ir->Event.MouseEvent.dwButtonState + & MOUSEMASK))) { + done = 1; + retval = 1; + } + + else /* Discard it, it's an insignificant event */ + ReadConsoleInput(hConIn, ir, 1, &count); + } else /* There are no events in console event queue */ { + done = 1; /* Stop looking */ + retval = 0; + } + } + return retval; +} + +int +nh340_checkinput( + HANDLE hConIn, + INPUT_RECORD *ir, + DWORD *count, + boolean numpad, + int mode, + int *mod, + coord *cc) +{ +#if defined(SAFERHANGUP) + DWORD dwWait; +#endif + int ch = 0; + boolean valid = 0, done = 0; + +#ifdef QWERTZ_SUPPORT + if (numpad & 0x10) { + numpad &= ~0x10; + qwertz = TRUE; + } else { + qwertz = FALSE; + } +#endif + while (!done) { +#if defined(SAFERHANGUP) + dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for + INFINITE, // waits indefinitely + TRUE); // alertable wait enabled + if (dwWait == WAIT_FAILED) + return '\033'; +#endif + ReadConsoleInput(hConIn, ir, 1, count); + if (mode == 0) { + if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { +#ifdef QWERTZ_SUPPORT + if (qwertz) + numpad |= 0x10; +#endif + ch = nh340_processkeystroke(hConIn, ir, &valid, numpad, 0); +#ifdef QWERTZ_SUPPORT + numpad &= ~0x10; +#endif + done = valid; + } + } else { + if (count > 0) { + if (ir->EventType == KEY_EVENT + && ir->Event.KeyEvent.bKeyDown) { + ch = nh340_processkeystroke(hConIn, ir, &valid, numpad, 0); + if (valid) + return ch; + } else if (ir->EventType == MOUSE_EVENT) { + if ((ir->Event.MouseEvent.dwEventFlags == 0) + && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) { + cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1; + cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1; + + if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON) + *mod = CLICK_1; + else if (ir->Event.MouseEvent.dwButtonState + & RIGHTBUTTON) + *mod = CLICK_2; +#if 0 /* middle button */ + else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) + *mod = CLICK_3; +#endif + return 0; + } + } + } else + done = 1; + } + } + return mode ? 0 : ch; +} + #endif /* WIN32 */ diff --git a/sys/windows/nh340key.c b/sys/windows/nh340key.c deleted file mode 100644 index 1a54ff27b..000000000 --- a/sys/windows/nh340key.c +++ /dev/null @@ -1,353 +0,0 @@ -/* NetHack 3.7 nh340key.c $NHDT-Date: 1596498312 2020/08/03 23:45:12 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.16 $ */ -/* Copyright (c) NetHack PC Development Team 2003 */ -/* NetHack may be freely redistributed. See license for details. */ - -/* - * This is the NetHack keystroke processing from NetHack 3.4.0. - * It can be built as a run-time loadable dll (nh340key.dll), - * placed in the same directory as the nethack.exe executable, - * and loaded by specifying OPTIONS=altkeyhandler:nh340key - * in defaults.nh - */ - -static char where_to_get_source[] = "http://www.nethack.org/"; -static char author[] = "The NetHack Development Team"; - -#include "win32api.h" -#include "hack.h" -#include "wintty.h" - -extern HANDLE hConIn; -extern INPUT_RECORD ir; -char dllname[512]; -char *shortdllname; - -int __declspec(dllexport) __stdcall ProcessKeystroke(HANDLE hConIn, - INPUT_RECORD *ir, boolean *valid, boolean numberpad, int portdebug); - -int WINAPI -DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) -{ - char dlltmpname[512]; - char *tmp = dlltmpname, *tmp2; - *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0'; - (void) strcpy(dllname, tmp); - tmp2 = strrchr(dllname, '\\'); - if (tmp2) { - tmp2++; - shortdllname = tmp2; - } - return TRUE; -} - -/* - * Keyboard translation tables. - * (Adopted from the MSDOS port) - */ - -#define KEYPADLO 0x47 -#define KEYPADHI 0x53 - -#define PADKEYS (KEYPADHI - KEYPADLO + 1) -#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI) - -#ifdef QWERTZ_SUPPORT -/* when 'numberpad' is 0 and Cmd.swap_yz is True - (signaled by setting 0x10 on boolean numpad argument) - treat keypress of numpad 7 as 'z' rather than 'y' */ -static boolean qwertz = FALSE; -#endif - -/* - * Keypad keys are translated to the normal values below. - * Shifted keypad keys are translated to the - * shift values below. - */ - -static const struct pad { - uchar normal, shift, cntrl; -} keypad[PADKEYS] = - { - { 'y', 'Y', C('y') }, /* 7 */ - { 'k', 'K', C('k') }, /* 8 */ - { 'u', 'U', C('u') }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { 'h', 'H', C('h') }, /* 4 */ - { 'g', 'G', 'g' }, /* 5 */ - { 'l', 'L', C('l') }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { 'b', 'B', C('b') }, /* 1 */ - { 'j', 'J', C('j') }, /* 2 */ - { 'n', 'N', C('n') }, /* 3 */ - { 'i', 'I', C('i') }, /* Ins */ - { '.', ':', ':' } /* Del */ - }, - numpad[PADKEYS] = { - { '7', M('7'), '7' }, /* 7 */ - { '8', M('8'), '8' }, /* 8 */ - { '9', M('9'), '9' }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { '4', M('4'), '4' }, /* 4 */ - { 'g', 'G', 'g' }, /* 5 */ - { '6', M('6'), '6' }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { '1', M('1'), '1' }, /* 1 */ - { '2', M('2'), '2' }, /* 2 */ - { '3', M('3'), '3' }, /* 3 */ - { 'i', 'I', C('i') }, /* Ins */ - { '.', ':', ':' } /* Del */ - }; - -#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2') - -int __declspec(dllexport) __stdcall -ProcessKeystroke( - HANDLE hConIn, - INPUT_RECORD *ir, - boolean *valid, - boolean numberpad, - int portdebug) -{ - int keycode, vk; - unsigned char ch, pre_ch; - unsigned short int scan; - unsigned long shiftstate; - int altseq = 0; - const struct pad *kpad; - -#ifdef QWERTZ_SUPPORT - if (numberpad & 0x10) { - numberpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - - shiftstate = 0L; - ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - keycode = MapVirtualKey(vk, 2); - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - - if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || (iskeypad(scan)) || (altseq > 0)) - *valid = TRUE; - /* if (!valid) return 0; */ - /* - * shiftstate can be checked to see if various special - * keys were pressed at the same time as the key. - * Currently we are using the ALT & SHIFT & CONTROLS. - * - * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, - * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, - * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, - * CAPSLOCK_ON, ENHANCED_KEY - * - * are all valid bit masks to use on shiftstate. - * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the - * left control key was pressed with the keystroke. - */ - if (iskeypad(scan)) { - kpad = numberpad ? numpad : keypad; - if (shiftstate & SHIFT_PRESSED) { - ch = kpad[scan - KEYPADLO].shift; - } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { - ch = kpad[scan - KEYPADLO].cntrl; - } else { - ch = kpad[scan - KEYPADLO].normal; - } -#ifdef QWERTZ_SUPPORT - /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, - 'numberpad' will be 0; core swaps y to zap, z to move northwest; - we want numpad 7 to move northwest, so when qwertz is set, - tell core that user who types numpad 7 typed z rather than y */ - if (qwertz && kpad[scan - KEYPADLO].normal == 'y') - ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ -#endif /*QWERTZ_SUPPORT*/ - } else if (altseq > 0) { /* ALT sequence */ - if (vk == 0xBF) - ch = M('?'); - else - ch = M(tolower((uchar) keycode)); - } - if (ch == '\r') - ch = '\n'; -#ifdef PORT_DEBUG - if (portdebug) { - char buf[BUFSZ]; - Sprintf(buf, - "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, sh=0x%lX (ESC to end)", - shortdllname, ch, scan, vk, shiftstate); - fprintf(stdout, "\n%s", buf); - } -#endif - return ch; -} - -int __declspec(dllexport) __stdcall -NHkbhit( - HANDLE hConIn, - INPUT_RECORD *ir) -{ - int done = 0; /* true = "stop searching" */ - int retval; /* true = "we had a match" */ - DWORD count; - unsigned short int scan; - unsigned char ch; - unsigned long shiftstate; - int altseq = 0, keycode, vk; - done = 0; - retval = 0; - while (!done) { - count = 0; - PeekConsoleInput(hConIn, ir, 1, &count); - if (count > 0) { - if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { - ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - keycode = MapVirtualKey(vk, 2); - if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || iskeypad(scan) || altseq) { - done = 1; /* Stop looking */ - retval = 1; /* Found what we sought */ - } else { - /* Strange Key event; let's purge it to avoid trouble */ - ReadConsoleInput(hConIn, ir, 1, &count); - } - - } else if ((ir->EventType == MOUSE_EVENT - && (ir->Event.MouseEvent.dwButtonState - & MOUSEMASK))) { - done = 1; - retval = 1; - } - - else /* Discard it, it's an insignificant event */ - ReadConsoleInput(hConIn, ir, 1, &count); - } else /* There are no events in console event queue */ { - done = 1; /* Stop looking */ - retval = 0; - } - } - return retval; -} - -int __declspec(dllexport) __stdcall CheckInput( - HANDLE hConIn, - INPUT_RECORD *ir, - DWORD *count, - boolean numpad, - int mode, - int *mod, - coord *cc) -{ -#if defined(SAFERHANGUP) - DWORD dwWait; -#endif - int ch = 0; - boolean valid = 0, done = 0; - -#ifdef QWERTZ_SUPPORT - if (numpad & 0x10) { - numpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - while (!done) { -#if defined(SAFERHANGUP) - dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for - INFINITE, // waits indefinitely - TRUE); // alertable wait enabled - if (dwWait == WAIT_FAILED) - return '\033'; -#endif - ReadConsoleInput(hConIn, ir, 1, count); - if (mode == 0) { - if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { -#ifdef QWERTZ_SUPPORT - if (qwertz) - numpad |= 0x10; -#endif - ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0); -#ifdef QWERTZ_SUPPORT - numpad &= ~0x10; -#endif - done = valid; - } - } else { - if (count > 0) { - if (ir->EventType == KEY_EVENT - && ir->Event.KeyEvent.bKeyDown) { - ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0); - if (valid) - return ch; - } else if (ir->EventType == MOUSE_EVENT) { - if ((ir->Event.MouseEvent.dwEventFlags == 0) - && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) { - cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1; - cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1; - - if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON) - *mod = CLICK_1; - else if (ir->Event.MouseEvent.dwButtonState - & RIGHTBUTTON) - *mod = CLICK_2; -#if 0 /* middle button */ - else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) - *mod = CLICK_3; -#endif - return 0; - } - } - } else - done = 1; - } - } - return mode ? 0 : ch; -} - -int __declspec(dllexport) __stdcall -SourceWhere(char** buf) -{ - if (!buf) - return 0; - *buf = where_to_get_source; - return 1; -} - -int __declspec(dllexport) __stdcall -SourceAuthor(char** buf) -{ - if (!buf) - return 0; - *buf = author; - return 1; -} - -int __declspec(dllexport) __stdcall -KeyHandlerName(char** buf, int full) -{ - if (!buf) - return 0; - if (full) - *buf = dllname; - else - *buf = shortdllname; - return 1; -} diff --git a/sys/windows/nhdefkey.c b/sys/windows/nhdefkey.c deleted file mode 100644 index a3bde087e..000000000 --- a/sys/windows/nhdefkey.c +++ /dev/null @@ -1,384 +0,0 @@ -/* NetHack 3.7 nhdefkey.c $NHDT-Date: 1596498313 2020/08/03 23:45:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.19 $ */ -/* Copyright (c) NetHack PC Development Team 2003 */ -/* NetHack may be freely redistributed. See license for details. */ - -/* - * This is the default NetHack keystroke processing. - * It can be built as a run-time loadable dll (nhdefkey.dll). - * Alternative keystroke handlers can be built using the - * entry points in this file as a template. - * - * Use the defaults.nh "altkeyhandler" option to set a - * different dll name (without the ".DLL" extension) to - * get different processing. Ensure that the dll referenced - * in defaults.nh exists in the same directory as NetHack in - * order for it to load successfully. - * - */ - -static char where_to_get_source[] = "http://www.nethack.org/"; -static char author[] = "The NetHack Development Team"; - -#include "win32api.h" -#include "hack.h" -#include "wintty.h" - -extern HANDLE hConIn; -extern INPUT_RECORD ir; - -char dllname[512]; -char *shortdllname; - -int __declspec(dllexport) __stdcall ProcessKeystroke(HANDLE hConIn, - INPUT_RECORD *ir, boolean *valid, boolean numberpad, int portdebug); - -int WINAPI -DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) -{ - char dlltmpname[512]; - char *tmp = dlltmpname, *tmp2; - *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0'; - (void) strcpy(dllname, tmp); - tmp2 = strrchr(dllname, '\\'); - if (tmp2) { - tmp2++; - shortdllname = tmp2; - } - return TRUE; -} - -/* - * Keyboard translation tables. - * (Adopted from the MSDOS port) - */ - -#define KEYPADLO 0x47 -#define KEYPADHI 0x53 - -#define PADKEYS (KEYPADHI - KEYPADLO + 1) -#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI) - -#ifdef QWERTZ_SUPPORT -/* when 'numberpad' is 0 and Cmd.swap_yz is True - (signaled by setting 0x10 on boolean numpad argument) - treat keypress of numpad 7 as 'z' rather than 'y' */ -static boolean qwertz = FALSE; -#endif - -/* - * Keypad keys are translated to the normal values below. - * Shifted keypad keys are translated to the - * shift values below. - */ - -static const struct pad { - uchar normal, shift, cntrl; -} keypad[PADKEYS] = - { - { 'y', 'Y', C('y') }, /* 7 */ - { 'k', 'K', C('k') }, /* 8 */ - { 'u', 'U', C('u') }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { 'h', 'H', C('h') }, /* 4 */ - { 'g', 'G', 'g' }, /* 5 */ - { 'l', 'L', C('l') }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { 'b', 'B', C('b') }, /* 1 */ - { 'j', 'J', C('j') }, /* 2 */ - { 'n', 'N', C('n') }, /* 3 */ - { 'i', 'I', C('i') }, /* Ins */ - { '.', ':', ':' } /* Del */ - }, - numpad[PADKEYS] = { - { '7', M('7'), '7' }, /* 7 */ - { '8', M('8'), '8' }, /* 8 */ - { '9', M('9'), '9' }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { '4', M('4'), '4' }, /* 4 */ - { '5', M('5'), '5' }, /* 5 */ - { '6', M('6'), '6' }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { '1', M('1'), '1' }, /* 1 */ - { '2', M('2'), '2' }, /* 2 */ - { '3', M('3'), '3' }, /* 3 */ - { '0', M('0'), '0' }, /* Ins */ - { '.', ':', ':' } /* Del */ - }; - -#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2') - -static BYTE KeyState[256]; - -int __declspec(dllexport) __stdcall -ProcessKeystroke( - HANDLE hConIn, - INPUT_RECORD* ir, - boolean* valid, - boolean numberpad, - int portdebug) -{ - int k = 0; - int keycode, vk; - unsigned char ch, pre_ch; - unsigned short int scan; - unsigned long shiftstate; - int altseq = 0; - const struct pad *kpad; - -#ifdef QWERTZ_SUPPORT - if (numberpad & 0x10) { - numberpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - shiftstate = 0L; - ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - keycode = MapVirtualKey(vk, 2); - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - KeyState[VK_SHIFT] = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0; - KeyState[VK_CONTROL] = - (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ? 0x81 : 0; - KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0; - - if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || (iskeypad(scan)) || (altseq > 0)) - *valid = TRUE; - /* if (!valid) return 0; */ - /* - * shiftstate can be checked to see if various special - * keys were pressed at the same time as the key. - * Currently we are using the ALT & SHIFT & CONTROLS. - * - * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, - * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, - * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, - * CAPSLOCK_ON, ENHANCED_KEY - * - * are all valid bit masks to use on shiftstate. - * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the - * left control key was pressed with the keystroke. - */ - if (iskeypad(scan)) { - kpad = numberpad ? numpad : keypad; - if (shiftstate & SHIFT_PRESSED) { - ch = kpad[scan - KEYPADLO].shift; - } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { - ch = kpad[scan - KEYPADLO].cntrl; - } else { - ch = kpad[scan - KEYPADLO].normal; - } -#ifdef QWERTZ_SUPPORT - /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, - 'numberpad' will be 0; core swaps y to zap, z to move northwest; - we want numpad 7 to move northwest, so when qwertz is set, - tell core that user who types numpad 7 typed z rather than y */ - if (qwertz && kpad[scan - KEYPADLO].normal == 'y') - ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ -#endif /*QWERTZ_SUPPORT*/ - } else if (altseq > 0) { /* ALT sequence */ - if (vk == 0xBF) - ch = M('?'); - else - ch = M(tolower((uchar) keycode)); - } - /* Attempt to work better with international keyboards. */ - else { - WORD chr[2]; - k = ToAscii(vk, scan, KeyState, chr, 0); - if (k <= 2) - switch (k) { - case 2: /* two characters */ - ch = (unsigned char) chr[1]; - *valid = TRUE; - break; - case 1: /* one character */ - ch = (unsigned char) chr[0]; - *valid = TRUE; - break; - case 0: /* no translation */ - default: /* negative */ - *valid = FALSE; - } - } - if (ch == '\r') - ch = '\n'; -#ifdef PORT_DEBUG - if (portdebug) { - char buf[BUFSZ]; - Sprintf(buf, "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%lX, " - "ta=%d (ESC to end)", - shortdllname, ch, scan, vk, pre_ch, shiftstate, k); - fprintf(stdout, "\n%s", buf); - } -#endif - return ch; -} - -int __declspec(dllexport) __stdcall -NHkbhit(HANDLE hConIn, INPUT_RECORD *ir) -{ - int done = 0; /* true = "stop searching" */ - int retval; /* true = "we had a match" */ - DWORD count; - unsigned short int scan; - unsigned char ch; - unsigned long shiftstate; - int altseq = 0, keycode, vk; - done = 0; - retval = 0; - while (!done) { - count = 0; - PeekConsoleInput(hConIn, ir, 1, &count); - if (count > 0) { - if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { - ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - keycode = MapVirtualKey(vk, 2); - if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || iskeypad(scan) || altseq) { - done = 1; /* Stop looking */ - retval = 1; /* Found what we sought */ - } else { - /* Strange Key event; let's purge it to avoid trouble */ - ReadConsoleInput(hConIn, ir, 1, &count); - } - - } else if ((ir->EventType == MOUSE_EVENT - && (ir->Event.MouseEvent.dwButtonState - & MOUSEMASK))) { - done = 1; - retval = 1; - } - - else /* Discard it, it's an insignificant event */ - ReadConsoleInput(hConIn, ir, 1, &count); - } else /* There are no events in console event queue */ { - done = 1; /* Stop looking */ - retval = 0; - } - } - return retval; -} - -int __declspec(dllexport) __stdcall -CheckInput( - HANDLE hConIn, - INPUT_RECORD *ir, - DWORD* count, - boolean numpad, - int mode, - int *mod, - coord *cc) -{ -#if defined(SAFERHANGUP) - DWORD dwWait; -#endif - int ch = 0; - boolean valid = 0, done = 0; - -#ifdef QWERTZ_SUPPORT - if (numpad & 0x10) { - numpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - while (!done) { -#if defined(SAFERHANGUP) - dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for - INFINITE, // waits indefinitely - TRUE); // alertable wait enabled - if (dwWait == WAIT_FAILED) - return '\033'; -#endif - ReadConsoleInput(hConIn, ir, 1, count); - if (mode == 0) { - if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { - ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0); - done = valid; - } - } else { - if (count > 0) { - if (ir->EventType == KEY_EVENT - && ir->Event.KeyEvent.bKeyDown) { -#ifdef QWERTZ_SUPPORT - if (qwertz) - numpad |= 0x10; -#endif - ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0); -#ifdef QWERTZ_SUPPORT - numpad &= ~0x10; -#endif - if (valid) - return ch; - } else if (ir->EventType == MOUSE_EVENT) { - if ((ir->Event.MouseEvent.dwEventFlags == 0) - && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) { - cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1; - cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1; - - if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON) - *mod = CLICK_1; - else if (ir->Event.MouseEvent.dwButtonState - & RIGHTBUTTON) - *mod = CLICK_2; -#if 0 /* middle button */ - else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) - *mod = CLICK_3; -#endif - return 0; - } - } - } else - done = 1; - } - } - return mode ? 0 : ch; -} - -int __declspec(dllexport) __stdcall -SourceWhere(char** buf) -{ - if (!buf) - return 0; - *buf = where_to_get_source; - return 1; -} - -int __declspec(dllexport) __stdcall -SourceAuthor(char **buf) -{ - if (!buf) - return 0; - *buf = author; - return 1; -} - -int __declspec(dllexport) __stdcall -KeyHandlerName(char **buf, int full) -{ - if (!buf) - return 0; - if (full) - *buf = dllname; - else - *buf = shortdllname; - return 1; -} diff --git a/sys/windows/nhraykey.c b/sys/windows/nhraykey.c deleted file mode 100644 index 978b6564f..000000000 --- a/sys/windows/nhraykey.c +++ /dev/null @@ -1,666 +0,0 @@ -/* NetHack 3.7 nhraykey.c $NHDT-Date: 1596498314 2020/08/03 23:45:14 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.21 $ */ -/* Copyright (c) NetHack PC Development Team 2003 */ -/* NetHack may be freely redistributed. See license for details. */ - -/* - * Keystroke handling contributed by Ray Chason. - * The following text was written by Ray Chason. - * - * The problem - * =========== - * - * The console-mode Nethack wants both keyboard and mouse input. The - * problem is that the Windows API provides no easy way to get mouse input - * and also keyboard input properly translated according to the user's - * chosen keyboard layout. - * - * The ReadConsoleInput function returns a stream of keyboard and mouse - * events. Nethack is interested in those events that represent a key - * pressed, or a click on a mouse button. The keyboard events from - * ReadConsoleInput are not translated according to the keyboard layout, - * and do not take into account the shift, control, or alt keys. - * - * The PeekConsoleInput function works similarly to ReadConsoleInput, - * except that it does not remove an event from the queue and it returns - * instead of blocking when the queue is empty. - * - * A program can also use ReadConsole to get a properly translated stream - * of characters. Unfortunately, ReadConsole does not return mouse events, - * does not distinguish the keypad from the main keyboard, does not return - * keys shifted with Alt, and does not even return the ESC key when - * pressed. - * - * We want both the functionality of ReadConsole and the functionality of - * ReadConsoleInput. But Microsoft didn't seem to think of that. - * - * - * The solution, in the original code - * ================================== - * - * The original 3.4.1 distribution tries to get proper keyboard translation - * by passing keyboard events to the ToAscii function. This works, to some - * extent -- it takes the shift key into account, and it processes dead - * keys properly. But it doesn't take non-US keyboards into account. It - * appears that ToAscii is meant for windowed applications, and does not - * have enough information to do its job properly in a console application. - * - * - * The Finnish keyboard patch - * ========================== - * - * This patch adds the "subkeyvalue" option to the defaults.nh file. The - * user can then add OPTIONS=sukeyvalue:171/92, for instance, to replace - * the 171 character with 92, which is \. This works, once properly - * configured, but places too much burden on the user. It also bars the - * use of the substituted characters in naming objects or monsters. - * - * - * The solution presented here - * =========================== - * - * The best way I could find to combine the functionality of ReadConsole - * with that of ReadConsoleInput is simple in concept. First, call - * PeekConsoleInput to get the first event. If it represents a key press, - * call ReadConsole to retrieve the key. Otherwise, pop it off the queue - * with ReadConsoleInput and, if it's a mouse click, return it as such. - * - * But the Devil, as they say, is in the details. The problem is in - * recognizing an event that ReadConsole will return as a key. We don't - * want to call ReadConsole unless we know that it will immediately return: - * if it blocks, the mouse and the Alt sequences will cease to function - * until it returns. - * - * Separating process_keystroke into two functions, one for commands and a - * new one, process_keystroke2, for answering prompts, makes the job a lot - * easier. process_keystroke2 doesn't have to worry about mouse events or - * Alt sequences, and so the consequences are minor if ReadConsole blocks. - * process_keystroke, OTOH, never needs to return a non-ASCII character - * that was read from ReadConsole; it returns bytes with the high bit set - * only in response to an Alt sequence. - * - * So in process_keystroke, before calling ReadConsole, a bogus key event - * is pushed on the queue. This event causes ReadConsole to return, even - * if there was no other character available. Because the bogus key has - * the eighth bit set, it is filtered out. This is not done in - * process_keystroke2, because that would render dead keys unusable. - * - * A separate process_keystroke2 can also process the numeric keypad in a - * way that makes sense for prompts: just return the corresponding symbol, - * and pay no mind to number_pad or the num lock key. - * - * The recognition of Alt sequences is modified, to support the use of - * characters generated with the AltGr key. A keystroke is an Alt sequence - * if an Alt key is seen that can't be an AltGr (since an AltGr sequence - * could be a character, and in some layouts it could even be an ASCII - * character). This recognition is different on NT-based and 95-based - * Windows: - * - * * On NT-based Windows, AltGr signals as right Alt and left Ctrl - * together. So an Alt sequence is recognized if either Alt key is - * pressed and if right Alt and left Ctrl are not both present. This - * is true even if the keyboard in use does not have an AltGr key, and - * uses right Alt for AltGr. - * - * * On 95-based Windows, with a keyboard that lacks the AltGr key, the - * right Alt key is used instead. But it still signals as right Alt, - * without left Ctrl. There is no way for the application to know - * whether right Alt is Alt or AltGr, and so it is always assumed - * to be AltGr. This means that Alt sequences must be formed with - * left Alt. - * - * So the patch processes keystrokes as follows: - * - * * If the scan and virtual key codes are both 0, it's the bogus key, - * and we ignore it. - * - * * Keys on the numeric keypad are processed for commands as in the - * unpatched Nethack, and for prompts by returning the ASCII - * character, even if the num lock is off. - * - * * Alt sequences are processed for commands as in the unpatched - * Nethack, and ignored for prompts. - * - * * Control codes are returned as received, because ReadConsole will - * not return the ESC key. - * - * * Other key-down events are passed to ReadConsole. The use of - * ReadConsole is different for commands than for prompts: - * - * o For commands, the bogus key is pushed onto the queue before - * ReadConsole is called. On return, non-ASCII characters are - * filtered, so they are not mistaken for Alt sequences; this also - * filters the bogus key. - * - * o For prompts, the bogus key is not used, because that would - * interfere with dead keys. Eight bit characters may be returned, - * and are coded in the configured code page. - * - * - * Possible improvements - * ===================== - * - * Some possible improvements remain: - * - * * Integrate the existing Finnish keyboard patch, for use with non- - * QWERTY layouts such as the German QWERTZ keyboard or Dvorak. - * - * * Fix the keyboard glitches in the graphical version. Namely, dead - * keys don't work, and input comes in as ISO-8859-1 but is displayed - * as code page 437 if IBMgraphics is set on startup. - * - * * Transform incoming text to ISO-8859-1, for full compatibility with - * the graphical version. - * - * * After pushing the bogus key and calling ReadConsole, check to see - * if we got the bogus key; if so, and an Alt is pressed, process the - * event as an Alt sequence. - * - */ - -static char where_to_get_source[] = "http://www.nethack.org/"; -static char author[] = "Ray Chason"; - -#include "win32api.h" -#include "hack.h" -#include "wintty.h" - -extern HANDLE hConIn; -extern INPUT_RECORD ir; -char dllname[512]; -char *shortdllname; - -int __declspec(dllexport) __stdcall ProcessKeystroke(HANDLE hConIn, - INPUT_RECORD *ir, boolean *valid, boolean numberpad, int portdebug); - -static INPUT_RECORD bogus_key; - -int WINAPI -DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) -{ - char dlltmpname[512]; - char *tmp = dlltmpname, *tmp2; - *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0'; - (void) strcpy(dllname, tmp); - tmp2 = strrchr(dllname, '\\'); - if (tmp2) { - tmp2++; - shortdllname = tmp2; - } - /* A bogus key that will be filtered when received, to keep ReadConsole - * from blocking */ - bogus_key.EventType = KEY_EVENT; - bogus_key.Event.KeyEvent.bKeyDown = 1; - bogus_key.Event.KeyEvent.wRepeatCount = 1; - bogus_key.Event.KeyEvent.wVirtualKeyCode = 0; - bogus_key.Event.KeyEvent.wVirtualScanCode = 0; - bogus_key.Event.KeyEvent.uChar.AsciiChar = (uchar) 0x80; - bogus_key.Event.KeyEvent.dwControlKeyState = 0; - return TRUE; -} - -/* - * Keyboard translation tables. - * (Adopted from the MSDOS port) - */ - -#define KEYPADLO 0x47 -#define KEYPADHI 0x53 - -#define PADKEYS (KEYPADHI - KEYPADLO + 1) -#define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI) -#define isnumkeypad(x) \ - (KEYPADLO <= (x) && (x) <= 0x51 && (x) != 0x4A && (x) != 0x4E) - -#ifdef QWERTZ_SUPPORT -/* when 'numberpad' is 0 and Cmd.swap_yz is True - (signaled by setting 0x10 on boolean numpad argument) - treat keypress of numpad 7 as 'z' rather than 'y' */ -static boolean qwertz = FALSE; -#endif - -/* - * Keypad keys are translated to the normal values below. - * Shifted keypad keys are translated to the - * shift values below. - */ - -static const struct pad { - uchar normal, shift, cntrl; -} keypad[PADKEYS] = - { - { 'y', 'Y', C('y') }, /* 7 */ - { 'k', 'K', C('k') }, /* 8 */ - { 'u', 'U', C('u') }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { 'h', 'H', C('h') }, /* 4 */ - { 'g', 'G', 'g' }, /* 5 */ - { 'l', 'L', C('l') }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { 'b', 'B', C('b') }, /* 1 */ - { 'j', 'J', C('j') }, /* 2 */ - { 'n', 'N', C('n') }, /* 3 */ - { 'i', 'I', C('i') }, /* Ins */ - { '.', ':', ':' } /* Del */ - }, - numpad[PADKEYS] = { - { '7', M('7'), '7' }, /* 7 */ - { '8', M('8'), '8' }, /* 8 */ - { '9', M('9'), '9' }, /* 9 */ - { 'm', C('p'), C('p') }, /* - */ - { '4', M('4'), '4' }, /* 4 */ - { 'g', 'G', 'g' }, /* 5 */ - { '6', M('6'), '6' }, /* 6 */ - { '+', 'P', C('p') }, /* + */ - { '1', M('1'), '1' }, /* 1 */ - { '2', M('2'), '2' }, /* 2 */ - { '3', M('3'), '3' }, /* 3 */ - { 'i', 'I', C('i') }, /* Ins */ - { '.', ':', ':' } /* Del */ - }; - -#define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2') - -/* Use process_keystroke for key commands, process_keystroke2 for prompts */ -/* int process_keystroke(INPUT_RECORD *ir, boolean *valid, int - * portdebug); */ -int process_keystroke2(HANDLE, INPUT_RECORD *ir, boolean *valid); -static int is_altseq(unsigned long shiftstate); - -static int -is_altseq(unsigned long shiftstate) -{ - /* We need to distinguish the Alt keys from the AltGr key. - * On NT-based Windows, AltGr signals as right Alt and left Ctrl together; - * on 95-based Windows, AltGr signals as right Alt only. - * So on NT, we signal Alt if either Alt is pressed and left Ctrl is not, - * and on 95, we signal Alt for left Alt only. */ - switch (shiftstate - & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { - case LEFT_ALT_PRESSED: - case LEFT_ALT_PRESSED | LEFT_CTRL_PRESSED: - return 1; - - case RIGHT_ALT_PRESSED: - case RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED: - return (GetVersion() & 0x80000000) == 0; - - default: - return 0; - } -} - -int __declspec(dllexport) __stdcall -ProcessKeystroke( - HANDLE hConIn, - INPUT_RECORD *ir, - boolean *valid, - boolean numberpad, - int portdebug) -{ - int keycode, vk; - unsigned char ch, pre_ch; - unsigned short int scan; - unsigned long shiftstate; - int altseq = 0; - const struct pad *kpad; - DWORD count; - -#ifdef QWERTZ_SUPPORT - if (numberpad & 0x10) { - numberpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - shiftstate = 0L; - ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - keycode = MapVirtualKey(vk, 2); - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - if (scan == 0 && vk == 0) { - /* It's the bogus_key */ - ReadConsoleInput(hConIn, ir, 1, &count); - *valid = FALSE; - return 0; - } - - if (is_altseq(shiftstate)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || (iskeypad(scan)) || (altseq > 0)) - *valid = TRUE; - /* if (!valid) return 0; */ - /* - * shiftstate can be checked to see if various special - * keys were pressed at the same time as the key. - * Currently we are using the ALT & SHIFT & CONTROLS. - * - * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, - * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, - * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, - * CAPSLOCK_ON, ENHANCED_KEY - * - * are all valid bit masks to use on shiftstate. - * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the - * left control key was pressed with the keystroke. - */ - if (iskeypad(scan)) { - ReadConsoleInput(hConIn, ir, 1, &count); - kpad = numberpad ? numpad : keypad; - if (shiftstate & SHIFT_PRESSED) { - ch = kpad[scan - KEYPADLO].shift; - } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) { - ch = kpad[scan - KEYPADLO].cntrl; - } else { - ch = kpad[scan - KEYPADLO].normal; - } -#ifdef QWERTZ_SUPPORT - /* OPTIONS=number_pad:-1 is for qwertz keyboard; for that setting, - 'numberpad' will be 0; core swaps y to zap, z to move northwest; - we want numpad 7 to move northwest, so when qwertz is set, - tell core that user who types numpad 7 typed z rather than y */ - if (qwertz && kpad[scan - KEYPADLO].normal == 'y') - ch += 1; /* changes y to z, Y to Z, ^Y to ^Z */ -#endif /*QWERTZ_SUPPORT*/ - } else if (altseq > 0) { /* ALT sequence */ - ReadConsoleInput(hConIn, ir, 1, &count); - if (vk == 0xBF) - ch = M('?'); - else - ch = M(tolower((uchar) keycode)); - } else if (ch < 32 && !isnumkeypad(scan)) { - /* Control code; ReadConsole seems to filter some of these, - * including ESC */ - ReadConsoleInput(hConIn, ir, 1, &count); - } - /* Attempt to work better with international keyboards. */ - else { - CHAR ch2; - DWORD written; - /* The bogus_key guarantees that ReadConsole will return, - * and does not itself do anything */ - WriteConsoleInput(hConIn, &bogus_key, 1, &written); - ReadConsole(hConIn, &ch2, 1, &count, NULL); - /* Prevent high characters from being interpreted as alt - * sequences; also filter the bogus_key */ - if (ch2 & 0x80) - *valid = FALSE; - else - ch = ch2; - if (ch == 0) - *valid = FALSE; - } - if (ch == '\r') - ch = '\n'; -#ifdef PORT_DEBUG - if (portdebug) { - char buf[BUFSZ]; - Sprintf(buf, "PORTDEBUG: ch=%u, scan=%u, vk=%d, pre=%d, " - "shiftstate=0x%lX (ESC to end)\n", - ch, scan, vk, pre_ch, shiftstate); - fprintf(stdout, "\n%s", buf); - } -#endif - return ch; -} - -int -process_keystroke2( - HANDLE hConIn, - INPUT_RECORD *ir, - boolean *valid) -{ - /* Use these values for the numeric keypad */ - static const char keypad_nums[] = "789-456+1230."; - - unsigned char ch; - int vk; - unsigned short int scan; - unsigned long shiftstate; - int altseq; - DWORD count; - - ch = ir->Event.KeyEvent.uChar.AsciiChar; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - scan = ir->Event.KeyEvent.wVirtualScanCode; - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - - if (scan == 0 && vk == 0) { - /* It's the bogus_key */ - ReadConsoleInput(hConIn, ir, 1, &count); - *valid = FALSE; - return 0; - } - - altseq = is_altseq(shiftstate); - if (ch || (iskeypad(scan)) || altseq) - *valid = TRUE; - /* if (!valid) return 0; */ - /* - * shiftstate can be checked to see if various special - * keys were pressed at the same time as the key. - * Currently we are using the ALT & SHIFT & CONTROLS. - * - * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED, - * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED, - * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON, - * CAPSLOCK_ON, ENHANCED_KEY - * - * are all valid bit masks to use on shiftstate. - * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the - * left control key was pressed with the keystroke. - */ - if (iskeypad(scan) && !altseq) { - ReadConsoleInput(hConIn, ir, 1, &count); - ch = keypad_nums[scan - KEYPADLO]; - } else if (ch < 32 && !isnumkeypad(scan)) { - /* Control code; ReadConsole seems to filter some of these, - * including ESC */ - ReadConsoleInput(hConIn, ir, 1, &count); - } - /* Attempt to work better with international keyboards. */ - else { - CHAR ch2; - ReadConsole(hConIn, &ch2, 1, &count, NULL); - ch = ch2 & 0xFF; - if (ch == 0) - *valid = FALSE; - } - if (ch == '\r') - ch = '\n'; - return ch; -} - -int __declspec(dllexport) __stdcall -CheckInput( - HANDLE hConIn, - INPUT_RECORD *ir, - DWORD *count, - boolean numpad, - int mode, - int *mod, - coord *cc) -{ -#if defined(SAFERHANGUP) - DWORD dwWait; -#endif - int ch = 0; - boolean valid = 0, done = 0; - -#ifdef QWERTZ_SUPPORT - if (numpad & 0x10) { - numpad &= ~0x10; - qwertz = TRUE; - } else { - qwertz = FALSE; - } -#endif - while (!done) { - *count = 0; - dwWait = WaitForSingleObject(hConIn, INFINITE); -#if defined(SAFERHANGUP) - if (dwWait == WAIT_FAILED) - return '\033'; -#endif - PeekConsoleInput(hConIn, ir, 1, count); - if (mode == 0) { - if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) { - ch = process_keystroke2(hConIn, ir, &valid); - done = valid; - } else - ReadConsoleInput(hConIn, ir, 1, count); - } else { - ch = 0; - if (count > 0) { - if (ir->EventType == KEY_EVENT - && ir->Event.KeyEvent.bKeyDown) { -#ifdef QWERTZ_SUPPORT - if (qwertz) - numpad |= 0x10; -#endif - ch = ProcessKeystroke(hConIn, ir, &valid, numpad, -#ifdef PORTDEBUG - 1); -#else - 0); -#endif -#ifdef QWERTZ_SUPPORT - numpad &= ~0x10; -#endif - if (valid) - return ch; - } else { - ReadConsoleInput(hConIn, ir, 1, count); - if (ir->EventType == MOUSE_EVENT) { - if ((ir->Event.MouseEvent.dwEventFlags == 0) - && (ir->Event.MouseEvent.dwButtonState - & MOUSEMASK)) { - cc->x = - ir->Event.MouseEvent.dwMousePosition.X + 1; - cc->y = - ir->Event.MouseEvent.dwMousePosition.Y - 1; - - if (ir->Event.MouseEvent.dwButtonState - & LEFTBUTTON) - *mod = CLICK_1; - else if (ir->Event.MouseEvent.dwButtonState - & RIGHTBUTTON) - *mod = CLICK_2; -#if 0 /* middle button */ - else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON) - *mod = CLICK_3; -#endif - return 0; - } - } -#if 0 - /* We ignore these types of console events */ - else if (ir->EventType == FOCUS_EVENT) { - } - else if (ir->EventType == MENU_EVENT) { - } -#endif - } - } else - done = 1; - } - } - *mod = 0; - return ch; -} - -int __declspec(dllexport) __stdcall NHkbhit( - HANDLE hConIn, - INPUT_RECORD *ir) -{ - int done = 0; /* true = "stop searching" */ - int retval; /* true = "we had a match" */ - DWORD count; - unsigned short int scan; - unsigned char ch; - unsigned long shiftstate; - int altseq = 0, keycode, vk; - - done = 0; - retval = 0; - while (!done) { - count = 0; - PeekConsoleInput(hConIn, ir, 1, &count); - if (count > 0) { - if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) { - ch = ir->Event.KeyEvent.uChar.AsciiChar; - scan = ir->Event.KeyEvent.wVirtualScanCode; - shiftstate = ir->Event.KeyEvent.dwControlKeyState; - vk = ir->Event.KeyEvent.wVirtualKeyCode; - if (scan == 0 && vk == 0) { - /* It's the bogus_key. Discard it */ - ReadConsoleInput(hConIn,ir,1,&count); - } else { - keycode = MapVirtualKey(vk, 2); - if (is_altseq(shiftstate)) { - if (ch || inmap(keycode, vk)) - altseq = 1; - else - altseq = -1; /* invalid altseq */ - } - if (ch || iskeypad(scan) || altseq) { - done = 1; /* Stop looking */ - retval = 1; /* Found what we sought */ - } else { - /* Strange Key event; let's purge it to avoid trouble */ - ReadConsoleInput(hConIn, ir, 1, &count); - } - } - - } else if ((ir->EventType == MOUSE_EVENT - && (ir->Event.MouseEvent.dwButtonState - & MOUSEMASK))) { - done = 1; - retval = 1; - } - - else /* Discard it, it's an insignificant event */ - ReadConsoleInput(hConIn, ir, 1, &count); - } else /* There are no events in console event queue */ { - done = 1; /* Stop looking */ - retval = 0; - } - } - return retval; -} - -int __declspec(dllexport) __stdcall -SourceWhere(char** buf) -{ - if (!buf) - return 0; - *buf = where_to_get_source; - return 1; -} - -int __declspec(dllexport) __stdcall -SourceAuthor(char** buf) -{ - if (!buf) - return 0; - *buf = author; - return 1; -} - -int __declspec(dllexport) __stdcall KeyHandlerName( - char **buf, - int full) -{ - if (!buf) - return 0; - if (full) - *buf = dllname; - else - *buf = shortdllname; - return 1; -} diff --git a/sys/windows/stubs.c b/sys/windows/stubs.c index 0830a7468..893d838a7 100644 --- a/sys/windows/stubs.c +++ b/sys/windows/stubs.c @@ -190,4 +190,14 @@ play_usersound_via_idx(int idx, int volume) } #endif /* USER_SOUNDS && TTY_SOUND_ESCCODES */ +void +set_altkeyhandling(const char *inName) +{ +} + +int +set_keyhandling_via_option(void) +{ + return 1; +} #endif /* TTYSTUBS */ diff --git a/sys/windows/vs/NetHack.sln b/sys/windows/vs/NetHack.sln index b2e237095..05267876a 100644 --- a/sys/windows/vs/NetHack.sln +++ b/sys/windows/vs/NetHack.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHackW", "NetHackW\NetHackW.vcxproj", "{CEC5D360-8804-454F-8591-002184C23499}" ProjectSection(ProjectDependencies) = postProject @@ -41,25 +41,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetHack", "NetHack\NetHack. ProjectSection(ProjectDependencies) = postProject {63F9B82B-F589-4082-ABE5-D4F0682050AB} = {63F9B82B-F589-4082-ABE5-D4F0682050AB} {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} - {6813477F-64B6-4B97-B230-438D0D233385} = {6813477F-64B6-4B97-B230-438D0D233385} {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} = {0303A585-3F83-4BB7-AF6B-1E12C8FB54AC} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhdefkey", "nhdefkey\nhdefkey.vcxproj", "{6813477F-64B6-4B97-B230-438D0D233385}" - ProjectSection(ProjectDependencies) = postProject - {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nh340key", "nh340key\nh340key.vcxproj", "{BE04E242-A1E9-4593-B95B-057F37330B76}" - ProjectSection(ProjectDependencies) = postProject - {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nhraykey", "nhraykey\nhraykey.vcxproj", "{2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}" - ProjectSection(ProjectDependencies) = postProject - {BA3DD34C-04B7-40D0-B373-9329AA9E8945} = {BA3DD34C-04B7-40D0-B373-9329AA9E8945} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDCurses", "PDCurses\PDCurses.vcxproj", "{BAA70D0F-3EC7-4D10-91F0-974F1F49308B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{477BF231-48E0-4312-AA12-9D8576215489}" @@ -141,30 +125,6 @@ Global {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|Win32.Build.0 = Release|Win32 {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.ActiveCfg = Release|x64 {609BC774-C6F8-4B2B-AA7D-5B3D0EA95751}.Release|x64.Build.0 = Release|x64 - {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.ActiveCfg = Debug|Win32 - {6813477F-64B6-4B97-B230-438D0D233385}.Debug|Win32.Build.0 = Debug|Win32 - {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.ActiveCfg = Debug|x64 - {6813477F-64B6-4B97-B230-438D0D233385}.Debug|x64.Build.0 = Debug|x64 - {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.ActiveCfg = Release|Win32 - {6813477F-64B6-4B97-B230-438D0D233385}.Release|Win32.Build.0 = Release|Win32 - {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.ActiveCfg = Release|x64 - {6813477F-64B6-4B97-B230-438D0D233385}.Release|x64.Build.0 = Release|x64 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.ActiveCfg = Debug|Win32 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|Win32.Build.0 = Debug|Win32 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.ActiveCfg = Debug|x64 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Debug|x64.Build.0 = Debug|x64 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.ActiveCfg = Release|Win32 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|Win32.Build.0 = Release|Win32 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.ActiveCfg = Release|x64 - {BE04E242-A1E9-4593-B95B-057F37330B76}.Release|x64.Build.0 = Release|x64 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.ActiveCfg = Debug|Win32 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|Win32.Build.0 = Debug|Win32 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.ActiveCfg = Debug|x64 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Debug|x64.Build.0 = Debug|x64 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.ActiveCfg = Release|Win32 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|Win32.Build.0 = Release|Win32 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.ActiveCfg = Release|x64 - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2}.Release|x64.Build.0 = Release|x64 {BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|Win32.ActiveCfg = Debug|Win32 {BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|Win32.Build.0 = Debug|Win32 {BAA70D0F-3EC7-4D10-91F0-974F1F49308B}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/sys/windows/vs/nh340key/nh340key.def b/sys/windows/vs/nh340key/nh340key.def deleted file mode 100644 index f484a536f..000000000 --- a/sys/windows/vs/nh340key/nh340key.def +++ /dev/null @@ -1,8 +0,0 @@ -LIBRARY nh340key -EXPORTS -ProcessKeystroke -NHkbhit -CheckInput -SourceWhere -SourceAuthor -KeyHandlerName diff --git a/sys/windows/vs/nh340key/nh340key.vcxproj b/sys/windows/vs/nh340key/nh340key.vcxproj deleted file mode 100644 index 663cefd3a..000000000 --- a/sys/windows/vs/nh340key/nh340key.vcxproj +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - {BE04E242-A1E9-4593-B95B-057F37330B76} - Win32Proj - nh340key - - - - - - - - - - - - - - - - - - - - - $(BinDir) - - - - $(IncDir);$(SysWindDir);$(LuaDir);%(AdditionalIncludeDirectories) - - - $(ToolsDir)$(TargetName).lib - - - - - nh340key.def - - - - - - - - - - - - - diff --git a/sys/windows/vs/nhdefkey/nhdefkey.def b/sys/windows/vs/nhdefkey/nhdefkey.def deleted file mode 100644 index 2950904e4..000000000 --- a/sys/windows/vs/nhdefkey/nhdefkey.def +++ /dev/null @@ -1,8 +0,0 @@ -LIBRARY nhdefkey -EXPORTS -ProcessKeystroke -NHkbhit -CheckInput -SourceWhere -SourceAuthor -KeyHandlerName diff --git a/sys/windows/vs/nhdefkey/nhdefkey.vcxproj b/sys/windows/vs/nhdefkey/nhdefkey.vcxproj deleted file mode 100644 index 4af518c60..000000000 --- a/sys/windows/vs/nhdefkey/nhdefkey.vcxproj +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - {6813477F-64B6-4B97-B230-438D0D233385} - Win32Proj - nhdefkey - - - - - - - - - - - - - - - - - - - - - $(BinDir) - - - - $(IncDir);$(SysWindDir);$(LuaDir);%(AdditionalIncludeDirectories) - - - $(ToolsDir)$(TargetName).lib - - - - - nhdefkey.def - - - - - - - - - - - - - diff --git a/sys/windows/vs/nhraykey/nhraykey.def b/sys/windows/vs/nhraykey/nhraykey.def deleted file mode 100644 index 5432a1af3..000000000 --- a/sys/windows/vs/nhraykey/nhraykey.def +++ /dev/null @@ -1,8 +0,0 @@ -LIBRARY nhraykey -EXPORTS -ProcessKeystroke -NHkbhit -CheckInput -SourceWhere -SourceAuthor -KeyHandlerName diff --git a/sys/windows/vs/nhraykey/nhraykey.vcxproj b/sys/windows/vs/nhraykey/nhraykey.vcxproj deleted file mode 100644 index 788fb490a..000000000 --- a/sys/windows/vs/nhraykey/nhraykey.vcxproj +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - {2E1F4BB3-3BD7-43AD-8E64-D3B8A2F5D7B2} - Win32Proj - nhraykey - - - - - - - - - - - - - - - - - - - - - $(BinDir) - - - - $(IncDir);$(SysWindDir);$(LuaDir);%(AdditionalIncludeDirectories) - - - $(ToolsDir)$(TargetName).lib - - - - - nhraykey.def - - - - - - - - - - - - -