ConsoleKeyMapping.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. namespace Terminal.Gui.ConsoleDrivers {
  6. /// <summary>
  7. /// Helper class to handle the scan code and virtual key from a <see cref="ConsoleKey"/>.
  8. /// </summary>
  9. public static class ConsoleKeyMapping {
  10. class ScanCodeMapping : IEquatable<ScanCodeMapping> {
  11. public uint ScanCode;
  12. public uint VirtualKey;
  13. public ConsoleModifiers Modifiers;
  14. public uint UnicodeChar;
  15. public ScanCodeMapping (uint scanCode, uint virtualKey, ConsoleModifiers modifiers, uint unicodeChar)
  16. {
  17. ScanCode = scanCode;
  18. VirtualKey = virtualKey;
  19. Modifiers = modifiers;
  20. UnicodeChar = unicodeChar;
  21. }
  22. public bool Equals (ScanCodeMapping other)
  23. {
  24. return ScanCode.Equals (other.ScanCode) &&
  25. VirtualKey.Equals (other.VirtualKey) &&
  26. Modifiers.Equals (other.Modifiers) &&
  27. UnicodeChar.Equals (other.UnicodeChar);
  28. }
  29. }
  30. static ConsoleModifiers GetModifiers (ConsoleModifiers modifiers)
  31. {
  32. if (modifiers.HasFlag (ConsoleModifiers.Shift)
  33. && !modifiers.HasFlag (ConsoleModifiers.Alt)
  34. && !modifiers.HasFlag (ConsoleModifiers.Control)) {
  35. return ConsoleModifiers.Shift;
  36. } else if (modifiers == (ConsoleModifiers.Alt | ConsoleModifiers.Control)) {
  37. return modifiers;
  38. }
  39. return 0;
  40. }
  41. static ScanCodeMapping GetScanCode (string propName, uint keyValue, ConsoleModifiers modifiers)
  42. {
  43. switch (propName) {
  44. case "UnicodeChar":
  45. var sCode = scanCodes.FirstOrDefault ((e) => e.UnicodeChar == keyValue && e.Modifiers == modifiers);
  46. if (sCode == null && modifiers == (ConsoleModifiers.Alt | ConsoleModifiers.Control)) {
  47. return scanCodes.FirstOrDefault ((e) => e.UnicodeChar == keyValue && e.Modifiers == 0);
  48. }
  49. return sCode;
  50. case "VirtualKey":
  51. sCode = scanCodes.FirstOrDefault ((e) => e.VirtualKey == keyValue && e.Modifiers == modifiers);
  52. if (sCode == null && modifiers == (ConsoleModifiers.Alt | ConsoleModifiers.Control)) {
  53. return scanCodes.FirstOrDefault ((e) => e.VirtualKey == keyValue && e.Modifiers == 0);
  54. }
  55. return sCode;
  56. }
  57. return null;
  58. }
  59. /// <summary>
  60. /// Gets the <see cref="ConsoleKey"/> from the provided <see cref="KeyCode"/>.
  61. /// </summary>
  62. /// <param name="key"></param>
  63. /// <returns></returns>
  64. public static ConsoleKeyInfo GetConsoleKeyFromKey (KeyCode key)
  65. {
  66. var mod = new ConsoleModifiers ();
  67. if (key.HasFlag (KeyCode.ShiftMask)) {
  68. mod |= ConsoleModifiers.Shift;
  69. }
  70. if (key.HasFlag (KeyCode.AltMask)) {
  71. mod |= ConsoleModifiers.Alt;
  72. }
  73. if (key.HasFlag (KeyCode.CtrlMask)) {
  74. mod |= ConsoleModifiers.Control;
  75. }
  76. return GetConsoleKeyFromKey ((uint)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), mod, out _);
  77. }
  78. /// <summary>
  79. /// Get the <see cref="ConsoleKeyInfo"/> from a unicode character and modifiers (e.g. (Key)'a' and (Key)Key.CtrlMask).
  80. /// </summary>
  81. /// <param name="keyValue">The key as a unicode codepoint.</param>
  82. /// <param name="modifiers">The modifier keys.</param>
  83. /// <param name="scanCode">The resulting scan code.</param>
  84. /// <returns>The <see cref="ConsoleKeyInfo"/>.</returns>
  85. public static ConsoleKeyInfo GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifiers, out uint scanCode)
  86. {
  87. scanCode = 0;
  88. uint outputChar = keyValue;
  89. if (keyValue == 0) {
  90. return new ConsoleKeyInfo ((char)keyValue, ConsoleKey.None, modifiers.HasFlag (ConsoleModifiers.Shift),
  91. modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control));
  92. }
  93. uint consoleKey = (uint)MapKeyToConsoleKey ((KeyCode)keyValue, modifiers, out bool mappable);
  94. if (mappable) {
  95. var mod = GetModifiers (modifiers);
  96. var scode = GetScanCode ("UnicodeChar", keyValue, mod);
  97. if (scode != null) {
  98. consoleKey = scode.VirtualKey;
  99. scanCode = scode.ScanCode;
  100. outputChar = scode.UnicodeChar;
  101. } else {
  102. // If the consoleKey is < 255, retain the lower 8 bits of the key value and set the upper bits to 0xff.
  103. // This is a shifted value that will be used by the GetKeyCharFromConsoleKey to do the correct action
  104. // because keyValue maybe a UnicodeChar or a ConsoleKey, e.g. for PageUp is passed the ConsoleKey.PageUp
  105. consoleKey = consoleKey < 0xff ? consoleKey & 0xff | 0xff << 8 : consoleKey;
  106. outputChar = GetKeyCharFromConsoleKey (consoleKey, modifiers, out consoleKey, out scanCode);
  107. }
  108. } else {
  109. var mod = GetModifiers (modifiers);
  110. var scode = GetScanCode ("VirtualKey", consoleKey, mod);
  111. if (scode != null) {
  112. consoleKey = scode.VirtualKey;
  113. scanCode = scode.ScanCode;
  114. outputChar = scode.UnicodeChar;
  115. }
  116. }
  117. return new ConsoleKeyInfo ((char)outputChar, (ConsoleKey)consoleKey, modifiers.HasFlag (ConsoleModifiers.Shift),
  118. modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control));
  119. }
  120. /// <summary>
  121. /// Get the output character from the <see cref="ConsoleKey"/>, the correct <see cref="ConsoleKey"/>
  122. /// and the scan code used on <see cref="WindowsDriver"/>.
  123. /// </summary>
  124. /// <param name="unicodeChar">The unicode character.</param>
  125. /// <param name="modifiers">The modifiers keys.</param>
  126. /// <param name="consoleKey">The resulting console key.</param>
  127. /// <param name="scanCode">The resulting scan code.</param>
  128. /// <returns>The output character or the <paramref name="consoleKey"/>.</returns>
  129. static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers modifiers, out uint consoleKey, out uint scanCode)
  130. {
  131. uint decodedChar = unicodeChar >> 8 == 0xff ? unicodeChar & 0xff : unicodeChar;
  132. uint keyChar = decodedChar;
  133. consoleKey = 0;
  134. var mod = GetModifiers (modifiers);
  135. scanCode = 0;
  136. var scode = unicodeChar != 0 && unicodeChar >> 8 != 0xff ? GetScanCode ("VirtualKey", decodedChar, mod) : null;
  137. if (scode != null) {
  138. consoleKey = scode.VirtualKey;
  139. keyChar = scode.UnicodeChar;
  140. scanCode = scode.ScanCode;
  141. }
  142. if (scode == null) {
  143. scode = unicodeChar != 0 ? GetScanCode ("UnicodeChar", decodedChar, mod) : null;
  144. if (scode != null) {
  145. consoleKey = scode.VirtualKey;
  146. keyChar = scode.UnicodeChar;
  147. scanCode = scode.ScanCode;
  148. }
  149. }
  150. if (decodedChar != 0 && scanCode == 0 && char.IsLetter ((char)decodedChar)) {
  151. string stFormD = ((char)decodedChar).ToString ().Normalize (System.Text.NormalizationForm.FormD);
  152. for (int i = 0; i < stFormD.Length; i++) {
  153. var uc = CharUnicodeInfo.GetUnicodeCategory (stFormD [i]);
  154. if (uc != UnicodeCategory.NonSpacingMark && uc != UnicodeCategory.OtherLetter) {
  155. consoleKey = char.ToUpper (stFormD [i]);
  156. scode = GetScanCode ("VirtualKey", char.ToUpper (stFormD [i]), 0);
  157. if (scode != null) {
  158. scanCode = scode.ScanCode;
  159. }
  160. }
  161. }
  162. }
  163. return keyChar;
  164. }
  165. /// <summary>
  166. /// Maps a unicode character (e.g. (Key)'a') to a uint representing a <see cref="ConsoleKey"/>.
  167. /// </summary>
  168. /// <param name="keyValue">The key value.</param>
  169. /// <param name="modifiers">The modifiers keys.</param>
  170. /// <param name="isMappable">
  171. /// <see langword="true"/> means the return value can be mapped to a valid unicode character.
  172. /// <see langword="false"/> means the return value is in the ConsoleKey enum.
  173. /// </param>
  174. /// <returns>The <see cref="ConsoleKey"/> or the <paramref name="keyValue"/>.</returns>
  175. public static ConsoleKey MapKeyToConsoleKey (KeyCode keyValue, ConsoleModifiers modifiers, out bool isMappable)
  176. {
  177. isMappable = false;
  178. switch (keyValue) {
  179. case KeyCode.Delete:
  180. return ConsoleKey.Delete;
  181. case KeyCode.CursorUp:
  182. return ConsoleKey.UpArrow;
  183. case KeyCode.CursorDown:
  184. return ConsoleKey.DownArrow;
  185. case KeyCode.CursorLeft:
  186. return ConsoleKey.LeftArrow;
  187. case KeyCode.CursorRight:
  188. return ConsoleKey.RightArrow;
  189. case KeyCode.PageUp:
  190. return ConsoleKey.PageUp;
  191. case KeyCode.PageDown:
  192. return ConsoleKey.PageDown;
  193. case KeyCode.Home:
  194. return ConsoleKey.Home;
  195. case KeyCode.End:
  196. return ConsoleKey.End;
  197. case KeyCode.InsertChar:
  198. return ConsoleKey.Insert;
  199. case KeyCode.DeleteChar:
  200. return ConsoleKey.Delete;
  201. case KeyCode.F1:
  202. return ConsoleKey.F1;
  203. case KeyCode.F2:
  204. return ConsoleKey.F2;
  205. case KeyCode.F3:
  206. return ConsoleKey.F3;
  207. case KeyCode.F4:
  208. return ConsoleKey.F4;
  209. case KeyCode.F5:
  210. return ConsoleKey.F5;
  211. case KeyCode.F6:
  212. return ConsoleKey.F6;
  213. case KeyCode.F7:
  214. return ConsoleKey.F7;
  215. case KeyCode.F8:
  216. return ConsoleKey.F8;
  217. case KeyCode.F9:
  218. return ConsoleKey.F9;
  219. case KeyCode.F10:
  220. return ConsoleKey.F10;
  221. case KeyCode.F11:
  222. return ConsoleKey.F11;
  223. case KeyCode.F12:
  224. return ConsoleKey.F12;
  225. case KeyCode.F13:
  226. return ConsoleKey.F13;
  227. case KeyCode.F14:
  228. return ConsoleKey.F14;
  229. case KeyCode.F15:
  230. return ConsoleKey.F15;
  231. case KeyCode.F16:
  232. return ConsoleKey.F16;
  233. case KeyCode.F17:
  234. return ConsoleKey.F17;
  235. case KeyCode.F18:
  236. return ConsoleKey.F18;
  237. case KeyCode.F19:
  238. return ConsoleKey.F19;
  239. case KeyCode.F20:
  240. return ConsoleKey.F20;
  241. case KeyCode.F21:
  242. return ConsoleKey.F21;
  243. case KeyCode.F22:
  244. return ConsoleKey.F22;
  245. case KeyCode.F23:
  246. return ConsoleKey.F23;
  247. case KeyCode.F24:
  248. return ConsoleKey.F24;
  249. case KeyCode.Tab | KeyCode.ShiftMask:
  250. return ConsoleKey.Tab;
  251. case KeyCode.Unknown:
  252. isMappable = true;
  253. return 0;
  254. }
  255. isMappable = true;
  256. if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= KeyCode.A and <= KeyCode.Z) {
  257. return (ConsoleKey)(keyValue - 32);
  258. } else if (modifiers == ConsoleModifiers.None && keyValue is >= KeyCode.A and <= KeyCode.Z) {
  259. return (ConsoleKey)(keyValue + 32);
  260. }
  261. if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= (KeyCode)'À' and <= (KeyCode)'Ý') {
  262. return (ConsoleKey)(keyValue - 32);
  263. } else if (modifiers == ConsoleModifiers.None && keyValue is >= (KeyCode)'À' and <= (KeyCode)'Ý') {
  264. return (ConsoleKey)(keyValue + 32);
  265. }
  266. return (ConsoleKey)keyValue;
  267. }
  268. /// <summary>
  269. /// Maps a <see cref="ConsoleKey"/> to a <see cref="KeyCode"/>.
  270. /// </summary>
  271. /// <param name="consoleKey">The console key.</param>
  272. /// <param name="isMappable">If <see langword="true"/> is mapped to a valid character, otherwise <see langword="false"/>.</param>
  273. /// <returns>The <see cref="KeyCode"/> or the <paramref name="consoleKey"/>.</returns>
  274. public static KeyCode MapConsoleKeyToKey (ConsoleKey consoleKey, out bool isMappable)
  275. {
  276. isMappable = false;
  277. switch (consoleKey) {
  278. case ConsoleKey.Delete:
  279. return KeyCode.Delete;
  280. case ConsoleKey.UpArrow:
  281. return KeyCode.CursorUp;
  282. case ConsoleKey.DownArrow:
  283. return KeyCode.CursorDown;
  284. case ConsoleKey.LeftArrow:
  285. return KeyCode.CursorLeft;
  286. case ConsoleKey.RightArrow:
  287. return KeyCode.CursorRight;
  288. case ConsoleKey.PageUp:
  289. return KeyCode.PageUp;
  290. case ConsoleKey.PageDown:
  291. return KeyCode.PageDown;
  292. case ConsoleKey.Home:
  293. return KeyCode.Home;
  294. case ConsoleKey.End:
  295. return KeyCode.End;
  296. case ConsoleKey.Insert:
  297. return KeyCode.InsertChar;
  298. case ConsoleKey.F1:
  299. return KeyCode.F1;
  300. case ConsoleKey.F2:
  301. return KeyCode.F2;
  302. case ConsoleKey.F3:
  303. return KeyCode.F3;
  304. case ConsoleKey.F4:
  305. return KeyCode.F4;
  306. case ConsoleKey.F5:
  307. return KeyCode.F5;
  308. case ConsoleKey.F6:
  309. return KeyCode.F6;
  310. case ConsoleKey.F7:
  311. return KeyCode.F7;
  312. case ConsoleKey.F8:
  313. return KeyCode.F8;
  314. case ConsoleKey.F9:
  315. return KeyCode.F9;
  316. case ConsoleKey.F10:
  317. return KeyCode.F10;
  318. case ConsoleKey.F11:
  319. return KeyCode.F11;
  320. case ConsoleKey.F12:
  321. return KeyCode.F12;
  322. case ConsoleKey.F13:
  323. return KeyCode.F13;
  324. case ConsoleKey.F14:
  325. return KeyCode.F14;
  326. case ConsoleKey.F15:
  327. return KeyCode.F15;
  328. case ConsoleKey.F16:
  329. return KeyCode.F16;
  330. case ConsoleKey.F17:
  331. return KeyCode.F17;
  332. case ConsoleKey.F18:
  333. return KeyCode.F18;
  334. case ConsoleKey.F19:
  335. return KeyCode.F19;
  336. case ConsoleKey.F20:
  337. return KeyCode.F20;
  338. case ConsoleKey.F21:
  339. return KeyCode.F21;
  340. case ConsoleKey.F22:
  341. return KeyCode.F22;
  342. case ConsoleKey.F23:
  343. return KeyCode.F23;
  344. case ConsoleKey.F24:
  345. return KeyCode.F24;
  346. case ConsoleKey.Tab:
  347. return KeyCode.Tab;
  348. }
  349. isMappable = true;
  350. if (consoleKey is >= ConsoleKey.A and <= ConsoleKey.Z) {
  351. return (KeyCode)(consoleKey + 32);
  352. }
  353. return (KeyCode)consoleKey;
  354. }
  355. /// <summary>
  356. /// Maps a <see cref="ConsoleKeyInfo"/> to a <see cref="KeyCode"/>.
  357. /// </summary>
  358. /// <param name="keyInfo">The console key info.</param>
  359. /// <param name="key">The key.</param>
  360. /// <returns>The <see cref="KeyCode"/> with <see cref="ConsoleModifiers"/> or the <paramref name="key"/></returns>
  361. public static KeyCode MapKeyModifiers (ConsoleKeyInfo keyInfo, KeyCode key)
  362. {
  363. var keyMod = new KeyCode ();
  364. if ((keyInfo.Modifiers & ConsoleModifiers.Shift) != 0) {
  365. keyMod = KeyCode.ShiftMask;
  366. }
  367. if ((keyInfo.Modifiers & ConsoleModifiers.Control) != 0) {
  368. keyMod |= KeyCode.CtrlMask;
  369. }
  370. if ((keyInfo.Modifiers & ConsoleModifiers.Alt) != 0) {
  371. keyMod |= KeyCode.AltMask;
  372. }
  373. return keyMod != KeyCode.Null ? keyMod | key : key;
  374. }
  375. static HashSet<ScanCodeMapping> scanCodes = new HashSet<ScanCodeMapping> {
  376. new ScanCodeMapping (1, 27, 0, 27), // Escape
  377. new ScanCodeMapping (1, 27, ConsoleModifiers.Shift, 27),
  378. new ScanCodeMapping (2, 49, 0, 49), // D1
  379. new ScanCodeMapping (2, 49, ConsoleModifiers.Shift, 33),
  380. new ScanCodeMapping (3, 50, 0, 50), // D2
  381. new ScanCodeMapping (3, 50, ConsoleModifiers.Shift, 34),
  382. new ScanCodeMapping (3, 50, ConsoleModifiers.Alt | ConsoleModifiers.Control, 64),
  383. new ScanCodeMapping (4, 51, 0, 51), // D3
  384. new ScanCodeMapping (4, 51, ConsoleModifiers.Shift, 35),
  385. new ScanCodeMapping (4, 51, ConsoleModifiers.Alt | ConsoleModifiers.Control, 163),
  386. new ScanCodeMapping (5, 52, 0, 52), // D4
  387. new ScanCodeMapping (5, 52, ConsoleModifiers.Shift, 36),
  388. new ScanCodeMapping (5, 52, ConsoleModifiers.Alt | ConsoleModifiers.Control, 167),
  389. new ScanCodeMapping (6, 53, 0, 53), // D5
  390. new ScanCodeMapping (6, 53, ConsoleModifiers.Shift, 37),
  391. new ScanCodeMapping (6, 53, ConsoleModifiers.Alt | ConsoleModifiers.Control, 8364),
  392. new ScanCodeMapping (7, 54, 0, 54), // D6
  393. new ScanCodeMapping (7, 54, ConsoleModifiers.Shift, 38),
  394. new ScanCodeMapping (8, 55, 0, 55), // D7
  395. new ScanCodeMapping (8, 55, ConsoleModifiers.Shift, 47),
  396. new ScanCodeMapping (8, 55, ConsoleModifiers.Alt | ConsoleModifiers.Control, 123),
  397. new ScanCodeMapping (9, 56, 0, 56), // D8
  398. new ScanCodeMapping (9, 56, ConsoleModifiers.Shift, 40),
  399. new ScanCodeMapping (9, 56, ConsoleModifiers.Alt | ConsoleModifiers.Control, 91),
  400. new ScanCodeMapping (10, 57, 0, 57), // D9
  401. new ScanCodeMapping (10, 57, ConsoleModifiers.Shift, 41),
  402. new ScanCodeMapping (10, 57, ConsoleModifiers.Alt | ConsoleModifiers.Control, 93),
  403. new ScanCodeMapping (11, 48, 0, 48), // D0
  404. new ScanCodeMapping (11, 48, ConsoleModifiers.Shift, 61),
  405. new ScanCodeMapping (11, 48, ConsoleModifiers.Alt | ConsoleModifiers.Control, 125),
  406. new ScanCodeMapping (12, 219, 0, 39), // Oem4
  407. new ScanCodeMapping (12, 219, ConsoleModifiers.Shift, 63),
  408. new ScanCodeMapping (13, 221, 0, 171), // Oem6
  409. new ScanCodeMapping (13, 221, ConsoleModifiers.Shift, 187),
  410. new ScanCodeMapping (14, 8, 0, 8), // Backspace
  411. new ScanCodeMapping (14, 8, ConsoleModifiers.Shift, 8),
  412. new ScanCodeMapping (15, 9, 0, 9), // Tab
  413. new ScanCodeMapping (15, 9, ConsoleModifiers.Shift, 15),
  414. new ScanCodeMapping (16, 81, 0, 113), // Q
  415. new ScanCodeMapping (16, 81, ConsoleModifiers.Shift, 81),
  416. new ScanCodeMapping (17, 87, 0, 119), // W
  417. new ScanCodeMapping (17, 87, ConsoleModifiers.Shift, 87),
  418. new ScanCodeMapping (18, 69, 0, 101), // E
  419. new ScanCodeMapping (18, 69, ConsoleModifiers.Shift, 69),
  420. new ScanCodeMapping (19, 82, 0, 114), // R
  421. new ScanCodeMapping (19, 82, ConsoleModifiers.Shift, 82),
  422. new ScanCodeMapping (20, 84, 0, 116), // T
  423. new ScanCodeMapping (20, 84, ConsoleModifiers.Shift, 84),
  424. new ScanCodeMapping (21, 89, 0, 121), // Y
  425. new ScanCodeMapping (21, 89, ConsoleModifiers.Shift, 89),
  426. new ScanCodeMapping (22, 85, 0, 117), // U
  427. new ScanCodeMapping (22, 85, ConsoleModifiers.Shift, 85),
  428. new ScanCodeMapping (23, 73, 0, 105), // I
  429. new ScanCodeMapping (23, 73, ConsoleModifiers.Shift, 73),
  430. new ScanCodeMapping (24, 79, 0, 111), // O
  431. new ScanCodeMapping (24, 79, ConsoleModifiers.Shift, 79),
  432. new ScanCodeMapping (25, 80, 0, 112), // P
  433. new ScanCodeMapping (25, 80, ConsoleModifiers.Shift, 80),
  434. new ScanCodeMapping (26, 187, 0, 43), // OemPlus
  435. new ScanCodeMapping (26, 187, ConsoleModifiers.Shift, 42),
  436. new ScanCodeMapping (26, 187, ConsoleModifiers.Alt | ConsoleModifiers.Control, 168),
  437. new ScanCodeMapping (27, 186, 0, 180), // Oem1
  438. new ScanCodeMapping (27, 186, ConsoleModifiers.Shift, 96),
  439. new ScanCodeMapping (28, 13, 0, 13), // Enter
  440. new ScanCodeMapping (28, 13, ConsoleModifiers.Shift, 13),
  441. new ScanCodeMapping (29, 17, 0, 0), // Control
  442. new ScanCodeMapping (29, 17, ConsoleModifiers.Shift, 0),
  443. new ScanCodeMapping (scanCode: 30, virtualKey: 65, modifiers: 0, unicodeChar: 97), // VK = A, UC = 'a'
  444. new ScanCodeMapping (30, 65, ConsoleModifiers.Shift, 65), // VK = A | Shift, UC = 'A'
  445. new ScanCodeMapping (31, 83, 0, 115), // S
  446. new ScanCodeMapping (31, 83, ConsoleModifiers.Shift, 83),
  447. new ScanCodeMapping (32, 68, 0, 100), // D
  448. new ScanCodeMapping (32, 68, ConsoleModifiers.Shift, 68),
  449. new ScanCodeMapping (33, 70, 0, 102), // F
  450. new ScanCodeMapping (33, 70, ConsoleModifiers.Shift, 70),
  451. new ScanCodeMapping (34, 71, 0, 103), // G
  452. new ScanCodeMapping (34, 71, ConsoleModifiers.Shift, 71),
  453. new ScanCodeMapping (35, 72, 0, 104), // H
  454. new ScanCodeMapping (35, 72, ConsoleModifiers.Shift, 72),
  455. new ScanCodeMapping (36, 74, 0, 106), // J
  456. new ScanCodeMapping (36, 74, ConsoleModifiers.Shift, 74),
  457. new ScanCodeMapping (37, 75, 0, 107), // K
  458. new ScanCodeMapping (37, 75, ConsoleModifiers.Shift, 75),
  459. new ScanCodeMapping (38, 76, 0, 108), // L
  460. new ScanCodeMapping (38, 76, ConsoleModifiers.Shift, 76),
  461. new ScanCodeMapping (39, 192, 0, 231), // Oem3
  462. new ScanCodeMapping (39, 192, ConsoleModifiers.Shift, 199),
  463. new ScanCodeMapping (40, 222, 0, 186), // Oem7
  464. new ScanCodeMapping (40, 222, ConsoleModifiers.Shift, 170),
  465. new ScanCodeMapping (41, 220, 0, 92), // Oem5
  466. new ScanCodeMapping (41, 220, ConsoleModifiers.Shift, 124),
  467. new ScanCodeMapping (42, 16, 0, 0), // LShift
  468. new ScanCodeMapping (42, 16, ConsoleModifiers.Shift, 0),
  469. new ScanCodeMapping (43, 191, 0, 126), // Oem2
  470. new ScanCodeMapping (43, 191, ConsoleModifiers.Shift, 94),
  471. new ScanCodeMapping (44, 90, 0, 122), // Z
  472. new ScanCodeMapping (44, 90, ConsoleModifiers.Shift, 90),
  473. new ScanCodeMapping (45, 88, 0, 120), // X
  474. new ScanCodeMapping (45, 88, ConsoleModifiers.Shift, 88),
  475. new ScanCodeMapping (46, 67, 0, 99), // C
  476. new ScanCodeMapping (46, 67, ConsoleModifiers.Shift, 67),
  477. new ScanCodeMapping (47, 86, 0, 118), // V
  478. new ScanCodeMapping (47, 86, ConsoleModifiers.Shift, 86),
  479. new ScanCodeMapping (48, 66, 0, 98), // B
  480. new ScanCodeMapping (48, 66, ConsoleModifiers.Shift, 66),
  481. new ScanCodeMapping (49, 78, 0, 110), // N
  482. new ScanCodeMapping (49, 78, ConsoleModifiers.Shift, 78),
  483. new ScanCodeMapping (50, 77, 0, 109), // M
  484. new ScanCodeMapping (50, 77, ConsoleModifiers.Shift, 77),
  485. new ScanCodeMapping (51, 188, 0, 44), // OemComma
  486. new ScanCodeMapping (51, 188, ConsoleModifiers.Shift, 59),
  487. new ScanCodeMapping (52, 190, 0, 46), // OemPeriod
  488. new ScanCodeMapping (52, 190, ConsoleModifiers.Shift, 58),
  489. new ScanCodeMapping (53, 189, 0, 45), // OemMinus
  490. new ScanCodeMapping (53, 189, ConsoleModifiers.Shift, 95),
  491. new ScanCodeMapping (54, 16, 0, 0), // RShift
  492. new ScanCodeMapping (54, 16, ConsoleModifiers.Shift, 0),
  493. new ScanCodeMapping (55, 44, 0, 0), // PrintScreen
  494. new ScanCodeMapping (55, 44, ConsoleModifiers.Shift, 0),
  495. new ScanCodeMapping (56, 18, 0, 0), // Alt
  496. new ScanCodeMapping (56, 18, ConsoleModifiers.Shift, 0),
  497. new ScanCodeMapping (57, 32, 0, 32), // Spacebar
  498. new ScanCodeMapping (57, 32, ConsoleModifiers.Shift, 32),
  499. new ScanCodeMapping (58, 20, 0, 0), // Caps
  500. new ScanCodeMapping (58, 20, ConsoleModifiers.Shift, 0),
  501. new ScanCodeMapping (59, 112, 0, 0), // F1
  502. new ScanCodeMapping (59, 112, ConsoleModifiers.Shift, 0),
  503. new ScanCodeMapping (60, 113, 0, 0), // F2
  504. new ScanCodeMapping (60, 113, ConsoleModifiers.Shift, 0),
  505. new ScanCodeMapping (61, 114, 0, 0), // F3
  506. new ScanCodeMapping (61, 114, ConsoleModifiers.Shift, 0),
  507. new ScanCodeMapping (62, 115, 0, 0), // F4
  508. new ScanCodeMapping (62, 115, ConsoleModifiers.Shift, 0),
  509. new ScanCodeMapping (63, 116, 0, 0), // F5
  510. new ScanCodeMapping (63, 116, ConsoleModifiers.Shift, 0),
  511. new ScanCodeMapping (64, 117, 0, 0), // F6
  512. new ScanCodeMapping (64, 117, ConsoleModifiers.Shift, 0),
  513. new ScanCodeMapping (65, 118, 0, 0), // F7
  514. new ScanCodeMapping (65, 118, ConsoleModifiers.Shift, 0),
  515. new ScanCodeMapping (66, 119, 0, 0), // F8
  516. new ScanCodeMapping (66, 119, ConsoleModifiers.Shift, 0),
  517. new ScanCodeMapping (67, 120, 0, 0), // F9
  518. new ScanCodeMapping (67, 120, ConsoleModifiers.Shift, 0),
  519. new ScanCodeMapping (68, 121, 0, 0), // F10
  520. new ScanCodeMapping (68, 121, ConsoleModifiers.Shift, 0),
  521. new ScanCodeMapping (69, 144, 0, 0), // Num
  522. new ScanCodeMapping (69, 144, ConsoleModifiers.Shift, 0),
  523. new ScanCodeMapping (70, 145, 0, 0), // Scroll
  524. new ScanCodeMapping (70, 145, ConsoleModifiers.Shift, 0),
  525. new ScanCodeMapping (71, 36, 0, 0), // Home
  526. new ScanCodeMapping (71, 36, ConsoleModifiers.Shift, 0),
  527. new ScanCodeMapping (72, 38, 0, 0), // UpArrow
  528. new ScanCodeMapping (72, 38, ConsoleModifiers.Shift, 0),
  529. new ScanCodeMapping (73, 33, 0, 0), // PageUp
  530. new ScanCodeMapping (73, 33, ConsoleModifiers.Shift, 0),
  531. new ScanCodeMapping (74, 109, 0, 45), // Subtract
  532. new ScanCodeMapping (74, 109, ConsoleModifiers.Shift, 45),
  533. new ScanCodeMapping (75, 37, 0, 0), // LeftArrow
  534. new ScanCodeMapping (75, 37, ConsoleModifiers.Shift, 0),
  535. new ScanCodeMapping (76, 12, 0, 0), // Center
  536. new ScanCodeMapping (76, 12, ConsoleModifiers.Shift, 0),
  537. new ScanCodeMapping (77, 39, 0, 0), // RightArrow
  538. new ScanCodeMapping (77, 39, ConsoleModifiers.Shift, 0),
  539. new ScanCodeMapping (78, 107, 0, 43), // Add
  540. new ScanCodeMapping (78, 107, ConsoleModifiers.Shift, 43),
  541. new ScanCodeMapping (79, 35, 0, 0), // End
  542. new ScanCodeMapping (79, 35, ConsoleModifiers.Shift, 0),
  543. new ScanCodeMapping (80, 40, 0, 0), // DownArrow
  544. new ScanCodeMapping (80, 40, ConsoleModifiers.Shift, 0),
  545. new ScanCodeMapping (81, 34, 0, 0), // PageDown
  546. new ScanCodeMapping (81, 34, ConsoleModifiers.Shift, 0),
  547. new ScanCodeMapping (82, 45, 0, 0), // Insert
  548. new ScanCodeMapping (82, 45, ConsoleModifiers.Shift, 0),
  549. new ScanCodeMapping (83, 46, 0, 0), // Delete
  550. new ScanCodeMapping (83, 46, ConsoleModifiers.Shift, 0),
  551. new ScanCodeMapping (86, 226, 0, 60), // OEM 102
  552. new ScanCodeMapping (86, 226, ConsoleModifiers.Shift, 62),
  553. new ScanCodeMapping (87, 122, 0, 0), // F11
  554. new ScanCodeMapping (87, 122, ConsoleModifiers.Shift, 0),
  555. new ScanCodeMapping (88, 123, 0, 0), // F12
  556. new ScanCodeMapping (88, 123, ConsoleModifiers.Shift, 0)
  557. };
  558. /// <summary>
  559. /// Decode a <see cref="ConsoleKeyInfo"/> that is using <see cref="ConsoleKey.Packet"/>.
  560. /// </summary>
  561. /// <param name="consoleKeyInfo">The console key info.</param>
  562. /// <returns>The decoded <see cref="ConsoleKeyInfo"/> or the <paramref name="consoleKeyInfo"/>.</returns>
  563. /// <remarks>If it's a <see cref="ConsoleKey.Packet"/> the <see cref="ConsoleKeyInfo.KeyChar"/> may be
  564. /// a <see cref="ConsoleKeyInfo.Key"/> or a <see cref="ConsoleKeyInfo.KeyChar"/> value.
  565. /// </remarks>
  566. public static ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
  567. {
  568. if (consoleKeyInfo.Key != ConsoleKey.Packet) {
  569. return consoleKeyInfo;
  570. }
  571. return GetConsoleKeyFromKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out _);
  572. }
  573. }
  574. }