// ==============================================================
//                ORBITER MODULE: ASCENSIONULTRA
//                  Part of Ascension Ultra
//          Copyright (C) 2010 Friedrich Kastner-Masilko
//                   All rights reserved
//
// KeyboardFilter.cpp
// Class implementation of keyboard filter.
// ==============================================================
#include <windows.h>
#include "KeyboardFilter.h"
#include <stdio.h>

LRESULT CALLBACK Intercept(int nCode, WPARAM wParam, LPARAM lParam)
{
	KeyboardFilter filter=*KeyboardFilter::Current;
	if (nCode < 0) return CallNextHookEx(filter.GetHook(), nCode, wParam, lParam);
	filter.Preprocess(wParam, lParam);
	filter.Process(wParam, (lParam & 0x80000000)==0);
	return CallNextHookEx(filter.GetHook(), nCode, wParam, lParam);
}

KeyboardFilter::KeyboardFilter(void *obj, int (*consumeDirectKey)(void*, char*), void (*prefilter)(void*, WPARAM &wparam, LPARAM &lparam))
{
	//Install keyboard hook
	if (Current==NULL)
	{
		Current=this;
		ConsumeDirectKey=consumeDirectKey;
		Prefilter=prefilter;
		object=obj;
		kstate=new char[256];
		for(int i=0;i<256;i++) kstate[i]=(char)0x00;
		hhook=SetWindowsHookEx(WH_KEYBOARD, Intercept, NULL, GetCurrentThreadId());
	}
}

KeyboardFilter::~KeyboardFilter(void)
{
	if (Current==this)
	{
		UnhookWindowsHookEx(hhook);
		delete [] kstate;
		ConsumeDirectKey=NULL;
		Prefilter=NULL;
		Current=NULL;
	}
}

void KeyboardFilter::Preprocess(WPARAM &wparam, LPARAM &lparam)
{
	if (Prefilter!=NULL)
	{
		Prefilter(object, wparam, lparam);
	}
}

int KeyboardFilter::Process(short key, bool down)
{
	bool edge=(kstate[VK2OAPI[key]] & 0x80)>0;
	if (down) kstate[VK2OAPI[key]]=0x80;
	else kstate[VK2OAPI[key]]=0x00;
	return down ^ edge?ConsumeDirectKey(object, kstate):0;
}

KeyboardFilter *KeyboardFilter::Current=NULL;

HHOOK KeyboardFilter::GetHook(){return hhook;}

