/*
 *  psychlops_io_API_OSX.cpp
 *  Psychlops Standard Library (MacOSX)
 *
 *  Last Modified 2006/01/04 by Kenchi HOSOKAWA
 *  (C) 2005 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */


#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
#include <CoreServices/CoreServices.h>
//#include <CoreFoundation/CoreFoundation.h>


#include "psychlops_io_API_OSX.h"
#include "../../core/devices/psychlops_io_hid.h"


namespace Psychlops {

	typedef HumanInterfaceDevice HID;

	MPTaskID APIHIDProperties::inputListnerTask, APIHIDProperties::inputListnerTask2;
	bool APIHIDProperties::refresh_needed = false;

	void APIHIDProperties::initialize() {
		bindKeyCode();
	}
	void APIHIDProperties::finalize() {
	}
	bool APIHIDProperties::get(Mouse::Button button, Mouse::ButtonState state) {
		bool val = HID::state[state].button[button.code];
		if(state!=Mouse::pressed) HID::state[state].button[button.code] = false;
		return val;
	}
	void APIHIDProperties::setPointerPosition(int x, int y) {
		CGPoint p;
		p.x = x;
		p.y = y;
		CGWarpMouseCursorPosition(p);
	}

#if (defined(PANTHER) && ( PANTHER==1 )) || defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
	const int KEYMAP_ARRAY_LENGTH = 4;
	void APIHIDProperties::updateKeyboard() {
		KeyMap tmpkeys;
		for(int i=0;i<KEYMAP_ARRAY_LENGTH;i++) {
			key[HID::hadpressed][i] = key[HID::pressed][i];
		}
		GetKeys(tmpkeys);
#if (__LITTLE_ENDIAN__)
		for(int i=0; i<4; i++) key[HID::pressed][i] = CFSwapInt32BigToHost( tmpkeys[i].bigEndianValue );
#else
		for(int i=0; i<4; i++) key[HID::pressed][i] = tmpkeys[i];
#endif
		for(int i=0;i<KEYMAP_ARRAY_LENGTH;i++) {
			key[HID::pushed][i] = (key[HID::pressed][i] ^ key[HID::hadpressed][i]) & key[HID::pressed][i] | key[HID::pushed][i];
			key[HID::released][i] = (key[HID::pressed][i] ^ key[HID::hadpressed][i]) & (~key[HID::pressed][i]) | key[HID::released][i];
		}
	}
	void APIHIDProperties::updateMouse() {
		bool state = Button();
		HID::state[HID::hadpressed].button[Mouse::left.code] = HID::state[HID::pressed].button[Mouse::left.code];		
		HID::state[HID::pressed].button[Mouse::left.code] = state;
		HID::state[HID::pushed].button[Mouse::left.code] = (HID::state[HID::pressed].button[Mouse::left.code] != HID::state[HID::hadpressed].button[Mouse::left.code]) & HID::state[HID::pressed].button[Mouse::left.code] | HID::state[HID::pushed].button[Mouse::left.code];
		HID::state[HID::released].button[Mouse::left.code] = (HID::state[HID::pressed].button[Mouse::left.code] != HID::state[HID::hadpressed].button[Mouse::left.code]) & !HID::state[HID::pressed].button[Mouse::left.code] | HID::state[HID::released].button[Mouse::left.code];
		::Point point;
		GetMouse(&point);
		Mouse::uniX.val_ = point.h;
		Mouse::uniY.val_ = point.v;
	}
	
	//	UInt32 APIKeyboardProperties::TMP_KEY_STATUS = 0;
	UInt32 APIHIDProperties::key[KEYMAP_ARRAY_LENGTH][4];
	unsigned long APIHIDProperties::keybinder[128][2];

