win32tty: dynamic keystroke handler with 3.4.0 behaviour
This commit is contained in:
6
Files
6
Files
@@ -190,9 +190,9 @@ winmain.c
|
||||
sys/winnt:
|
||||
(files for Windows 9x, NT and Windows2000 version)
|
||||
Install.nt Makefile.bcc Makefile.gcc Makefile.msc console.rc
|
||||
defaults.nh mapimail.c nethack.def nhdefkey.c nhico.uu
|
||||
nhsetup.bat ntsound.c nttty.c porthelp win32api.h
|
||||
winnt.c
|
||||
defaults.nh mapimail.c nethack.def nhdefkey.c nh340key.c
|
||||
nhico.uu nhsetup.bat ntsound.c nttty.c porthelp
|
||||
win32api.h winnt.c
|
||||
|
||||
util:
|
||||
(files for all versions)
|
||||
|
||||
@@ -572,7 +572,7 @@ $(NHRES): $(NTSYS)\console.rc $(NTSYS)\NetHack.ico
|
||||
# DO NOT INDENT THE << below!
|
||||
#
|
||||
|
||||
$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(GAMEDIR)\nhdefkey.dll
|
||||
$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(GAMEDIR)\nhdefkey.dll $(GAMEDIR)\nh340key.dll
|
||||
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
|
||||
@echo Linking....
|
||||
$(link) $(LFLAGS) user32.lib winmm.lib -out:$@ @<<$(GAME).lnk
|
||||
@@ -597,6 +597,21 @@ $(GAMEDIR)\nhdefkey.dll : $(O)$(@B).o $(O)$(@B).def
|
||||
/PDB:"$(@B).PDB" /MAP:"$(@B).map" /DEF:$(O)$(@B).def \
|
||||
-out:$@ $(O)$(@B).o
|
||||
|
||||
$(O)nh340key.def:
|
||||
@echo EXPORTS >$@
|
||||
@echo ProcessKeystroke >>$@
|
||||
@echo NHkbhit >>$@
|
||||
@echo SourceWhere >>$@
|
||||
@echo SourceAuthor >>$@
|
||||
@echo KeyHandlerName >>$@
|
||||
|
||||
$(GAMEDIR)\nh340key.dll : $(O)$(@B).o $(O)$(@B).def
|
||||
@if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR)
|
||||
@echo Linking $@
|
||||
$(link) -debug:full -debugtype:cv /RELEASE /NOLOGO /DLL user32.lib \
|
||||
/PDB:"$(@B).PDB" /MAP:"$(@B).map" /DEF:$(O)$(@B).def \
|
||||
-out:$@ $(O)$(@B).o
|
||||
|
||||
#
|
||||
# Secondary Targets.
|
||||
#
|
||||
|
||||
241
sys/winnt/nh340key.c
Normal file
241
sys/winnt/nh340key.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/* SCCS Id: @(#)nh340key.c 3.4 $Date$ */
|
||||
/* 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 "hack.h"
|
||||
#include "wintty.h"
|
||||
#include "win32api.h"
|
||||
|
||||
extern HANDLE hConIn;
|
||||
extern INPUT_RECORD ir;
|
||||
char dllname[512];
|
||||
char *shortdllname;
|
||||
|
||||
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)
|
||||
|
||||
/*
|
||||
* 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(ir, valid, numberpad, portdebug)
|
||||
INPUT_RECORD *ir;
|
||||
boolean *valid;
|
||||
boolean numberpad;
|
||||
int portdebug;
|
||||
{
|
||||
int metaflags = 0, k = 0;
|
||||
int keycode, vk;
|
||||
unsigned char ch, pre_ch, mk = 0;
|
||||
unsigned short int scan;
|
||||
unsigned long shiftstate;
|
||||
int altseq = 0;
|
||||
const struct pad *kpad;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (altseq > 0) { /* ALT sequence */
|
||||
if (vk == 0xBF) ch = M('?');
|
||||
else ch = M(tolower(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%X (ESC to end)",
|
||||
shortdllname, ch, scan, vk, shiftstate);
|
||||
fprintf(stdout, "\n%s", buf);
|
||||
}
|
||||
#endif
|
||||
return ch;
|
||||
}
|
||||
|
||||
int __declspec(dllexport) __stdcall
|
||||
NHkbhit(hConIn, ir)
|
||||
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 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(buf)
|
||||
char **buf;
|
||||
{
|
||||
if (!buf) return 0;
|
||||
*buf = where_to_get_source;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __declspec(dllexport) __stdcall
|
||||
SourceAuthor(buf)
|
||||
char **buf;
|
||||
{
|
||||
if (!buf) return 0;
|
||||
*buf = author;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __declspec(dllexport) __stdcall
|
||||
KeyHandlerName(buf, full)
|
||||
char **buf;
|
||||
int full;
|
||||
{
|
||||
if (!buf) return 0;
|
||||
if (full) *buf = dllname;
|
||||
else *buf = shortdllname;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user