/*
Module Name: kbdCShack.c
Description: Czech and Slovak 1337 h4x0r5' keyboard layout
Copyright: (c) 2008, Ladislav Matula
Licence: Freeware even for commercial use, cannot be sold
Version 1.1
*/

#define COMPILE_MULTIMON_STUBS
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0502
#define WINVER 0x0502
#define VK_CSHACK VK_KANA
#define KBD_TYPE 4

#include <windows.h>
#include "kbd.h"

/////////////////////////built-in modifications/////////////////////////////////////

//#define PRESERVE_RIGHT_WIN //CShack instead of right Win key
//#define OLD_MODE_U //swapping ù ú, old mode: u->ù h->ú, new mode: u->ú h->ù
//#define SWAP_Z_Y //swapping z y

///////////////////////////////////////////////////////////////////////////


// #if defined(_M_IA64)
// 	#pragma section(".data")
// 	#define ALLOC_SECTION_LDATA __declspec(allocate(".data"))
// #else
// 	#pragma data_seg(".data")
// 	#define ALLOC_SECTION_LDATA
// #endif

#define ALLOC_SECTION_LDATA

//ausVK[] - Virtual Scan Code to Virtual Key conversion table for CShack
static ALLOC_SECTION_LDATA USHORT ausVK[] = 
{
	T00, T01, T02, T03, T04, T05, T06, T07, T08, T09, T0A, T0B, T0C, T0D, T0E, T0F,
	T10, T11, T12, T13, T14,

#ifdef SWAP_Z_Y
	T2C, //Z
#else
	T15, //Y
#endif
	T16, T17, T18, T19, T1A, T1B, T1C, T1D, T1E, T1F,
	T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T2A, T2B, 

#ifdef SWAP_Z_Y
	T15, //Y
#else
	T2C, //Z
#endif

	T2D, T2E, T2F,
	T30, T31, T32, T33, T34, T35,

	//Right-hand Shift key must have KBDEXT bit set.
	T36 | KBDEXT,

	T37 | KBDMULTIVK,				// numpad_* + Shift/Alt -> SnapShot

	T38, T39, VK_CSHACK /*T3A*/, T3B, T3C, T3D, T3E, T3F, T40, T41, T42, T43, T44,

	//NumLock Key:
	//	   KBDEXT	  - VK_NUMLOCK is an Extended key
	//	   KBDMULTIVK - VK_NUMLOCK or VK_PAUSE (without or with CTRL)

	//T45 | KBDEXT | KBDMULTIVK,
	//T3A,//replace NumLock with CapsLock?
	X20 | KBDEXT,//replace numlock with Mute

	//T46 | KBDMULTIVK,
	X22 | KBDEXT,//replace ScrollLock with Play | Pause	

	//Number Pad keys:
	//	   KBDNUMPAD  - digits 0-9 and decimal point.
	//	   KBDSPECIAL - require special processing by Windows

//	  T47 | KBDNUMPAD | KBDSPECIAL,   // Numpad 7 (Home)
//	  T48 | KBDNUMPAD | KBDSPECIAL,   // Numpad 8 (Up),
//	  T49 | KBDNUMPAD | KBDSPECIAL,   // Numpad 9 (PgUp),
	VK_NUMPAD7,   // Numpad 7 (Home)
	VK_NUMPAD8,   // Numpad 8 (Up),
	VK_NUMPAD9,   // Numpad 9 (PgUp),

	T4A ,
  
	//T4B | KBDNUMPAD | KBDSPECIAL,   // Numpad 4 (Left),
	//T4C | KBDNUMPAD | KBDSPECIAL,   // Numpad 5 (Clear),
	//T4D | KBDNUMPAD | KBDSPECIAL,   // Numpad 6 (Right),
	VK_NUMPAD4,   // Numpad 4 (Left),
	VK_NUMPAD5,   // Numpad 5 (Clear),
	VK_NUMPAD6,   // Numpad 6 (Right),

	T4E,

	//T4F | KBDNUMPAD | KBDSPECIAL,   // Numpad 1 (End),
	//T50 | KBDNUMPAD | KBDSPECIAL,   // Numpad 2 (Down),
	//T51 | KBDNUMPAD | KBDSPECIAL,   // Numpad 3 (PgDn),
	//T52 | KBDNUMPAD | KBDSPECIAL,   // Numpad 0 (Ins),

	VK_NUMPAD1,   // Numpad 1 (End),
	VK_NUMPAD2,   // Numpad 2 (Down),
	VK_NUMPAD3,   // Numpad 3 (PgDn),
	VK_NUMPAD0,   // Numpad 0 (Ins),

//	VK_SEPARATOR,	// Numpad . (Del),
	T53 | KBDNUMPAD | KBDSPECIAL,   // Numpad . (Del),

	T54, T55, T56, T57, T58, T59, T5A, T5B, T5C, T5D, T5E, T5F, T60, T61, T62, T63,
	T64, T65, T66, T67, T68, T69, T6A, T6B, T6C, T6D, T6E, T6F, T70, T71, T72, T73,
	T74, T75, T76, T77, T78, T79, T7A, T7B, T7C, T7D, T7E

};