	void APIHIDProperties::refresh() {
		for(int i=0;i<KEYMAP_ARRAY_LENGTH;i++) {
			key[HID::pushed][i] = 0;
			key[HID::released][i] = 0;
		}
		refresh_needed = false;
	}		
	
#endif

#if defined(PANTHER) && ( PANTHER==1 )
//  Loop Based Keyboard-Accept Code (10.3)
	void APIHIDProperties::startListener() {
		MPCreateTask((TaskProc)&lisnerProcedure, NULL, 4096, NULL, NULL, NULL, 0, &inputListnerTask);
		MPSetTaskWeight(inputListnerTask,1);
	}
	void APIHIDProperties::stopListener() {
		OSStatus terminationStatus = 1000;
		MPTerminateTask(inputListnerTask, terminationStatus);
	}
	void APIHIDProperties::lisnerProcedure(){
		MPSemaphoreID delay;
		MPCreateSemaphore(0, 0, &delay);
		for(;;) {
			update();
			(void) MPWaitOnSemaphore(delay, kDurationMicrosecond*100);
		}
	}

	bool APIHIDProperties::get(Keyboard::Key key_, Keyboard::KeyState state) {
		if(refresh_needed) { refresh(); }
		int returnvalue;
		returnvalue = key[state][keybinder[key_.code][BIG]] & keybinder[key_.code][SMALL];
		/*if(state!=pressed) {
		 key[state][keybinder[code][BIG]] = key[state][keybinder[code][BIG]] & (!keybinder[code][SMALL]);
		 }*/
		if(returnvalue!=0 && state!=Keyboard::pressed) {
			key[state][keybinder[key_.code][BIG]] -= (keybinder[key_.code][SMALL]);
		}
		if(returnvalue==0) { return false; }
		else { return true; }
	}	
	void APIHIDProperties::update() {
		updateKeyboard();
		updateMouse();
	}
#else
	
#if defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
	void APIHIDProperties::lisnerProcedure(){
		MPSemaphoreID delay;
		MPCreateSemaphore(0, 0, &delay);
		for(;;) {
			updateKeyboard();
			(void) MPWaitOnSemaphore(delay, kDurationMicrosecond*1000);
		}
	}
	bool APIHIDProperties::get(Keyboard::Key key_, Keyboard::KeyState state) {
		if(refresh_needed) { refresh(); }
		int returnvalue;
		returnvalue = key[state][keybinder[key_.code][BIG]] & keybinder[key_.code][SMALL];
		if(returnvalue!=0 && state!=Keyboard::pressed) key[state][keybinder[key_.code][BIG]] -= (keybinder[key_.code][SMALL]);
		return returnvalue==0 ? false : true;
	}
#else
//  Event Based Keyboard-Accept Code (10.4)
	bool APIHIDProperties::get(Keyboard::Key key_, Keyboard::KeyState state) {
		bool val = HID::state[(HID::ButtonState)state].key[keybinder[key_.code]];
		if(state!=Keyboard::pressed) HID::state[(HID::ButtonState)state].key[keybinder[key_.code]] = false;
		return val;
	}
#endif

	void APIHIDProperties::update() {
	}

	void APIHIDProperties::startListener() {
		MPCreateTask((TaskProc)&loopListener, NULL, 4096, NULL, NULL, NULL, 0, &inputListnerTask);
		MPSetTaskWeight(inputListnerTask,1);
#if defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
		MPCreateTask((TaskProc)&lisnerProcedure, NULL, 4096, NULL, NULL, NULL, 0, &inputListnerTask);
		MPSetTaskWeight(inputListnerTask2,1);
#endif
	}
	void APIHIDProperties::stopListener() {
		OSStatus terminationStatus = 1000;
		MPTerminateTask(inputListnerTask, terminationStatus);
#if !defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
		CFRelease(listenerKey);
#else
		MPTerminateTask(inputListnerTask2, terminationStatus);
#endif
		CFRelease(listenerMouse);
	}
	void APIHIDProperties::loopListener() {
#if !defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
		CGEventMask keyMask   = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged);
		//ProcessSerialNumber psn;
		//GetCurrentProcess(&psn);
		//CFMachPortRef tapKey   = CGEventTapCreateForPSN(&psn, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, keyMask, &listenToKeyboard, NULL);
		CFMachPortRef tapKey   = CGEventTapCreate(/*kCGAnnotatedSessionEventTap*/kCGHIDEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, keyMask, &listenToKeyboard, NULL);
		listenerKey = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tapKey, 0);
		CFRunLoopAddSource(CFRunLoopGetCurrent(), listenerKey, kCFRunLoopCommonModes);