//Convert OAPI key identifier to virtual key code
const short KeyboardFilter::OAPI2VK[256]=
{
	0x00,//---							0x00
	0x1b,//#define OAPI_KEY_ESCAPE		0x01
	0x31,//#define OAPI_KEY_1			0x02
	0x32,//#define OAPI_KEY_2			0x03		
	0x33,//#define OAPI_KEY_3			0x04
	0x34,//#define OAPI_KEY_4			0x05
	0x35,//#define OAPI_KEY_5			0x06
	0x36,//#define OAPI_KEY_6			0x07
	0x37,//#define OAPI_KEY_7			0x08
	0x38,//#define OAPI_KEY_8			0x09
	0x39,//#define OAPI_KEY_9			0x0A
	0x30,//#define OAPI_KEY_0			0x0B
	0xBD,//#define OAPI_KEY_MINUS		0x0C  // on main keyboard
	0x00,//#define OAPI_KEY_EQUALS		0x0D
	0x08,//#define OAPI_KEY_BACK		0x0E  // backspace
	0x09,//#define OAPI_KEY_TAB			0x0F
	0x51,//#define OAPI_KEY_Q			0x10
	0x57,//#define OAPI_KEY_W			0x11
	0x45,//#define OAPI_KEY_E			0x12
	0x52,//#define OAPI_KEY_R			0x13
	0x54,//#define OAPI_KEY_T			0x14
	0x59,//#define OAPI_KEY_Y			0x15
	0x55,//#define OAPI_KEY_U			0x16
	0x49,//#define OAPI_KEY_I			0x17
	0x4F,//#define OAPI_KEY_O			0x18
	0x50,//#define OAPI_KEY_P			0x19
	0xDB,//#define OAPI_KEY_LBRACKET	0x1A
	0xDD,//#define OAPI_KEY_RBRACKET	0x1B
	0x0D,//#define OAPI_KEY_RETURN		0x1C  // Enter on main keyboard
	0xA2,//#define OAPI_KEY_LCONTROL	0x1D
	0x41,//#define OAPI_KEY_A			0x1E
	0x53,//#define OAPI_KEY_S			0x1F
	0x44,//#define OAPI_KEY_D			0x20
	0x46,//#define OAPI_KEY_F			0x21
	0x47,//#define OAPI_KEY_G			0x22
	0x48,//#define OAPI_KEY_H			0x23
	0x4A,//#define OAPI_KEY_J			0x24
	0x4B,//#define OAPI_KEY_K			0x25
	0x4C,//#define OAPI_KEY_L			0x26
	0xBA,//#define OAPI_KEY_SEMICOLON	0x27
	0xDE,//#define OAPI_KEY_APOSTROPHE	0x28
	0xC0,//#define OAPI_KEY_GRAVE		0x29  // accent grave
	0xA0,//#define OAPI_KEY_LSHIFT		0x2A
	0xDC,//#define OAPI_KEY_BACKSLASH	0x2B
	0x5A,//#define OAPI_KEY_Z			0x2C
	0x58,//#define OAPI_KEY_X			0x2D
	0x43,//#define OAPI_KEY_C			0x2E
	0x56,//#define OAPI_KEY_V			0x2F
	0x42,//#define OAPI_KEY_B			0x30
	0x4E,//#define OAPI_KEY_N			0x31
	0x4D,//#define OAPI_KEY_M			0x32
	0xBC,//#define OAPI_KEY_COMMA		0x33
	0xBE,//#define OAPI_KEY_PERIOD		0x34  // . on main keyboard
	0xBF,//#define OAPI_KEY_SLASH		0x35  // / on main keyboard
	0xA1,//#define OAPI_KEY_RSHIFT		0x36
	0x6A,//#define OAPI_KEY_MULTIPLY	0x37  // * on numeric keypad
	0xA4,//#define OAPI_KEY_LALT		0x38  // left Alt
	0x20,//#define OAPI_KEY_SPACE		0x39
	0x14,//#define OAPI_KEY_CAPITAL		0x3A  // caps lock key
	0x70,//#define OAPI_KEY_F1			0x3B
	0x71,//#define OAPI_KEY_F2			0x3C
	0x72,//#define OAPI_KEY_F3			0x3D
	0x73,//#define OAPI_KEY_F4			0x3E
	0x74,//#define OAPI_KEY_F5			0x3F
	0x75,//#define OAPI_KEY_F6			0x40
	0x76,//#define OAPI_KEY_F7			0x41
	0x77,//#define OAPI_KEY_F8			0x42
	0x78,//#define OAPI_KEY_F9			0x43
	0x79,//#define OAPI_KEY_F10			0x44
	0x90,//#define OAPI_KEY_NUMLOCK		0x45
	0x91,//#define OAPI_KEY_SCROLL		0x46  // Scroll lock
	0x67,//#define OAPI_KEY_NUMPAD7		0x47
	0x68,//#define OAPI_KEY_NUMPAD8		0x48
	0x69,//#define OAPI_KEY_NUMPAD9		0x49
	0x6D,//#define OAPI_KEY_SUBTRACT	0x4A  // - on numeric keypad
	0x64,//#define OAPI_KEY_NUMPAD4		0x4B
	0x65,//#define OAPI_KEY_NUMPAD5		0x4C
	0x66,//#define OAPI_KEY_NUMPAD6		0x4D
	0x6B,//#define OAPI_KEY_ADD			0x4E  // + on numeric keypad
	0x61,//#define OAPI_KEY_NUMPAD1		0x4F
	0x62,//#define OAPI_KEY_NUMPAD2		0x50
	0x63,//#define OAPI_KEY_NUMPAD3		0x51
	0x60,//#define OAPI_KEY_NUMPAD0		0x52
	0x6E,//#define OAPI_KEY_DECIMAL		0x53  // . on numeric keypad
	0x00,//---							0x54
	0x00,//---							0x55
	0xE2,//#define OAPI_KEY_OEM_102		0x56  // | < > on UK/German keyboards
	0x7A,//#define OAPI_KEY_F11			0x57
	0x7B,//#define OAPI_KEY_F12			0x58
	0x00,//---							0x59
	0x00,//---							0x5A
	0x00,//---							0x5B
	0x00, 0x00, 0x00, 0x00,							//5C,5D,5E,5F
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//60,61,62,63,64,65,66,67
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//68,69,6A,6B,6C,6D,6E,6F
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//70,71,72,73,74,75,76,77
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//78,79,7A,7B,7C,7D,7E,7F
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//80,81,82,83,84,85,86,87
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//88,89,8A,8B,8C,8D,8E,8F
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//90,91,92,93,94,95,96,97
	0x00, 0x00, 0x00, 0x00,							//98,99,9A,9B
	0x6C,//#define OAPI_KEY_NUMPADENTER	0x9C  // Enter on numeric keypad
	0xA3,//#define OAPI_KEY_RCONTROL	0x9D  // right Control key
	0x00,//---							0x9E
	0x00,//---							0x9F
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//A0,A1,A2,A3,A4,A5,A6,A7
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//A8,A9,AA,AB,AC,AD,AE,AF
	0x00, 0x00, 0x00, 0x00,							//B0,B1,B2,B3
	0x00,//---							0xB4
	0x6F,//#define OAPI_KEY_DIVIDE		0xB5  // / on numeric keypad
	0x00,//---							0xB6
	0x00,//---							0xB7
	0xA5,//#define OAPI_KEY_RALT        0xB8  // right Alt
	0x00,//---							0xB9
	0x00,//---							0xBA
	0x00,//---							0xBB
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	//BC,BD,BE,BF,C0,C1,C2,C3
	0x00,//---							0xC4
	0x00,//---							0xC5
	0x00,//---							0xC6		
	0x24,//#define OAPI_KEY_HOME        0xC7  // Home on cursor keypad
	0x26,//#define OAPI_KEY_UP          0xC8  // up-arrow on cursor keypad
	0x21,//#define OAPI_KEY_PRIOR       0xC9  // PgUp on cursor keypad
	0x00,//---							0xCA
	0x25,//#define OAPI_KEY_LEFT        0xCB  // left-arrow on cursor keypad
	0x00,//---							0xCC
	0x27,//#define OAPI_KEY_RIGHT       0xCD  // right-arrow on cursor keypad
	0x00,//---							0xCE
	0x23,//#define OAPI_KEY_END         0xCF  // End on cursor keypad
	0x28,//#define OAPI_KEY_DOWN        0xD0  // down-arrow on cursor keypad
	0x22,//#define OAPI_KEY_NEXT        0xD1  // PgDn on cursor keypad
	0x2D,//#define OAPI_KEY_INSERT      0xD2  // Insert on cursor keypad
	0x2E //#define OAPI_KEY_DELETE      0xD3  // Delete on cursor keypad
};