static ALLOC_SECTION_LDATA VSC_VK aE0VscToVk[] = 
{
		{ 0x10, X10 | KBDEXT			  },  // Speedracer: Previous Track
		{ 0x19, X19 | KBDEXT			  },  // Speedracer: Next Track
		{ 0x1D, X1D | KBDEXT			  },  // RControl
		{ 0x20, X20 | KBDEXT			  },  // Speedracer: Volume Mute
		{ 0x21, X21 | KBDEXT			  },  // Speedracer: Launch App 2
		{ 0x22, X22 | KBDEXT			  },  // Speedracer: Media Play/Pause
		{ 0x24, X24 | KBDEXT			  },  // Speedracer: Media Stop
		{ 0x2E, X2E | KBDEXT			  },  // Speedracer: Volume Down
		{ 0x30, X30 | KBDEXT			  },  // Speedracer: Volume Up
		{ 0x32, X32 | KBDEXT			  },  // Speedracer: Browser Home
		{ 0x35, X35 | KBDEXT			  },  // Numpad Divide
		{ 0x37, X37 | KBDEXT			  },  // Snapshot
		{ 0x38, X38 | KBDEXT			  },  // RMenu
		{ 0x47, X47 | KBDEXT			  },  // Home
		{ 0x48, X48 | KBDEXT			  },  // Up
		{ 0x49, X49 | KBDEXT			  },  // Prior
		{ 0x4B, X4B | KBDEXT			  },  // Left
		{ 0x4D, X4D | KBDEXT			  },  // Right
		{ 0x4F, X4F | KBDEXT			  },  // End
		{ 0x50, X50 | KBDEXT			  },  // Down
		{ 0x51, X51 | KBDEXT			  },  // Next
		{ 0x52, X52 | KBDEXT			  },  // Insert
		{ 0x53, X53 | KBDEXT			  },  // Delete
		{ 0x5B, X5B | KBDEXT			  },  // Left Win

#ifdef PRESERVE_RIGHT_WIN
		{ 0x5C, X5C | KBDEXT			  },  // Right Win
#else
		{ 0x5C, VK_CSHACK				  },  // Right Win
#endif

		{ 0x5D, X5D | KBDEXT			  },  // Application
		{ 0x5F, X5F | KBDEXT			  },  // Speedracer: Sleep
		{ 0x65, X65 | KBDEXT			  },  // Speedracer: Browser Search
		{ 0x66, X66 | KBDEXT			  },  // Speedracer: Browser Favorites
		{ 0x67, X67 | KBDEXT			  },  // Speedracer: Browser Refresh
		{ 0x68, X68 | KBDEXT			  },  // Speedracer: Browser Stop
		{ 0x69, X69 | KBDEXT			  },  // Speedracer: Browser Forward
		{ 0x6A, X6A | KBDEXT			  },  // Speedracer: Browser Back
		{ 0x6B, X6B | KBDEXT			  },  // Speedracer: Launch App 1
		{ 0x6C, X6C | KBDEXT			  },  // Speedracer: Launch Mail
		{ 0x6D, X6D | KBDEXT			  },  // Speedracer: Launch Media Selector
		{ 0x1C, X1C | KBDEXT			  },  // Numpad Enter
		{ 0x46, X46 | KBDEXT			  },  // Break (Ctrl + Pause)
		{ 0,	  0 					  }
};