#endif
		CGEventMask mouseMask =
		CGEventMaskBit(kCGEventLeftMouseDown)  | CGEventMaskBit(kCGEventLeftMouseUp) | CGEventMaskBit(kCGEventLeftMouseDragged)
		| CGEventMaskBit(kCGEventRightMouseDown)   | CGEventMaskBit(kCGEventRightMouseUp) | CGEventMaskBit(kCGEventRightMouseDragged)
		| CGEventMaskBit(kCGEventOtherMouseDown) | CGEventMaskBit(kCGEventOtherMouseUp) | CGEventMaskBit(kCGEventOtherMouseDragged)
		| CGEventMaskBit(kCGEventMouseMoved)     | CGEventMaskBit(kCGEventScrollWheel);
		//CFMachPortRef tapMouse = CGEventTapCreateForPSN(&psn, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, mouseMask, &listenToMouse, NULL);
		CFMachPortRef tapMouse = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGTailAppendEventTap, kCGEventTapOptionListenOnly, mouseMask, &listenToMouse, NULL);
		listenerMouse = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tapMouse, 0);
		CFRunLoopAddSource(CFRunLoopGetCurrent(), listenerMouse, kCFRunLoopCommonModes);

		CFRunLoopRun();
	}
	CGEventRef APIHIDProperties::listenToKeyboard(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
#if !defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
		CGEventFlags flags = CGEventGetFlags(event);
		CGPoint point = CGEventGetLocation(event);
		CGEventTimestamp time_stamp = CGEventGetTimestamp(event);
		int64_t key_code = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
		bool tmp_mod;

		switch (type) {
			case kCGEventKeyDown:
				HID::state[HID::pressed].key[key_code] = true;
				HID::state[HID::pushed].key[key_code] = true | HID::state[HID::pushed].key[key_code];
				break;
			case kCGEventKeyUp:
				HID::state[HID::pressed].key[key_code] = true;
				HID::state[HID::released].key[key_code] = true | HID::state[HID::released].key[key_code];
				break;
			case kCGEventFlagsChanged:
				const CGEventFlags flags = CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState);
				tmp_mod = HID::state[HID::pressed].key[keybinder[Keyboard::shift.code]];
				HID::state[HID::pressed].key[keybinder[Keyboard::shift.code]] = ((flags&kCGEventFlagMaskShift)!=0);
				if((flags&kCGEventFlagMaskShift)!=0) HID::state[HID::pushed].key[keybinder[Keyboard::shift.code]] = true | HID::state[HID::pushed].key[keybinder[Keyboard::shift.code]];
				HID::state[HID::pressed].key[keybinder[Keyboard::ctrl.code]]  = ((flags&kCGEventFlagMaskControl)!=0);
				if((flags&kCGEventFlagMaskControl)!=0) HID::state[HID::pushed].key[keybinder[Keyboard::ctrl.code]] = true | HID::state[HID::pushed].key[keybinder[Keyboard::ctrl.code]];
				HID::state[HID::pressed].key[keybinder[Keyboard::alt.code]]   = ((flags&kCGEventFlagMaskAlternate)!=0);
				if((flags&kCGEventFlagMaskAlternate)!=0) HID::state[HID::pushed].key[keybinder[Keyboard::alt.code]] = true | HID::state[HID::pushed].key[keybinder[Keyboard::alt.code]];
				break;
		}
