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
-
-
-
-
-
-
-
-
-
-
-
-
-