static ALLOC_SECTION_LDATA VSC_VK aE1VscToVk[] = 
{
		{ 0x1D, Y1D 					  },  // Pause
		{ 0   ,   0 					  }
};

//aVkToBits[]  - map Virtual Keys to Modifier Bits
static ALLOC_SECTION_LDATA VK_TO_BIT aVkToBits[] = 
{
	{ VK_SHIFT	  ,   KBDSHIFT	   },
	{ VK_CONTROL  ,   KBDCTRL	   },
	{ VK_MENU	  ,   KBDALT	   },
	{ VK_CSHACK   ,   KBDKANA	   },
	{0			  ,    0		   }
};

//aModification[]  - map character modifier bits to modification number
static ALLOC_SECTION_LDATA MODIFIERS CharModifiers = 
{
	&aVkToBits[0],
	9,
	{
	//	Modification# //  Keys Pressed
	//	============= // =============
		0,			  // 0: 0000
		1,			  // 1: 0001					Shift
		2,			  // 2: 0010			  Ctrl
		3,			  // 3: 0011			  Ctrl + Shift
		SHFT_INVALID, // 4: 0100		Alt 				: invalid
		SHFT_INVALID, // 5: 0101		Alt 	   + Shift	: invalid
		SHFT_INVALID, // 6: 0110		Alt + Ctrl			: invalid
		SHFT_INVALID, // 7: 0111		Alt + Ctrl + Shift	: invalid
		4,			  // 8: 1000 CShack
		5,			  // 9: 1001 CSHack 		   + Shift
	 }
};

//aVkToWch2[]  - Virtual Key to WCHAR translation for 2 shift states
//aVkToWch3[]  - Virtual Key to WCHAR translation for 3 shift states
//aVkToWch4[]  - Virtual Key to WCHAR translation for 4 shift states
static ALLOC_SECTION_LDATA VK_TO_WCHARS2 aVkToWch2[] = 
{
//						  | 		|  Shift  |
//						  |=========|=========|
/*
	{VK_OEM_3	  ,0	  ,'`'		,'~'	  },
	{'1'		  ,0	  ,'1'		,'!'	  },
	{'3'		  ,0	  ,'3'		,'#'	  },
	{'4' 		 ,0 	 ,'4'	   ,'$' 	 },
	{'5' 		 ,0 	 ,'5'	   ,'%' 	 },
	{'7' 		 ,0 	 ,'7'	   ,'&' 	 },
	{'8'		  ,0	  ,'8'		,'*'	  },
	{'9'		  ,0	  ,'9'		,'('	  },
	{'0'		  ,0	  ,'0'		,')'	  },
	{VK_OEM_PLUS  ,0	  ,'='		,'+'	  },
	{'Q'		  ,0	  ,'q'		,'Q'	  },
	{'W'		  ,0	  ,'w'		,'W'	  },
	{'E'		  ,0	  ,'e'		,'E'	  },
	{'R'		  ,0	  ,'r'		,'R'	  },
	{'T'		  ,0	  ,'t'		,'T'	  },
	{'Y'		  ,0	  ,'y'		,'Y'	  },
	{'U'		  ,0	  ,'u'		,'U'	  },
	{'I'		  ,0	  ,'i'		,'I'	  },
	{'O'		  ,0	  ,'o'		,'O'	  },
	{'P'		  ,0	  ,'p'		,'P'	  },
	{'A'		  ,0	  ,'a'		,'A'	  },
	{'S'		  ,0	  ,'s'		,'S'	  },
	{'D'		  ,0	  ,'d'		,'D'	  },
	{'F'		  ,0	  ,'f'		,'F'	  },
	{'G'		  ,0	  ,'g'		,'G'	  },
	{'H'		  ,0	  ,'h'		,'H'	  },
	{'J'		  ,0	  ,'j'		,'J'	  },
	{'K'		  ,0	  ,'k'		,'K'	  },
	{'L'		  ,0	  ,'l'		,'L'	  },

	{VK_OEM_1	  ,0	  ,';'		,':'	  },
	{VK_OEM_7	  ,0	  ,'\'' 	,'\"'	  },
	{'Z'			,0		,'z'	  ,'Z'		},
	{'X'		  ,0	  ,'x'		,'X'	  },
	{'C'		  ,0	  ,'c'		,'C'	  },*/


	//{'V'			,CAPLOK 	 ,'v'	   ,'V' 	 },
	{'V'		  ,0	  ,'v'		,'V'	  }, //no CAPS-LOCK influence
						
/*	{'B'		  ,0		,'b'	  ,'B'		},
	{'N'		  ,0	  ,'n'		,'N'	  },
	{'M'		  ,0	  ,'m'		,'M'	  },
	{VK_OEM_COMMA ,0	  ,','		,'<'	  },
	{VK_OEM_PERIOD,0	  ,'.'		,'>'	  },
	{VK_OEM_2	  ,0	  ,'/'		,'?'	  },*/
	{VK_TAB 	  ,0	  ,'\t' 	,'\t'	  },
/*	{VK_DECIMAL   ,0	  ,'.'		,'.'	  },
	{VK_ADD 	  ,0	  ,'+'		,'+'	  },
	{VK_DIVIDE	  ,0	  ,'/'		,'/'	  },
	{VK_MULTIPLY  ,0	  ,'*'		,'*'	  },
	{VK_SUBTRACT  ,0	  ,'-'		,'-'	  },*/
	{0			  ,0	  ,0		,0		  }
};