#endif
		if(refresh_needed) {
			Keyboard::refresh_internal();
			Mouse::refresh_internal();
			refresh_needed = false;
		}
		return NULL;
	}
	CGEventRef APIHIDProperties::listenToMouse(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
		CGEventFlags flags = CGEventGetFlags(event);
		CGPoint point = CGEventGetLocation(event);
		CGEventTimestamp time_stamp = CGEventGetTimestamp(event);
		//Mouse::lastPoint.x = point.x; Mouse::lastPoint.y = point.y;
		Mouse::uniX.val_ = point.x;
		Mouse::uniY.val_ = point.y;
		if(type==kCGEventMouseMoved) return NULL;
		if(type==kCGEventScrollWheel) {
			Mouse::wheelDelta.y -= CGEventGetIntegerValueField(event, kCGScrollWheelEventDeltaAxis1);
			Mouse::wheelDelta.x -= CGEventGetIntegerValueField(event, kCGScrollWheelEventDeltaAxis2);
			Mouse::wheelDelta.z += CGEventGetIntegerValueField(event, kCGScrollWheelEventDeltaAxis3);
			return NULL;
		}
		int button = CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber);
		switch (type) {
			case kCGEventLeftMouseDown:
			case kCGEventRightMouseDown:
			case kCGEventOtherMouseDown:
				HID::state[HID::pressed].button[button] = true;
				HID::state[HID::pushed].button[button] = true | HID::state[HID::pushed].button[button];
				break;
			case kCGEventLeftMouseUp:
			case kCGEventRightMouseUp:
			case kCGEventOtherMouseUp:
				HID::state[HID::pressed].button[button] = false;
				HID::state[HID::released].button[button] = true | HID::state[HID::released].button[button];
				break;
		}
				/*
		switch (type) {
			case kCGEventLeftMouseDown:
				HID::state[HID::pressed].button[Mouse::left.code] = true;
				HID::state[HID::pushed].button[Mouse::left.code] = true | HID::state[HID::pushed].button[Mouse::left.code];
				break;
			case kCGEventLeftMouseUp:
				HID::state[HID::pressed].button[Mouse::left.code] = false;
				HID::state[HID::released].button[Mouse::left.code] = true | HID::state[HID::released].button[Mouse::left.code];
				break;
			case kCGEventRightMouseDown:
				HID::state[HID::pressed].button[Mouse::right.code] = true;
				HID::state[HID::pushed].button[Mouse::right.code] = true | HID::state[HID::pushed].button[Mouse::right.code];
				break;
			case kCGEventRightMouseUp:
				HID::state[HID::pressed].button[Mouse::right.code] = false;
				HID::state[HID::released].button[Mouse::right.code] = true | HID::state[HID::released].button[Mouse::right.code];
				break;
			case kCGEventOtherMouseDown:
				HID::state[HID::pressed].button[Mouse::middle.code] = true;
				HID::state[HID::pushed].button[Mouse::middle.code] = true | HID::state[HID::pushed].button[Mouse::middle.code];
				break;
			case kCGEventOtherMouseUp:
				HID::state[HID::pressed].button[Mouse::middle.code] = false;
				HID::state[HID::released].button[Mouse::middle.code] = true | HID::state[HID::released].button[Mouse::middle.code];
				break;
		}
 */
		return NULL;
	}

	CFRunLoopSourceRef APIHIDProperties::listenerKey,  APIHIDProperties::listenerMouse;

#if !defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
	int APIHIDProperties::keybinder[128];