const short KeyboardFilter::VK2OAPI[256]=
{
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x0E,	0x0F,	0x00,	0x00,	0x00,	0x1C,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x3A,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x01,	0x00,	0x00,	0x00,	0x00,
	0x39,	0xC9,	0xD1,	0xCF,	0xC7,	0xCB,	0xC8,	0xCD,
	0xD0,	0x00,	0x00,	0x00,	0x00,	0xD2,	0xD3,	0x00,
	0x0B,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,	0x08,
	0x09,	0x0A,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x1E,	0x30,	0x2E,	0x20,	0x12,	0x21,	0x22,
	0x23,	0x17,	0x24,	0x25,	0x26,	0x32,	0x31,	0x18,
	0x19,	0x10,	0x13,	0x1F,	0x14,	0x16,	0x2F,	0x11,
	0x2D,	0x15,	0x2C,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x52,	0x4F,	0x50,	0x51,	0x4B,	0x4C,	0x4D,	0x47,
	0x48,	0x49,	0x37,	0x4E,	0x9C,	0x4A,	0x53,	0xB5,
	0x3B,	0x3C,	0x3D,	0x3E,	0x3F,	0x40,	0x41,	0x42,
	0x43,	0x44,	0x57,	0x58,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x45,	0x46,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x2A,	0x36,	0x1D,	0x9D,	0x38,	0xB8,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x27,	0x00,	0x33,	0x0C,	0x34,	0x35,
	0x29,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
	0x00,	0x00,	0x00,	0x1A,	0x2B,	0x1B,	0x28,	0x00,
	0x00,	0x00,	0x56
};