static ALLOC_SECTION_LDATA VK_TO_WCHARS3 aVkToWch3[] = 
{
//						|		  |  Shift	|  Ctrl   |
//						|=========|=========|=========|
/*	{VK_OEM_4	   ,0	   ,'[' 	 ,'{'	   ,0x001b	 },
	{VK_OEM_6	   ,0	   ,']' 	 ,'}'	   ,0x001d	 },
	{VK_OEM_5	   ,0	   ,'\\'	 ,'|'	   ,0x001c	 },
	{VK_OEM_102   ,0	   ,'\\'	 ,'|'	   ,0x001c	 },*/
	{VK_BACK		,0		,'\b'	  ,'\b' 	,0x007f   },
	{VK_ESCAPE	,0		,0x001b   ,0x001b	,0x001b   },
//	{VK_RETURN	  ,0	  ,'\r' 	,'\r'	  ,'\n' 	},
//	{VK_SPACE	   ,0	   ,' ' 	 ,' '	   ,' ' 	 },
	{VK_CANCEL	,0		,0x0003   ,0x0003	,0x0003   },
	{0			,0		,0		  ,0		,0		  }
};

/*
static ALLOC_SECTION_LDATA VK_TO_WCHARS4 aVkToWch4[] = 
{
//						|		  |  Shift	|  Ctrl   |S+Ctrl	|
//						|=========|=========|=========|=========|
//?  {'2'		   ,0	   ,'2' 	 ,'@'	   ,WCH_NONE ,0x0000   },
//?  {'6'		   ,0	   ,'6' 	 ,'^'	   ,WCH_NONE ,0x001e   },
//?  {VK_OEM_MINUS ,0	   ,'-' 	 ,'_'	   ,WCH_NONE ,0x001f   },
  {0			,0		,0		  ,0		,0		  ,0		}
};
*/