#endif
#endif

	void APIHIDProperties::bindKeyCode() {
		struct Keyboard_ {
			enum KeyCode{
				one=0,two,three,four,five,six,seven,eight,nine,zero,
				a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
				comma,period,slash,
				pad0,pad1,pad2,pad3,pad4,pad5,pad6,pad7,pad8,pad9,
				rtn,spc,esc,tab,up,down,left,right,
				//	key modulator
				shift=100, shift_r, ctrl, alt,
				//  not recommended
				hyphen=59,equal,backslash,caret,
				underscore,semicolon,colon,leftbracket,rightbracket,at,   // because these keys laid on different location in differnt keyboard-lacalization.
				padcomma,padperiod,padenter,padplus,padminus,padasterisk,padslash,padequal,padclear,	//  because these keys are OS-specific.
				nfer,xfer   // because these keys exist only on Japanese keyboard
			};
		};

#if (defined(PANTHER) && ( PANTHER==1 )) || defined(PSYCHLOPS_SNOW_LEOPARD_PATCH)
		keybinder[Keyboard_::pad0][BIG] = 2;
		keybinder[Keyboard_::pad0][SMALL] = 1024;
		keybinder[Keyboard_::pad1][BIG] = 2;
		keybinder[Keyboard_::pad1][SMALL] = 2048;
		keybinder[Keyboard_::pad2][BIG] = 2;
		keybinder[Keyboard_::pad2][SMALL] = 4096;
		keybinder[Keyboard_::pad3][BIG] = 2;
		keybinder[Keyboard_::pad3][SMALL] = 8192;
		keybinder[Keyboard_::pad4][BIG] = 2;
		keybinder[Keyboard_::pad4][SMALL] = 16384;
		keybinder[Keyboard_::pad5][BIG] = 2;
		keybinder[Keyboard_::pad5][SMALL] = 32768;
		keybinder[Keyboard_::pad6][BIG] = 2;
		keybinder[Keyboard_::pad6][SMALL] = 1;
		keybinder[Keyboard_::pad7][BIG] = 2;
		keybinder[Keyboard_::pad7][SMALL] = 2;
		keybinder[Keyboard_::pad8][BIG] = 2;
		keybinder[Keyboard_::pad8][SMALL] = 8;
		keybinder[Keyboard_::pad9][BIG] = 2;
		keybinder[Keyboard_::pad9][SMALL] = 16;
		keybinder[Keyboard_::padcomma][BIG] = 2;
		keybinder[Keyboard_::padcomma][SMALL] = 128;
		keybinder[Keyboard_::padperiod][BIG] = 2;
		keybinder[Keyboard_::padperiod][SMALL] = 33554432L;
		keybinder[Keyboard_::padenter][BIG] = 2;
		keybinder[Keyboard_::padenter][SMALL] = 1048576L;
		keybinder[Keyboard_::padplus][BIG] = 2;
		keybinder[Keyboard_::padplus][SMALL] = 536870912L;
		keybinder[Keyboard_::padminus][BIG] = 2;
		keybinder[Keyboard_::padminus][SMALL] = 4194304L;
		keybinder[Keyboard_::padasterisk][BIG] = 2;
		keybinder[Keyboard_::padasterisk][SMALL] = 134217728L;
		keybinder[Keyboard_::padslash][BIG] = 2;
		keybinder[Keyboard_::padslash][SMALL] = 524288;
		keybinder[Keyboard_::padequal][BIG] = 2;
		keybinder[Keyboard_::padequal][SMALL] = 512;
		keybinder[Keyboard_::padclear][BIG] = 2;
		keybinder[Keyboard_::padclear][SMALL] = 2147483648UL;
		
		keybinder[Keyboard_::one][BIG] = 0;
		keybinder[Keyboard_::one][SMALL] = 1024;
		keybinder[Keyboard_::two][BIG] = 0;
		keybinder[Keyboard_::two][SMALL] = 2048;
		keybinder[Keyboard_::three][BIG] = 0;
		keybinder[Keyboard_::three][SMALL] = 4096;
		keybinder[Keyboard_::four][BIG] = 0;
		keybinder[Keyboard_::four][SMALL] = 8192;
		keybinder[Keyboard_::five][BIG] = 0;
		keybinder[Keyboard_::five][SMALL] = 32768;
		keybinder[Keyboard_::six][BIG] = 0;
		keybinder[Keyboard_::six][SMALL] = 16384;
		keybinder[Keyboard_::seven][BIG] = 0;
		keybinder[Keyboard_::seven][SMALL] = 4;
		keybinder[Keyboard_::eight][BIG] = 0;
		keybinder[Keyboard_::eight][SMALL] = 16;
		keybinder[Keyboard_::nine][BIG] = 0;
		keybinder[Keyboard_::nine][SMALL] = 2;
		keybinder[Keyboard_::zero][BIG] = 0;
		keybinder[Keyboard_::zero][SMALL] = 32;
		keybinder[Keyboard_::hyphen][BIG] = 0;
		keybinder[Keyboard_::hyphen][SMALL] = 8;
		keybinder[Keyboard_::caret][BIG] = 0;
		keybinder[Keyboard_::caret][SMALL] = 1;
		keybinder[Keyboard_::backslash][BIG] = 2;
		keybinder[Keyboard_::backslash][SMALL] = 32;
		
		keybinder[Keyboard_::q][BIG] = 0;
		keybinder[Keyboard_::q][SMALL] = 1048576L;
		keybinder[Keyboard_::w][BIG] = 0;
		keybinder[Keyboard_::w][SMALL] = 2097152L;
		keybinder[Keyboard_::e][BIG] = 0;
		keybinder[Keyboard_::e][SMALL] = 4194304L;
		keybinder[Keyboard_::r][BIG] = 0;
		keybinder[Keyboard_::r][SMALL] = 8388608L;
		keybinder[Keyboard_::t][BIG] = 0;
		keybinder[Keyboard_::t][SMALL] = 512;
		keybinder[Keyboard_::y][BIG] = 0;
		keybinder[Keyboard_::y][SMALL] = 256;
		keybinder[Keyboard_::u][BIG] = 1;
		keybinder[Keyboard_::u][SMALL] = 16777216L;
		keybinder[Keyboard_::i][BIG] = 1;
		keybinder[Keyboard_::i][SMALL] = 67108864L;
		keybinder[Keyboard_::o][BIG] = 0;
		keybinder[Keyboard_::o][SMALL] = 128;
		keybinder[Keyboard_::p][BIG] = 1;
		keybinder[Keyboard_::p][SMALL] = 134217728L;
		keybinder[Keyboard_::at][BIG] = 1;
		keybinder[Keyboard_::at][SMALL] = 33554432L;
		keybinder[Keyboard_::leftbracket][BIG] = 0;
		keybinder[Keyboard_::leftbracket][SMALL] = 64;
		
		keybinder[Keyboard_::a][BIG] = 0;
		keybinder[Keyboard_::a][SMALL] = 16777216L;
		keybinder[Keyboard_::s][BIG] = 0;
		keybinder[Keyboard_::s][SMALL] = 33554432L;
		keybinder[Keyboard_::d][BIG] = 0;
		keybinder[Keyboard_::d][SMALL] = 67108864L;
		keybinder[Keyboard_::f][BIG] = 0;
		keybinder[Keyboard_::f][SMALL] = 134217728L;
		keybinder[Keyboard_::g][BIG] = 0;
		keybinder[Keyboard_::g][SMALL] = 536870912L;
		keybinder[Keyboard_::h][BIG] = 0;
		keybinder[Keyboard_::h][SMALL] = 268435456L;
		keybinder[Keyboard_::j][BIG] = 1;
		keybinder[Keyboard_::j][SMALL] = 1073741824L;
		keybinder[Keyboard_::k][BIG] = 1;
		keybinder[Keyboard_::k][SMALL] = 65536L;
		keybinder[Keyboard_::l][BIG] = 1;
		keybinder[Keyboard_::l][SMALL] = 536870912L;
		keybinder[Keyboard_::semicolon][BIG] = 1;
		keybinder[Keyboard_::semicolon][SMALL] = 131072L;
		keybinder[Keyboard_::colon][BIG] = 1;
		keybinder[Keyboard_::colon][SMALL] = 2147483648UL;
		keybinder[Keyboard_::rightbracket][BIG] = 1;
		keybinder[Keyboard_::rightbracket][SMALL] = 262144L;
		
		keybinder[Keyboard_::z][BIG] = 0;
		keybinder[Keyboard_::z][SMALL] = 1073741824L;
		keybinder[Keyboard_::x][BIG] = 0;
		keybinder[Keyboard_::x][SMALL] = 2147483648UL;
		keybinder[Keyboard_::c][BIG] = 0;
		keybinder[Keyboard_::c][SMALL] = 65536L;
		keybinder[Keyboard_::v][BIG] = 0;
		keybinder[Keyboard_::v][SMALL] = 131072L;
		keybinder[Keyboard_::b][BIG] = 0;
		keybinder[Keyboard_::b][SMALL] = 524288L;
		keybinder[Keyboard_::n][BIG] = 1;
		keybinder[Keyboard_::n][SMALL] = 2097152L;
		keybinder[Keyboard_::m][BIG] = 1;
		keybinder[Keyboard_::m][SMALL] = 4194304L;
		keybinder[Keyboard_::comma][BIG] = 1;
		keybinder[Keyboard_::comma][SMALL] = 524288L;
		keybinder[Keyboard_::period][BIG] = 1;
		keybinder[Keyboard_::period][SMALL] = 8388608L;
		keybinder[Keyboard_::slash][BIG] = 1;
		keybinder[Keyboard_::slash][SMALL] = 1048576L;
		keybinder[Keyboard_::underscore][BIG] = 2;
		keybinder[Keyboard_::underscore][SMALL] = 64;
		
		keybinder[Keyboard_::esc][BIG] = 1;
		keybinder[Keyboard_::esc][SMALL] = 8192;
		keybinder[Keyboard_::tab][BIG] = 1;
		keybinder[Keyboard_::tab][SMALL] = 256;
		keybinder[Keyboard_::rtn][BIG] = 1;
		keybinder[Keyboard_::rtn][SMALL] = 268435456;
		keybinder[Keyboard_::spc][BIG] = 1;
		keybinder[Keyboard_::spc][SMALL] = 512;
		keybinder[Keyboard_::up][BIG] = 3;
		keybinder[Keyboard_::up][SMALL] = 64;
		keybinder[Keyboard_::down][BIG] = 3;
		keybinder[Keyboard_::down][SMALL] = 32;
		keybinder[Keyboard_::left][BIG] = 3;
		keybinder[Keyboard_::left][SMALL] = 8;
		keybinder[Keyboard_::right][BIG] = 3;
		keybinder[Keyboard_::right][SMALL] = 16;
		
		keybinder[Keyboard_::shift][BIG] = 1;
		keybinder[Keyboard_::shift][SMALL] = 1;
		keybinder[Keyboard_::ctrl][BIG] = 1;
		keybinder[Keyboard_::ctrl][SMALL] = 8;
		keybinder[Keyboard_::alt][BIG] = 1;
		keybinder[Keyboard_::alt][SMALL] = 4;
#else
		keybinder[Keyboard_::pad0] = 82;
		keybinder[Keyboard_::pad1] = 83;
		keybinder[Keyboard_::pad2] = 84;
		keybinder[Keyboard_::pad3] = 85;
		keybinder[Keyboard_::pad4] = 86;
		keybinder[Keyboard_::pad5] = 87;
		keybinder[Keyboard_::pad6] = 88;
		keybinder[Keyboard_::pad7] = 89;
		keybinder[Keyboard_::pad8] = 91;
		keybinder[Keyboard_::pad9] = 02;
		keybinder[Keyboard_::padcomma] = 95;
		keybinder[Keyboard_::padperiod] = 65;
		keybinder[Keyboard_::padenter] = 76;
		keybinder[Keyboard_::padplus] = 69;
		keybinder[Keyboard_::padminus] = 78;
		keybinder[Keyboard_::padasterisk] = 67;
		keybinder[Keyboard_::padslash] = 75;
		keybinder[Keyboard_::padequal] = 81;
		keybinder[Keyboard_::padclear] = 71;
		
		keybinder[Keyboard_::one]   = 18;
		keybinder[Keyboard_::two]   = 19;
		keybinder[Keyboard_::three] = 20;
		keybinder[Keyboard_::four]  = 21;
		keybinder[Keyboard_::five]  = 23;
		keybinder[Keyboard_::six]   = 22;
		keybinder[Keyboard_::seven] = 26;
		keybinder[Keyboard_::eight] = 28;
		keybinder[Keyboard_::nine]  = 25;
		keybinder[Keyboard_::zero]  = 29;
		keybinder[Keyboard_::hyphen] = 27;
		keybinder[Keyboard_::caret] = 24;
		keybinder[Keyboard_::backslash] = 93;
		
		keybinder[Keyboard_::q] = 12;
		keybinder[Keyboard_::w] = 13;
		keybinder[Keyboard_::e] = 14;
		keybinder[Keyboard_::r] = 15;
		keybinder[Keyboard_::t] = 17;
		keybinder[Keyboard_::y] = 16;
		keybinder[Keyboard_::u] = 32;
		keybinder[Keyboard_::i] = 34;
		keybinder[Keyboard_::o] = 31;
		keybinder[Keyboard_::p] = 35;
		keybinder[Keyboard_::at] = 33;
		keybinder[Keyboard_::leftbracket] = 30;
		
		keybinder[Keyboard_::a] = 0;
		keybinder[Keyboard_::s] = 1;
		keybinder[Keyboard_::d] = 2;
		keybinder[Keyboard_::f] = 3;
		keybinder[Keyboard_::g] = 5;
		keybinder[Keyboard_::h] = 4;
		keybinder[Keyboard_::j] = 38;
		keybinder[Keyboard_::k] = 40;
		keybinder[Keyboard_::l] = 37;
		keybinder[Keyboard_::semicolon] = 41;
		keybinder[Keyboard_::colon] = 39;
		keybinder[Keyboard_::rightbracket] = 42;
		
		keybinder[Keyboard_::z] = 6;
		keybinder[Keyboard_::x] = 7;
		keybinder[Keyboard_::c] = 8;
		keybinder[Keyboard_::v] = 9;
		keybinder[Keyboard_::b] = 11;
		keybinder[Keyboard_::n] = 45;
		keybinder[Keyboard_::m] = 46;
		keybinder[Keyboard_::comma] = 43;
		keybinder[Keyboard_::period] = 47;
		keybinder[Keyboard_::slash] = 44;
		keybinder[Keyboard_::underscore] = 94;
		
		keybinder[Keyboard_::esc] = 53;
		keybinder[Keyboard_::rtn] = 36;
		keybinder[Keyboard_::spc] = 49;
		keybinder[Keyboard_::up] = 126;
		keybinder[Keyboard_::down] = 125;
		keybinder[Keyboard_::left] = 123;
		keybinder[Keyboard_::right] = 124;
		keybinder[Keyboard_::tab] = 48;
		keybinder[Keyboard_::nfer] = 102;
		keybinder[Keyboard_::xfer] = 104;

		keybinder[Keyboard_::shift] = 56;
		keybinder[Keyboard_::shift_r] = 60;
		keybinder[Keyboard_::ctrl] = 59;
		keybinder[Keyboard_::alt] = 58;
#endif
	}







