#include <stdlib.h>
#include <conio.h>
#include <signal.h>
#include <dos.h>
#include <bios.h>

#define KEYINT	9
static unsigned char	cbuff[40];
static int		extended_code;
static unsigned char	*sp, *ep;
extern unsigned long PCMap[];

main()
{
	void (interrupt far *old)();
	void interrupt far foo();
	int keyup, keycode, key;
	int breakit = 1;

	sp = ep = cbuff;
	extended_code = 0;

	_disable();
	old = _dos_getvect(KEYINT);
	_dos_setvect(KEYINT, foo);
	_enable();

	do {
		while (ep > sp) {
			if (0xf0 == (*sp & 0xf0)) {
				sp++;
				continue;
			}
			if (0xe0 == (*sp & 0xfe)) {
				extended_code = 1;
				sp++;
				continue;
			}
			keyup = *sp & 0x80 ? 1 : 0;
			keycode = (*sp++ & 0x7f);
			if (extended_code) {
				if (keycode >= 0x45)
					keycode += 0x22;
				else if (keycode >= 0x35)
					keycode += 0x2e;
				else if (keycode == 0x2a)
					keycode += 0x38;
				else
					keycode += 0x44;
			}
			key = (unsigned int)PCMap[2 * (keycode - 1)];
			printf("key = %x, code = 0x%x, extended = %d, keyup = %d\n",
				key, keycode, extended_code, keyup);
			extended_code = 0;
			if (0x1b == (key & 0x7f)) {
				breakit = 0;
				break;
			}
		}
	} while (breakit);

	_disable();
	_dos_setvect(KEYINT, old);
	_enable();
}

#pragma check_stack(off)
void interrupt far
foo()
{
	void	kbd_disable();
	void	kbd_enable();

	_enable();
	if (ep == sp)
		ep = sp = cbuff;
	*ep++ = inp(0x60);
	outp(0x20, 0x20);
}

void
kbd_control(command)
int	command;
{

	_disable();
	while (inp(0x64) & 2)
		;
	outp(0x64, command);
	_enable();
}

void
kbd_disable()
{

	kbd_control(0xad);
}

void
kbd_enable()
{

	kbd_control(0xae);
}