static ALLOC_SECTION_LDATA VK_TO_WCHARS6 aVkToWch6[] = 
{
//					|		  |  Shift	|  Ctrl   |S+Ctrl	| KANA	| Sh+KANA
//					|=========|=========|=========|=========|=======|========
  { VK_OEM_3	,0		,'`'	  ,'~'		,WCH_NONE ,WCH_NONE ,0x2248, 0x00A1},//double tilda, reverse !
  {'1'			,0		,'1'	  ,'!'		,WCH_NONE ,WCH_NONE ,0xA7  , 0x2122},//paragraf, TM
  {'2'			,0		,'2'	  ,'@'		,WCH_NONE ,WCH_NONE ,0xAE  , 0x00A9}, //R, C
  {'3'			,0		,'3'	  ,'#'		,WCH_NONE ,WCH_NONE ,0x03C0, 0x2116}, //pi, No
  {'4'			,0		,'4'	  ,'$'		,WCH_NONE ,WCH_NONE ,0x020AC,0x00A2}, //euro, cent
  {'5'			,0		,'5'	  ,'%'		,WCH_NONE ,WCH_NONE ,0x00B0, 0x2030}, //stupen, promile
  {'6'			,0		,'6'	  ,'^'		,WCH_NONE ,0x001e	,0x2032, 0x221A}, //minuta-stopa-prime, odmocnina
  {'7'			,0		,'7'	  ,'&'		,WCH_NONE ,WCH_NONE ,0x2033, 0x221B}, //palec-doubleprime, treti odmocnina
  {'8'			,0		,'8'	  ,'*'		,WCH_NONE ,WCH_NONE ,0x221E, 0x2020}, //infinity, dagger (krizek)
  {'9'			,0		,'9'	  ,'('		,WCH_NONE ,WCH_NONE ,0x201A, 0x2211}, //prvni ceska jednoducha uvozovka 9, suma
  {'0'			,0		,'0'	  ,')'		,WCH_NONE ,WCH_NONE ,0x2018, 0x2019}, //druha ceska jednoducha uvozovka 6, druha en jednoducha uvozovka 9 horni
  {VK_OEM_MINUS ,0		,'-'	  ,'_'		,WCH_NONE ,0x001f	,0x2013, 0x2014}, //n-dash, m-dash
  {VK_OEM_PLUS	,0		,'='	  ,'+'		,WCH_NONE ,WCH_NONE ,0x2260, 0x00B1}, //nerovna se, plus-minus
  {VK_OEM_5 	,0		,'\\'	  ,'|'		,0x001c   ,WCH_NONE ,0x2250, 0x2261}, //priblizne rovno, identicke
  {VK_OEM_102	,0		,'\\'	  ,'|'		,0x001c   ,WCH_NONE ,0x2250, 0x2261}, //priblizne rovno, identicke
  {VK_OEM_4 	,0		,'['	  ,'{'		,0x001b   ,WCH_NONE ,0x00AB, 0x2039}, //francouzske uvozovky dvojite a jednoduche
  {VK_OEM_6 	,0		,']'	  ,'}'		,0x001d   ,WCH_NONE ,0x00BB, 0x203A}, //
  {VK_OEM_1 	,0		,';'	  ,':'		,WCH_NONE ,WCH_NONE ,0x201E, 0x00A6}, //prvni ceska uvozovka 99, "broken bar"
  {VK_OEM_7 	,0		,'\''	  ,'\"' 	,WCH_NONE ,WCH_NONE ,0x201C, 0x201D}, //druha ceska uvozovka 66, anglicka druha uvozovka
  {VK_OEM_COMMA ,0		,','	  ,'<'		,WCH_NONE ,WCH_NONE ,0x00B7, 0x2264}, //middle dot, je mensi nebo rovno
  {VK_OEM_PERIOD,0		,'.'	  ,'>'		,WCH_NONE ,WCH_NONE ,0x2026, 0x2265}, //trojtecka, je vetsi nebo rovno
  {VK_OEM_2 	,0		,'/'	  ,'?'		,WCH_NONE ,WCH_NONE ,0x00B5, 0x00BF}, //micro, obraceny otaznik
  {VK_SPACE 	,0		,' '	  ,0x2002	,' '	  ,WCH_NONE ,0x00A0, 0x2060}, //en space, hard space, word joiner
  {VK_RETURN	,0		,'\r'	  ,'\r' 	,'\n'	  ,WCH_NONE ,0x00B6, 0x00B6}, //znak odstavce

  {VK_DECIMAL	,0		,'.'	  ,'.'		,WCH_NONE  ,WCH_NONE ,0x2022, 0x2022}, //bullet
  {VK_ADD		,0		,'+'	  ,'+'		,WCH_NONE  ,WCH_NONE ,0x207A, 0x207A}, //super plus
  {VK_DIVIDE	,0		,'/'	  ,'/'		,WCH_NONE  ,WCH_NONE ,0x00F7, 0x00F7}, //deleno -:-
  {VK_MULTIPLY	,0		,'*'	  ,'*'		,WCH_NONE  ,WCH_NONE ,0x00D7, 0x00D7}, //krat
  {VK_SUBTRACT	,0		,'-'	  ,'-'		,WCH_NONE  ,WCH_NONE ,0x2212, 0x2212}, //minus

  {'Q'			,0 ,'q' 	 ,'Q'	   ,WCH_NONE ,0x0000   , 0xe4  , 0xc4  }, //
  {'W'			,0 ,'w' 	 ,'W'	   ,WCH_NONE ,0x0000   , 0x11B , 0x11a	}, //Ìì
  {'E'			,0 ,'e' 	 ,'E'	   ,WCH_NONE ,0x0000   , 0xe9  , 0xc9  }, //éÉ
  {'R'			,0 ,'r' 	 ,'R'	   ,WCH_NONE ,0x0000   , 0x159 , 0x158	}, //
  {'T'			,0 ,'t' 	 ,'T'	   ,WCH_NONE ,0x0000   , 0x165 , 0x164	}, //
  {'Y'			,0 ,'y' 	 ,'Y'	   ,WCH_NONE ,0x0000   , 0xfd  , 0xdd  }, //

#ifdef OLD_MODE_U
  {'U'			,0 ,'u' 	 ,'U'	   ,WCH_NONE ,0x0000   , 0x16f , 0x16e	}, //ùÙ
  {'H'			,0 ,'h' 	 ,'H'	   ,WCH_NONE ,0x0000   , 0xfa  , 0xda  },  //úÚ
#else
  {'U'			,0 ,'u' 	 ,'U'	   ,WCH_NONE ,0x0000   , 0xfa  , 0xda	}, //úÚ
  {'H'			,0 ,'h' 	 ,'H'	   ,WCH_NONE ,0x0000   , 0x16f , 0x16e  }, //ùÙ
#endif

  {'I'			,0 ,'i' 	 ,'I'	   ,WCH_NONE ,0x0000   , 0x0ed , 0x0cd	}, //
  {'O'			,0 ,'o' 	 ,'O'	   ,WCH_NONE ,0x0000   , 0xf3  , 0xd3  }, //
  {'P'			,0 ,'p' 	 ,'P'	   ,WCH_NONE ,0x0000   , 0xf6  , 0xd6  }, //Öö

  {'A'			,0 ,'a' 	 ,'A'	   ,WCH_NONE ,0x0000   , 0xe1  , 0xc1  }, //áÁ
  {'S'			,0 ,'s' 	 ,'S'	   ,WCH_NONE ,0x0000   , 0x161 , 0x160	}, //
  {'D'			,0 ,'d' 	 ,'D'	   ,WCH_NONE ,0x0000   , 0x10f , 0x10e	}, //
  {'F'			,0 ,'f' 	 ,'F'	   ,WCH_NONE ,0x0000   , 0xeb  , 0xcb  }, //ëË
  {'G'			,0 ,'g' 	 ,'G'	   ,WCH_NONE ,0x0000   , 0x155	, 0x154  }, //'r'R
  {'J'			,0 ,'j' 	 ,'J'	   ,WCH_NONE ,0x0000   , 0xfc  , 0xdc  }, //üÜ
  {'K'			,0 ,'k' 	 ,'K'	   ,WCH_NONE ,0x0000   , 0xf4  , 0xd4  }, //ôÔ
  {'L'			,0 ,'l' 	 ,'L'	   ,WCH_NONE ,0x0000   , 0x13e , 0x13d	}, //¾¼

  {'Z'			,0 ,'z' 	 ,'Z'	   ,WCH_NONE ,0x0000   , 0x17e , 0x17d }, //žŽ
  {'X'			,0 ,'x' 	 ,'X'	   ,WCH_NONE ,0x0000   , 0xf1 , 0xd1 }, //~n~N
  {'C'			,0 ,'c' 	 ,'C'		,WCH_NONE ,0x0000	, 0x10d , 0x10c  }, //
  //{'V'		  ,0	  ,'v'		,'V'	  ,WCH_NONE ,0x0000   , 0xe7  , 0xc7  }, //Çç
  {'B'			,0 ,'b' 	 ,'B'	   ,WCH_NONE ,0x0000   , 0xdf  , 0x3BC	}, //sharp s, micro
  {'N'			,0 ,'n' 	 ,'N'	   ,WCH_NONE ,0x0000   , 0x148 , 0x147	}, //
  {'M'			,0 ,'m' 	 ,'M'	   ,WCH_NONE ,0x0000   , 0x13a , 0x139	}, //åÅ

  {VK_NUMPAD0	,0 ,'0' 	 ,'0'	   ,WCH_NONE ,WCH_NONE ,0x2070	,0x2194   }, //0 exp, <->
  {VK_NUMPAD1	,0 ,'1' 	 ,'1'	   ,WCH_NONE ,WCH_NONE ,0x2000	,0x2153   }, //1 exp, 1/3
  {VK_NUMPAD2	,0 ,'2' 	 ,'2'	   ,WCH_NONE ,WCH_NONE ,0x00B2	,0x00BD   }, //2 exp, 1/2
  {VK_NUMPAD3	,0 ,'3' 	 ,'3'	   ,WCH_NONE ,WCH_NONE ,0x00B3	,0x00BE   }, //3 exp, 3/4
  {VK_NUMPAD4	,0 ,'4' 	 ,'4'	   ,WCH_NONE ,WCH_NONE ,0x2074	,0x00BC   }, //4 exp, 1/4
  {VK_NUMPAD5	,0 ,'5' 	 ,'5'	   ,WCH_NONE ,WCH_NONE ,0x2075	,0x215D   }, //5 exp, 5/8
  {VK_NUMPAD6	,0 ,'6' 	 ,'6'	   ,WCH_NONE ,WCH_NONE ,0x2076	,0x2154   }, //6 exp, 2/3
  {VK_NUMPAD7	,0 ,'7' 	 ,'7'	   ,WCH_NONE ,WCH_NONE ,0x2077	,0x215E   }, //7 exp, 7/8
  {VK_NUMPAD8	,0 ,'8' 	 ,'8'	   ,WCH_NONE ,WCH_NONE ,0x2078	,0x2158   }, //8 exp, 1/8
  {VK_NUMPAD9	,0 ,'9' 	 ,'9'	   ,WCH_NONE ,WCH_NONE ,0x2079	,0x215C   }, //9 exp, 3/8					
  {VK_SEPARATOR ,0 ,'.' 	 ,'.'	   ,WCH_NONE ,WCH_NONE ,0x2022	,0x2022   }, //bullet

  {0			,0 ,0		 ,0 	   ,0		 ,0 	   , 0		, 0 	  }
};