/*
	::Point APIMouseProperties::position_;

	void APIMouseProperties::getPosition(int &x, int &y) {
		x = position_.h;
		y = position_.v;
	}
	void APIMouseProperties::setPosition(int x, int y) {
		CGPoint p;
		p.x = x;
		p.y = y;
		CGWarpMouseCursorPosition(p);
	}

	void APIMouseProperties::update() {
		bool state = Button();
		HID::state[HID::hadpressed].button[Mouse::left.code] = HID::state[HID::pressed].button[Mouse::left.code];		
		HID::state[HID::pressed].button[Mouse::left.code] = state;
		HID::state[HID::pushed].button[Mouse::left.code] = (HID::state[HID::pressed].button[Mouse::left.code] != HID::state[HID::hadpressed].button[Mouse::left.code]) & HID::state[HID::pressed].button[Mouse::left.code] | HID::state[HID::pushed].button[Mouse::left.code];
		HID::state[HID::released].button[Mouse::left.code] = (HID::state[HID::pressed].button[Mouse::left.code] != HID::state[HID::hadpressed].button[Mouse::left.code]) & !HID::state[HID::pressed].button[Mouse::left.code] | HID::state[HID::released].button[Mouse::left.code];
		GetMouse(&position_);
	}

	bool APIMouseProperties::get(Mouse::Button button, HID::ButtonState state) {
		bool val = HID::state[state].button[button.code];
		HID::state[state].button[button.code] = false;
		return val;
	}
*/

}	/*	<- namespace Psycholops 	*/