// Put this last so that VkKeyScan interprets number characters
// as coming from the main section of the kbd (aVkToWch2 and
// aVkToWch5) before considering the numpad (aVkToWch1).
/*
static ALLOC_SECTION_LDATA VK_TO_WCHARS1 aVkToWch1[] = 
{
/*	  { VK_NUMPAD0	 , 0	  ,  '0'   },
	{ VK_NUMPAD1   , 0		,  '1'	 },
	{ VK_NUMPAD2   , 0		,  '2'	 },
	//{ VK_NUMPAD3	 , 0	  ,  '3'   },
	{ VK_NUMPAD4   , 0		,  '4'	 },
	{ VK_NUMPAD5   , 0		,  '5'	 },
	{ VK_NUMPAD6   , 0		,  '6'	 },
	{ VK_NUMPAD7   , 0		,  '7'	 },
	{ VK_NUMPAD8   , 0		,  '8'	 },
	{ VK_NUMPAD9   , 0		,  '9'	 },* /
	{ 0 		   , 0		,  '\0'  }
};
*/

static ALLOC_SECTION_LDATA VK_TO_WCHAR_TABLE aVkToWcharTable[] = 
{
	{  (PVK_TO_WCHARS1)aVkToWch3, 3, sizeof(aVkToWch3[0]) },
//? {  (PVK_TO_WCHARS1)aVkToWch4, 4, sizeof(aVkToWch4[0]) },

//////////////////	  
/*+*/	{  (PVK_TO_WCHARS1)aVkToWch6,6, sizeof(aVkToWch6[0]) },
//////////////////
	
	{  (PVK_TO_WCHARS1)aVkToWch2, 2, sizeof(aVkToWch2[0]) },
//? {  (PVK_TO_WCHARS1)aVkToWch1, 1, sizeof(aVkToWch1[0]) },
	{						NULL, 0, 0					  },
};

//aKeyNames[], aKeyNamesExt[]  - Virtual Scancode to Key Name tables
//Table attributes: Ordered Scan (by scancode), null-terminated
//Only the names of Extended, NumPad, Dead and Non-Printable keys are here.
//(Keys producing printable characters are named by that character)
static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNames[] = 
{
	0x01,	 L"Esc",
	0x0e,	 L"Backspace",
	0x0f,	 L"Tab",
	0x1c,	 L"Enter",
	0x1d,	 L"Ctrl",
	0x2a,	 L"Shift",
	0x36,	 L"Right Shift",
	0x37,	 L"Num *",
	0x38,	 L"Alt",
	0x39,	 L"Space",
	0x3a,	 L"CShack", //former Caps Lock
	0x3b,	 L"F1",
	0x3c,	 L"F2",
	0x3d,	 L"F3",
	0x3e,	 L"F4",
	0x3f,	 L"F5",
	0x40,	 L"F6",
	0x41,	 L"F7",
	0x42,	 L"F8",
	0x43,	 L"F9",
	0x44,	 L"F10",
	0x45,	 L"Pause",
	0x46,	 L"Play/Pause",  //former Scroll Lock
	0x47,	 L"Num 7",
	0x48,	 L"Num 8",
	0x49,	 L"Num 9",
	0x4a,	 L"Num -",
	0x4b,	 L"Num 4",
	0x4c,	 L"Num 5",
	0x4d,	 L"Num 6",
	0x4e,	 L"Num +",
	0x4f,	 L"Num 1",
	0x50,	 L"Num 2",
	0x51,	 L"Num 3",
	0x52,	 L"Num 0",
	0x53,	 L"Num Del",
	0x54,	 L"Sys Req",
	0x57,	 L"F11",
	0x58,	 L"F12",
	0x7c,	 L"F13",
	0x7d,	 L"F14",
	0x7e,	 L"F15",
	0x7f,	 L"F16",
	0x80,	 L"F17",
	0x81,	 L"F18",
	0x82,	 L"F19",
	0x83,	 L"F20",
	0x84,	 L"F21",
	0x85,	 L"F22",
	0x86,	 L"F23",
	0x87,	 L"F24",
	0	,	 NULL
};

static ALLOC_SECTION_LDATA VSC_LPWSTR aKeyNamesExt[] = 
{
	0x1c,	 L"Num Enter",
	0x1d,	 L"Right Ctrl",
	0x35,	 L"Num /",
	0x37,	 L"Prnt Scrn",
	0x38,	 L"Right Alt",
	0x45,	 L"Mute", //former Num Lock
	0x46,	 L"Break",
	0x47,	 L"Home",
	0x48,	 L"Up",
	0x49,	 L"Page Up",
	0x4b,	 L"Left",
	0x4d,	 L"Right",
	0x4f,	 L"End",
	0x50,	 L"Down",
	0x51,	 L"Page Down",
	0x52,	 L"Insert",
	0x53,	 L"Delete",
	0x54,	 L"<00>",
	0x56,	 L"Help",
	0x5b,	 L"Left Windows",

#ifdef PRESERVE_RIGHT_WIN
	0x5c,	 L"Right Windows", 
#else
	0x5c,	 L"CShack", 
#endif

	0x5d,	 L"Application",
	0	,	 NULL
};


static ALLOC_SECTION_LDATA KBDTABLES KbdTables = 
{
	//Modifier keys
	&CharModifiers,

	//Characters tables
	aVkToWcharTable,

	//Diacritics
	NULL,

	//Names of Keys
	aKeyNames,
	aKeyNamesExt,
	NULL,

	//Scan codes to Virtual Keys
	ausVK,
	sizeof(ausVK) / sizeof(ausVK[0]),
	aE0VscToVk,
	aE1VscToVk,

	//Locale-specific special processing
	MAKELONG(0,KBD_VERSION),

	//Ligatures
	0,
	0,
	NULL
};


KBDTABLES * __ptr64 KbdLayerDescriptor(VOID)
{
	return &KbdTables;
}
