diff --git a/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs b/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs index bab26eb32f..3c9d00da27 100644 --- a/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs +++ b/Terminal.Gui/ConsoleDrivers/ConsoleKeyMapping.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using static Terminal.Gui.WindowsConsole; -using System.Text; namespace Terminal.Gui.ConsoleDrivers { /// @@ -33,7 +31,7 @@ public bool Equals (ScanCodeMapping other) } } - static ConsoleModifiers GetModifiers (uint unicodeChar, ConsoleModifiers modifiers, bool isConsoleKey) + static ConsoleModifiers GetModifiers (ConsoleModifiers modifiers) { if (modifiers.HasFlag (ConsoleModifiers.Shift) && !modifiers.HasFlag (ConsoleModifiers.Alt) @@ -41,14 +39,8 @@ static ConsoleModifiers GetModifiers (uint unicodeChar, ConsoleModifiers modifie return ConsoleModifiers.Shift; } else if (modifiers == (ConsoleModifiers.Alt | ConsoleModifiers.Control)) { return modifiers; - } else if ((!isConsoleKey || modifiers.HasFlag (ConsoleModifiers.Shift) - || modifiers.HasFlag (ConsoleModifiers.Alt) - || modifiers.HasFlag (ConsoleModifiers.Control)) - && unicodeChar >= (uint)ConsoleKey.A && unicodeChar <= (uint)ConsoleKey.Z) { - // BUGBUG: I think this is the bug. We should not be adding shift to ConsoleKey.A as it should - // result in unicodeChar of 97 ('a') - return ConsoleModifiers.Shift; } + return 0; } @@ -77,7 +69,7 @@ static ScanCodeMapping GetScanCode (string propName, uint keyValue, ConsoleModif /// /// /// - public static ConsoleKey GetConsoleKeyFromKey (KeyCode key) + public static ConsoleKeyInfo GetConsoleKeyFromKey (KeyCode key) { var mod = new ConsoleModifiers (); if (key.HasFlag (KeyCode.ShiftMask)) { @@ -89,28 +81,28 @@ public static ConsoleKey GetConsoleKeyFromKey (KeyCode key) if (key.HasFlag (KeyCode.CtrlMask)) { mod |= ConsoleModifiers.Control; } - return (ConsoleKey)GetConsoleKeyFromKey ((uint)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), mod, out _, out _); + return GetConsoleKeyFromKey ((uint)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), mod, out _); } /// - /// Get the from a unicode character and modifiers (e.g. (Key)'a' and (Key)Key.CtrlMask). + /// Get the from a unicode character and modifiers (e.g. (Key)'a' and (Key)Key.CtrlMask). /// /// The key as a unicode codepoint. /// The modifier keys. /// The resulting scan code. - /// The resulting output character. - /// The or the . - public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifiers, out uint scanCode, out uint outputChar) + /// The . + public static ConsoleKeyInfo GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifiers, out uint scanCode) { scanCode = 0; - outputChar = keyValue; + uint outputChar = keyValue; if (keyValue == 0) { - return 0; + return new ConsoleKeyInfo ((char)keyValue, ConsoleKey.None, modifiers.HasFlag (ConsoleModifiers.Shift), + modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control)); } - uint consoleKey = MapKeyToConsoleKey ((KeyCode)keyValue, out bool mappable); + uint consoleKey = (uint)MapKeyToConsoleKey ((KeyCode)keyValue, modifiers, out bool mappable); if (mappable) { - var mod = GetModifiers (keyValue, modifiers, false); + var mod = GetModifiers (modifiers); var scode = GetScanCode ("UnicodeChar", keyValue, mod); if (scode != null) { consoleKey = scode.VirtualKey; @@ -118,11 +110,13 @@ public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifie outputChar = scode.UnicodeChar; } else { // If the consoleKey is < 255, retain the lower 8 bits of the key value and set the upper bits to 0xff. - // But why???? + // This is a shifted value that will be used by the GetKeyCharFromConsoleKey to do the correct action + // because keyValue maybe a UnicodeChar or a ConsoleKey, e.g. for PageUp is passed the ConsoleKey.PageUp consoleKey = consoleKey < 0xff ? consoleKey & 0xff | 0xff << 8 : consoleKey; + outputChar = GetKeyCharFromConsoleKey (consoleKey, modifiers, out consoleKey, out scanCode); } } else { - var mod = GetModifiers (keyValue, modifiers, false); + var mod = GetModifiers (modifiers); var scode = GetScanCode ("VirtualKey", consoleKey, mod); if (scode != null) { consoleKey = scode.VirtualKey; @@ -131,23 +125,25 @@ public static uint GetConsoleKeyFromKey (uint keyValue, ConsoleModifiers modifie } } - return consoleKey; + return new ConsoleKeyInfo ((char)outputChar, (ConsoleKey)consoleKey, modifiers.HasFlag (ConsoleModifiers.Shift), + modifiers.HasFlag (ConsoleModifiers.Alt), modifiers.HasFlag (ConsoleModifiers.Control)); } /// - /// Get the output character from the . + /// Get the output character from the , the correct + /// and the scan code used on . /// /// The unicode character. /// The modifiers keys. /// The resulting console key. /// The resulting scan code. /// The output character or the . - public static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers modifiers, out uint consoleKey, out uint scanCode) + static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers modifiers, out uint consoleKey, out uint scanCode) { uint decodedChar = unicodeChar >> 8 == 0xff ? unicodeChar & 0xff : unicodeChar; uint keyChar = decodedChar; consoleKey = 0; - var mod = GetModifiers (decodedChar, modifiers, true); + var mod = GetModifiers (modifiers); scanCode = 0; var scode = unicodeChar != 0 && unicodeChar >> 8 != 0xff ? GetScanCode ("VirtualKey", decodedChar, mod) : null; if (scode != null) { @@ -180,93 +176,93 @@ public static uint GetKeyCharFromConsoleKey (uint unicodeChar, ConsoleModifiers return keyChar; } - // BUGBUG: This API should take a Key and return a ConsoleKey, not uints /// /// Maps a unicode character (e.g. (Key)'a') to a uint representing a . /// /// The key value. + /// The modifiers keys. /// /// means the return value can be mapped to a valid unicode character. /// means the return value is in the ConsoleKey enum. /// /// The or the . - public static uint MapKeyToConsoleKey (KeyCode keyValue, out bool isMappable) + public static ConsoleKey MapKeyToConsoleKey (KeyCode keyValue, ConsoleModifiers modifiers, out bool isMappable) { isMappable = false; switch (keyValue) { case KeyCode.Delete: - return (uint)ConsoleKey.Delete; + return ConsoleKey.Delete; case KeyCode.CursorUp: - return (uint)ConsoleKey.UpArrow; + return ConsoleKey.UpArrow; case KeyCode.CursorDown: - return (uint)ConsoleKey.DownArrow; + return ConsoleKey.DownArrow; case KeyCode.CursorLeft: - return (uint)ConsoleKey.LeftArrow; + return ConsoleKey.LeftArrow; case KeyCode.CursorRight: - return (uint)ConsoleKey.RightArrow; + return ConsoleKey.RightArrow; case KeyCode.PageUp: - return (uint)ConsoleKey.PageUp; + return ConsoleKey.PageUp; case KeyCode.PageDown: - return (uint)ConsoleKey.PageDown; + return ConsoleKey.PageDown; case KeyCode.Home: - return (uint)ConsoleKey.Home; + return ConsoleKey.Home; case KeyCode.End: - return (uint)ConsoleKey.End; + return ConsoleKey.End; case KeyCode.InsertChar: - return (uint)ConsoleKey.Insert; + return ConsoleKey.Insert; case KeyCode.DeleteChar: - return (uint)ConsoleKey.Delete; + return ConsoleKey.Delete; case KeyCode.F1: - return (uint)ConsoleKey.F1; + return ConsoleKey.F1; case KeyCode.F2: - return (uint)ConsoleKey.F2; + return ConsoleKey.F2; case KeyCode.F3: - return (uint)ConsoleKey.F3; + return ConsoleKey.F3; case KeyCode.F4: - return (uint)ConsoleKey.F4; + return ConsoleKey.F4; case KeyCode.F5: - return (uint)ConsoleKey.F5; + return ConsoleKey.F5; case KeyCode.F6: - return (uint)ConsoleKey.F6; + return ConsoleKey.F6; case KeyCode.F7: - return (uint)ConsoleKey.F7; + return ConsoleKey.F7; case KeyCode.F8: - return (uint)ConsoleKey.F8; + return ConsoleKey.F8; case KeyCode.F9: - return (uint)ConsoleKey.F9; + return ConsoleKey.F9; case KeyCode.F10: - return (uint)ConsoleKey.F10; + return ConsoleKey.F10; case KeyCode.F11: - return (uint)ConsoleKey.F11; + return ConsoleKey.F11; case KeyCode.F12: - return (uint)ConsoleKey.F12; + return ConsoleKey.F12; case KeyCode.F13: - return (uint)ConsoleKey.F13; + return ConsoleKey.F13; case KeyCode.F14: - return (uint)ConsoleKey.F14; + return ConsoleKey.F14; case KeyCode.F15: - return (uint)ConsoleKey.F15; + return ConsoleKey.F15; case KeyCode.F16: - return (uint)ConsoleKey.F16; + return ConsoleKey.F16; case KeyCode.F17: - return (uint)ConsoleKey.F17; + return ConsoleKey.F17; case KeyCode.F18: - return (uint)ConsoleKey.F18; + return ConsoleKey.F18; case KeyCode.F19: - return (uint)ConsoleKey.F19; + return ConsoleKey.F19; case KeyCode.F20: - return (uint)ConsoleKey.F20; + return ConsoleKey.F20; case KeyCode.F21: - return (uint)ConsoleKey.F21; + return ConsoleKey.F21; case KeyCode.F22: - return (uint)ConsoleKey.F22; + return ConsoleKey.F22; case KeyCode.F23: - return (uint)ConsoleKey.F23; + return ConsoleKey.F23; case KeyCode.F24: - return (uint)ConsoleKey.F24; + return ConsoleKey.F24; case KeyCode.Tab | KeyCode.ShiftMask: - return (uint)ConsoleKey.Tab; + return ConsoleKey.Tab; case KeyCode.Unknown: isMappable = true; return 0; @@ -274,11 +270,18 @@ public static uint MapKeyToConsoleKey (KeyCode keyValue, out bool isMappable) isMappable = true; - //if (keyValue is >= Key.A and <= Key.Z) { - // return (uint)keyValue + 32; - //} + if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= KeyCode.A and <= KeyCode.Z) { + return (ConsoleKey)(keyValue - 32); + } else if (modifiers == ConsoleModifiers.None && keyValue is >= KeyCode.A and <= KeyCode.Z) { + return (ConsoleKey)(keyValue + 32); + } + if (modifiers == ConsoleModifiers.Shift && keyValue - 32 is >= (KeyCode)'À' and <= (KeyCode)'Ý') { + return (ConsoleKey)(keyValue - 32); + } else if (modifiers == ConsoleModifiers.None && keyValue is >= (KeyCode)'À' and <= (KeyCode)'Ý') { + return (ConsoleKey)(keyValue + 32); + } - return (uint)keyValue; + return (ConsoleKey)keyValue; } /// @@ -579,24 +582,20 @@ public static KeyCode MapKeyModifiers (ConsoleKeyInfo keyInfo, KeyCode key) }; /// - /// + /// Decode a that is using . /// - /// - /// + /// The console key info. + /// The decoded or the . + /// If it's a the may be + /// a or a value. + /// public static ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo) { if (consoleKeyInfo.Key != ConsoleKey.Packet) { return consoleKeyInfo; } - var mod = consoleKeyInfo.Modifiers; - bool shift = (mod & ConsoleModifiers.Shift) != 0; - bool alt = (mod & ConsoleModifiers.Alt) != 0; - bool control = (mod & ConsoleModifiers.Control) != 0; - - uint keyChar = GetKeyCharFromConsoleKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out uint virtualKey, out _); - - return new ConsoleKeyInfo ((char)keyChar, (ConsoleKey)virtualKey, shift, alt, control); + return GetConsoleKeyFromKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out _); } } } \ No newline at end of file diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index f4701aec6b..98181f0699 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -724,10 +724,10 @@ public override void SendKeys (char keyChar, ConsoleKey consoleKey, bool shift, if (control) { mod |= ConsoleModifiers.Control; } - var kchar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (keyChar, mod, out uint ckey, out _); - key = ConsoleKeyMapping.MapConsoleKeyToKey ((ConsoleKey)ckey, out bool mappable); + var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (keyChar, mod, out _); + key = ConsoleKeyMapping.MapConsoleKeyToKey ((ConsoleKey)cKeyInfo.Key, out bool mappable); if (mappable) { - key = (KeyCode)kchar; + key = (KeyCode)cKeyInfo.KeyChar; } } else { key = (KeyCode)keyChar; diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs index e2fcbbfd81..4cec5cb019 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs @@ -800,7 +800,7 @@ public static void PushMockKeyPress (KeyCode key) { MockKeyPresses.Push (new ConsoleKeyInfo ( (char)(key & ~KeyCode.CtrlMask & ~KeyCode.ShiftMask & ~KeyCode.AltMask), - ConsoleKeyMapping.GetConsoleKeyFromKey (key), + ConsoleKeyMapping.GetConsoleKeyFromKey (key).Key, key.HasFlag (KeyCode.ShiftMask), key.HasFlag (KeyCode.AltMask), key.HasFlag (KeyCode.CtrlMask))); diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 14118a51e6..5aaff3439c 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -998,9 +998,9 @@ ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo) var alt = (mod & ConsoleModifiers.Alt) != 0; var control = (mod & ConsoleModifiers.Control) != 0; - var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out uint virtualKey, out _); + var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (consoleKeyInfo.KeyChar, consoleKeyInfo.Modifiers, out _); - return new ConsoleKeyInfo ((char)keyChar, (ConsoleKey)virtualKey, shift, alt, control); + return new ConsoleKeyInfo (cKeyInfo.KeyChar, cKeyInfo.Key, shift, alt, control); } KeyCode MapKey (ConsoleKeyInfo keyInfo) @@ -1082,10 +1082,10 @@ KeyCode MapKey (ConsoleKeyInfo keyInfo) return (KeyCode)((uint)KeyCode.A + delta) | KeyCode.ShiftMask; } } - - if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == KeyCode.Space) { - return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space; - } + // This is buggy because is converting a lower case to a upper case and mustn't + //if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == KeyCode.Space) { + // return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space; + //} return (KeyCode)(uint)keyInfo.KeyChar; } if (key is >= ConsoleKey.D0 and <= ConsoleKey.D9) { diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 30f3966828..b78d0d2dc3 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -379,7 +379,7 @@ public struct KeyEventRecord { [FieldOffset (12), MarshalAs (UnmanagedType.U4)] public ControlKeyState dwControlKeyState; - public override readonly string ToString () => $"[KeyEventRecord({(bKeyDown ? "down" : "up")},{wRepeatCount},{wVirtualKeyCode},{wVirtualScanCode},{new Rune(UnicodeChar).MakePrintable()},{dwControlKeyState})]"; + public override readonly string ToString () => $"[KeyEventRecord({(bKeyDown ? "down" : "up")},{wRepeatCount},{wVirtualKeyCode},{wVirtualScanCode},{new Rune (UnicodeChar).MakePrintable ()},{dwControlKeyState})]"; } [Flags] @@ -617,7 +617,7 @@ public readonly string ToString (ConsoleKeyInfoEx ex) sb.Append ((ex.CapsLock ? "caps," : string.Empty)); sb.Append ((ex.NumLock ? "num," : string.Empty)); sb.Append ((ex.ScrollLock ? "scroll," : string.Empty)); - var s = sb.ToString ().TrimEnd (',').TrimEnd(' '); + var s = sb.ToString ().TrimEnd (',').TrimEnd (' '); return $"[ConsoleKeyInfoEx({s})]"; } } @@ -1005,12 +1005,12 @@ KeyCode MapKey (WindowsConsole.ConsoleKeyInfoEx keyInfoEx) if (((keyInfo.Modifiers == ConsoleModifiers.Shift) ^ (keyInfoEx.CapsLock))) { if (keyInfo.KeyChar <= (uint)KeyCode.Z) { return (KeyCode)((uint)KeyCode.A + delta) | KeyCode.ShiftMask; - } + } } if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) == 0) { return (KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space; - } + } if (((KeyCode)((uint)keyInfo.KeyChar) & KeyCode.Space) != 0) { if (((KeyCode)((uint)keyInfo.KeyChar) & ~KeyCode.Space) == (KeyCode)keyInfo.Key) { @@ -1077,7 +1077,7 @@ internal void ProcessInput (WindowsConsole.InputRecord inputEvent) inputEvent.KeyEvent = FromVKPacketToKeyEventRecord (inputEvent.KeyEvent); } var keyInfo = ToConsoleKeyInfoEx (inputEvent.KeyEvent); - Debug.WriteLine ($"event: {inputEvent.ToString()} {keyInfo.ToString (keyInfo)}"); + Debug.WriteLine ($"event: {inputEvent.ToString ()} {keyInfo.ToString (keyInfo)}"); var map = MapKey (keyInfo); @@ -1437,14 +1437,14 @@ public WindowsConsole.KeyEventRecord FromVKPacketToKeyEventRecord (WindowsConsol keyEvent.dwControlKeyState.HasFlag (WindowsConsole.ControlKeyState.RightControlPressed)) { mod |= ConsoleModifiers.Control; } - var keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (keyEvent.UnicodeChar, mod, out uint virtualKey, out uint scanCode); + var cKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (keyEvent.UnicodeChar, mod, out uint scanCode); return new WindowsConsole.KeyEventRecord { - UnicodeChar = (char)keyChar, + UnicodeChar = cKeyInfo.KeyChar, bKeyDown = keyEvent.bKeyDown, dwControlKeyState = keyEvent.dwControlKeyState, wRepeatCount = keyEvent.wRepeatCount, - wVirtualKeyCode = (ushort)virtualKey, + wVirtualKeyCode = (ushort)cKeyInfo.Key, wVirtualScanCode = (ushort)scanCode }; } diff --git a/UICatalog/Scenarios/VkeyPacketSimulator.cs b/UICatalog/Scenarios/VkeyPacketSimulator.cs index 4c59e5f0bb..4bb4fdd2e4 100644 --- a/UICatalog/Scenarios/VkeyPacketSimulator.cs +++ b/UICatalog/Scenarios/VkeyPacketSimulator.cs @@ -162,8 +162,8 @@ public override void Setup () mod |= ConsoleModifiers.Control; } for (int i = 0; i < _keyboardStrokes.Count; i++) { - var consoleKey = ConsoleKeyMapping.GetConsoleKeyFromKey ((uint)_keyboardStrokes [i], mod, out _, out _); - Application.Driver.SendKeys ((char)consoleKey, ConsoleKey.Packet, mod.HasFlag (ConsoleModifiers.Shift), + var consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey ((uint)_keyboardStrokes [i], mod, out _); + Application.Driver.SendKeys (consoleKeyInfo.KeyChar, ConsoleKey.Packet, mod.HasFlag (ConsoleModifiers.Shift), mod.HasFlag (ConsoleModifiers.Alt), mod.HasFlag (ConsoleModifiers.Control)); } //} diff --git a/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs new file mode 100644 index 0000000000..26cb60ec5a --- /dev/null +++ b/UnitTests/ConsoleDrivers/ConsoleKeyMappingTests.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Xunit; + +namespace Terminal.Gui.ConsoleDrivers; +public class ConsoleKeyMappingTests { + [Theory] + [InlineData ((KeyCode)'a' | KeyCode.ShiftMask, ConsoleKey.A, KeyCode.A, 'A')] + [InlineData ((KeyCode)'A', ConsoleKey.A, (KeyCode)'a', 'a')] + [InlineData ((KeyCode)'à' | KeyCode.ShiftMask, ConsoleKey.A, (KeyCode)'À', 'À')] + [InlineData ((KeyCode)'À', ConsoleKey.A, (KeyCode)'à', 'à')] + [InlineData ((KeyCode)'ü' | KeyCode.ShiftMask, ConsoleKey.U, (KeyCode)'Ü', 'Ü')] + [InlineData ((KeyCode)'Ü', ConsoleKey.U, (KeyCode)'ü', 'ü')] + [InlineData ((KeyCode)'ý' | KeyCode.ShiftMask, ConsoleKey.Y, (KeyCode)'Ý', 'Ý')] + [InlineData ((KeyCode)'Ý', ConsoleKey.Y, (KeyCode)'ý', 'ý')] + [InlineData ((KeyCode)'!' | KeyCode.ShiftMask, ConsoleKey.D1, (KeyCode)'!', '!')] + [InlineData (KeyCode.D1, ConsoleKey.D1, KeyCode.D1, '1')] + [InlineData ((KeyCode)'/' | KeyCode.ShiftMask, ConsoleKey.D7, (KeyCode)'/', '/')] + [InlineData (KeyCode.D7, ConsoleKey.D7, KeyCode.D7, '7')] + [InlineData (KeyCode.PageDown | KeyCode.ShiftMask, ConsoleKey.PageDown, KeyCode.Null, '\0')] + [InlineData (KeyCode.PageDown, ConsoleKey.PageDown, KeyCode.Null, '\0')] + + public void TestIfEqual (KeyCode key, ConsoleKey expectedConsoleKey, KeyCode expectedKey, char expectedChar) + { + var consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (key); + Assert.Equal (consoleKeyInfo.Key, expectedConsoleKey); + Assert.Equal ((char)expectedKey, expectedChar); + Assert.Equal (consoleKeyInfo.KeyChar, expectedChar); + } + + static object packetLock = new object (); + + /// + /// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'. + /// These are indicated with the wVirtualKeyCode of 231. When we see this code + /// then we need to look to the unicode character (UnicodeChar) instead of the key + /// when telling the rest of the framework what button was pressed. For full details + /// see: https://github.com/gui-cs/Terminal.Gui/issues/2008 + /// + [Theory] + [AutoInitShutdown] + [ClassData (typeof (PacketTest))] + public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool control, uint initialVirtualKey, + uint initialScanCode, KeyCode expectedRemapping, uint expectedVirtualKey, uint expectedScanCode) + { + lock (packetLock) { + Application._forceFakeConsole = true; + Application.Init (); + + var modifiers = new ConsoleModifiers (); + if (shift) { + modifiers |= ConsoleModifiers.Shift; + } + if (alt) { + modifiers |= ConsoleModifiers.Alt; + } + if (control) { + modifiers |= ConsoleModifiers.Control; + } + ConsoleKeyInfo consoleKeyInfo = ConsoleKeyMapping.GetConsoleKeyFromKey (unicodeCharacter, modifiers, out uint scanCode); + + Assert.Equal ((uint)consoleKeyInfo.Key, initialVirtualKey); + + + if (scanCode > 0 && consoleKeyInfo.KeyChar == 0) { + Assert.Equal (0, (double)consoleKeyInfo.KeyChar); + } else { + Assert.Equal (consoleKeyInfo.KeyChar, unicodeCharacter); + } + Assert.Equal ((uint)consoleKeyInfo.Key, expectedVirtualKey); + Assert.Equal (scanCode, initialScanCode); + Assert.Equal (scanCode, expectedScanCode); + + var top = Application.Top; + + top.KeyDown += (s, e) => { + Assert.Equal (Key.ToString (expectedRemapping), Key.ToString (e.KeyCode)); + e.Handled = true; + Application.RequestStop (); + }; + + int iterations = -1; + + Application.Iteration += (s, a) => { + iterations++; + if (iterations == 0) { + Application.Driver.SendKeys (consoleKeyInfo.KeyChar, ConsoleKey.Packet, shift, alt, control); + } + }; + Application.Run (); + Application.Shutdown (); + } + } + + public class PacketTest : IEnumerable, IEnumerable { + public IEnumerator GetEnumerator () + { + lock (packetLock) { + // unicodeCharacter, shift, alt, control, initialVirtualKey, initialScanCode, expectedRemapping, expectedVirtualKey, expectedScanCode + yield return new object [] { 'a', false, false, false, 'A', 30, KeyCode.A, 'A', 30 }; + yield return new object [] { 'A', true, false, false, 'A', 30, KeyCode.A | KeyCode.ShiftMask, 'A', 30 }; + yield return new object [] { 'A', true, true, false, 'A', 30, KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask, 'A', 30 }; + yield return new object [] { 'A', true, true, true, 'A', 30, KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 'A', 30 }; + yield return new object [] { 'z', false, false, false, 'Z', 44, KeyCode.Z, 'Z', 44 }; + yield return new object [] { 'Z', true, false, false, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask, 'Z', 44 }; + yield return new object [] { 'Z', true, true, false, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask | KeyCode.AltMask, 'Z', 44 }; + yield return new object [] { 'Z', true, true, true, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 'Z', 44 }; + yield return new object [] { '英', false, false, false, '\0', 0, (KeyCode)'英', '\0', 0 }; + yield return new object [] { '英', true, false, false, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask, '\0', 0 }; + yield return new object [] { '英', true, true, false, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask | KeyCode.AltMask, '\0', 0 }; + yield return new object [] { '英', true, true, true, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '\0', 0 }; + yield return new object [] { '+', false, false, false, 187, 26, (KeyCode)'+', 187, 26 }; + yield return new object [] { '*', true, false, false, 187, 26, (KeyCode)'*' | KeyCode.ShiftMask, 187, 26 }; + yield return new object [] { '+', true, true, false, 187, 26, (KeyCode)'+' | KeyCode.ShiftMask | KeyCode.AltMask, 187, 26 }; + yield return new object [] { '+', true, true, true, 187, 26, (KeyCode)'+' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 187, 26 }; + yield return new object [] { '1', false, false, false, '1', 2, KeyCode.D1, '1', 2 }; + yield return new object [] { '!', true, false, false, '1', 2, (KeyCode)'!' | KeyCode.ShiftMask, '1', 2 }; + yield return new object [] { '1', true, true, false, '1', 2, KeyCode.D1 | KeyCode.ShiftMask | KeyCode.AltMask, '1', 2 }; + yield return new object [] { '1', true, true, true, '1', 2, KeyCode.D1 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '1', 2 }; + yield return new object [] { '1', false, true, true, '1', 2, KeyCode.D1 | KeyCode.AltMask | KeyCode.CtrlMask, '1', 2 }; + yield return new object [] { '2', false, false, false, '2', 3, KeyCode.D2, '2', 3 }; + yield return new object [] { '"', true, false, false, '2', 3, (KeyCode)'"' | KeyCode.ShiftMask, '2', 3 }; + yield return new object [] { '2', true, true, false, '2', 3, KeyCode.D2 | KeyCode.ShiftMask | KeyCode.AltMask, '2', 3 }; + yield return new object [] { '2', true, true, true, '2', 3, KeyCode.D2 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '2', 3 }; + yield return new object [] { '@', false, true, true, '2', 3, (KeyCode)'@' | KeyCode.AltMask | KeyCode.CtrlMask, '2', 3 }; + yield return new object [] { '3', false, false, false, '3', 4, KeyCode.D3, '3', 4 }; + yield return new object [] { '#', true, false, false, '3', 4, (KeyCode)'#' | KeyCode.ShiftMask, '3', 4 }; + yield return new object [] { '3', true, true, false, '3', 4, KeyCode.D3 | KeyCode.ShiftMask | KeyCode.AltMask, '3', 4 }; + yield return new object [] { '3', true, true, true, '3', 4, KeyCode.D3 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '3', 4 }; + yield return new object [] { '£', false, true, true, '3', 4, (KeyCode)'£' | KeyCode.AltMask | KeyCode.CtrlMask, '3', 4 }; + yield return new object [] { '4', false, false, false, '4', 5, KeyCode.D4, '4', 5 }; + yield return new object [] { '$', true, false, false, '4', 5, (KeyCode)'$' | KeyCode.ShiftMask, '4', 5 }; + yield return new object [] { '4', true, true, false, '4', 5, KeyCode.D4 | KeyCode.ShiftMask | KeyCode.AltMask, '4', 5 }; + yield return new object [] { '4', true, true, true, '4', 5, KeyCode.D4 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '4', 5 }; + yield return new object [] { '§', false, true, true, '4', 5, (KeyCode)'§' | KeyCode.AltMask | KeyCode.CtrlMask, '4', 5 }; + yield return new object [] { '5', false, false, false, '5', 6, KeyCode.D5, '5', 6 }; + yield return new object [] { '%', true, false, false, '5', 6, (KeyCode)'%' | KeyCode.ShiftMask, '5', 6 }; + yield return new object [] { '5', true, true, false, '5', 6, KeyCode.D5 | KeyCode.ShiftMask | KeyCode.AltMask, '5', 6 }; + yield return new object [] { '5', true, true, true, '5', 6, KeyCode.D5 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '5', 6 }; + yield return new object [] { '€', false, true, true, '5', 6, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask, '5', 6 }; + yield return new object [] { '6', false, false, false, '6', 7, KeyCode.D6, '6', 7 }; + yield return new object [] { '&', true, false, false, '6', 7, (KeyCode)'&' | KeyCode.ShiftMask, '6', 7 }; + yield return new object [] { '6', true, true, false, '6', 7, KeyCode.D6 | KeyCode.ShiftMask | KeyCode.AltMask, '6', 7 }; + yield return new object [] { '6', true, true, true, '6', 7, KeyCode.D6 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '6', 7 }; + yield return new object [] { '6', false, true, true, '6', 7, KeyCode.D6 | KeyCode.AltMask | KeyCode.CtrlMask, '6', 7 }; + yield return new object [] { '7', false, false, false, '7', 8, KeyCode.D7, '7', 8 }; + yield return new object [] { '/', true, false, false, '7', 8, (KeyCode)'/' | KeyCode.ShiftMask, '7', 8 }; + yield return new object [] { '7', true, true, false, '7', 8, KeyCode.D7 | KeyCode.ShiftMask | KeyCode.AltMask, '7', 8 }; + yield return new object [] { '7', true, true, true, '7', 8, KeyCode.D7 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '7', 8 }; + yield return new object [] { '{', false, true, true, '7', 8, (KeyCode)'{' | KeyCode.AltMask | KeyCode.CtrlMask, '7', 8 }; + yield return new object [] { '8', false, false, false, '8', 9, KeyCode.D8, '8', 9 }; + yield return new object [] { '(', true, false, false, '8', 9, (KeyCode)'(' | KeyCode.ShiftMask, '8', 9 }; + yield return new object [] { '8', true, true, false, '8', 9, KeyCode.D8 | KeyCode.ShiftMask | KeyCode.AltMask, '8', 9 }; + yield return new object [] { '8', true, true, true, '8', 9, KeyCode.D8 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '8', 9 }; + yield return new object [] { '[', false, true, true, '8', 9, (KeyCode)'[' | KeyCode.AltMask | KeyCode.CtrlMask, '8', 9 }; + yield return new object [] { '9', false, false, false, '9', 10, KeyCode.D9, '9', 10 }; + yield return new object [] { ')', true, false, false, '9', 10, (KeyCode)')' | KeyCode.ShiftMask, '9', 10 }; + yield return new object [] { '9', true, true, false, '9', 10, KeyCode.D9 | KeyCode.ShiftMask | KeyCode.AltMask, '9', 10 }; + yield return new object [] { '9', true, true, true, '9', 10, KeyCode.D9 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '9', 10 }; + yield return new object [] { ']', false, true, true, '9', 10, (KeyCode)']' | KeyCode.AltMask | KeyCode.CtrlMask, '9', 10 }; + yield return new object [] { '0', false, false, false, '0', 11, KeyCode.D0, '0', 11 }; + yield return new object [] { '=', true, false, false, '0', 11, (KeyCode)'=' | KeyCode.ShiftMask, '0', 11 }; + yield return new object [] { '0', true, true, false, '0', 11, KeyCode.D0 | KeyCode.ShiftMask | KeyCode.AltMask, '0', 11 }; + yield return new object [] { '0', true, true, true, '0', 11, KeyCode.D0 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '0', 11 }; + yield return new object [] { '}', false, true, true, '0', 11, (KeyCode)'}' | KeyCode.AltMask | KeyCode.CtrlMask, '0', 11 }; + yield return new object [] { '\'', false, false, false, 219, 12, (KeyCode)'\'', 219, 12 }; + yield return new object [] { '?', true, false, false, 219, 12, (KeyCode)'?' | KeyCode.ShiftMask, 219, 12 }; + yield return new object [] { '\'', true, true, false, 219, 12, (KeyCode)'\'' | KeyCode.ShiftMask | KeyCode.AltMask, 219, 12 }; + yield return new object [] { '\'', true, true, true, 219, 12, (KeyCode)'\'' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 219, 12 }; + yield return new object [] { '«', false, false, false, 221, 13, (KeyCode)'«', 221, 13 }; + yield return new object [] { '»', true, false, false, 221, 13, (KeyCode)'»' | KeyCode.ShiftMask, 221, 13 }; + yield return new object [] { '«', true, true, false, 221, 13, (KeyCode)'«' | KeyCode.ShiftMask | KeyCode.AltMask, 221, 13 }; + yield return new object [] { '«', true, true, true, 221, 13, (KeyCode)'«' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 221, 13 }; + yield return new object [] { 'á', false, false, false, 'A', 30, (KeyCode)'á', 'A', 30 }; + yield return new object [] { 'Á', true, false, false, 'A', 30, (KeyCode)'Á' | KeyCode.ShiftMask, 'A', 30 }; + yield return new object [] { 'à', false, false, false, 'A', 30, (KeyCode)'à', 'A', 30 }; + yield return new object [] { 'À', true, false, false, 'A', 30, (KeyCode)'À' | KeyCode.ShiftMask, 'A', 30 }; + yield return new object [] { 'é', false, false, false, 'E', 18, (KeyCode)'é', 'E', 18 }; + yield return new object [] { 'É', true, false, false, 'E', 18, (KeyCode)'É' | KeyCode.ShiftMask, 'E', 18 }; + yield return new object [] { 'è', false, false, false, 'E', 18, (KeyCode)'è', 'E', 18 }; + yield return new object [] { 'È', true, false, false, 'E', 18, (KeyCode)'È' | KeyCode.ShiftMask, 'E', 18 }; + yield return new object [] { 'í', false, false, false, 'I', 23, (KeyCode)'í', 'I', 23 }; + yield return new object [] { 'Í', true, false, false, 'I', 23, (KeyCode)'Í' | KeyCode.ShiftMask, 'I', 23 }; + yield return new object [] { 'ì', false, false, false, 'I', 23, (KeyCode)'ì', 'I', 23 }; + yield return new object [] { 'Ì', true, false, false, 'I', 23, (KeyCode)'Ì' | KeyCode.ShiftMask, 'I', 23 }; + yield return new object [] { 'ó', false, false, false, 'O', 24, (KeyCode)'ó', 'O', 24 }; + yield return new object [] { 'Ó', true, false, false, 'O', 24, (KeyCode)'Ó' | KeyCode.ShiftMask, 'O', 24 }; + yield return new object [] { 'ò', false, false, false, 'O', 24, (KeyCode)'ò', 'O', 24 }; + yield return new object [] { 'Ò', true, false, false, 'O', 24, (KeyCode)'Ò' | KeyCode.ShiftMask, 'O', 24 }; + yield return new object [] { 'ú', false, false, false, 'U', 22, (KeyCode)'ú', 'U', 22 }; + yield return new object [] { 'Ú', true, false, false, 'U', 22, (KeyCode)'Ú' | KeyCode.ShiftMask, 'U', 22 }; + yield return new object [] { 'ù', false, false, false, 'U', 22, (KeyCode)'ù', 'U', 22 }; + yield return new object [] { 'Ù', true, false, false, 'U', 22, (KeyCode)'Ù' | KeyCode.ShiftMask, 'U', 22 }; + yield return new object [] { 'ö', false, false, false, 'O', 24, (KeyCode)'ö', 'O', 24 }; + yield return new object [] { 'Ö', true, false, false, 'O', 24, (KeyCode)'Ö' | KeyCode.ShiftMask, 'O', 24 }; + yield return new object [] { '<', false, false, false, 226, 86, (KeyCode)'<', 226, 86 }; + yield return new object [] { '>', true, false, false, 226, 86, (KeyCode)'>' | KeyCode.ShiftMask, 226, 86 }; + yield return new object [] { '<', true, true, false, 226, 86, (KeyCode)'<' | KeyCode.ShiftMask | KeyCode.AltMask, 226, 86 }; + yield return new object [] { '<', true, true, true, 226, 86, (KeyCode)'<' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 226, 86 }; + yield return new object [] { 'ç', false, false, false, 192, 39, (KeyCode)'ç', 192, 39 }; + yield return new object [] { 'Ç', true, false, false, 192, 39, (KeyCode)'Ç' | KeyCode.ShiftMask, 192, 39 }; + yield return new object [] { 'ç', true, true, false, 192, 39, (KeyCode)'ç' | KeyCode.ShiftMask | KeyCode.AltMask, 192, 39 }; + yield return new object [] { 'ç', true, true, true, 192, 39, (KeyCode)'ç' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 192, 39 }; + yield return new object [] { '¨', false, true, true, 187, 26, (KeyCode)'¨' | KeyCode.AltMask | KeyCode.CtrlMask, 187, 26 }; + yield return new object [] { KeyCode.PageUp, false, false, false, 33, 73, KeyCode.Null, 33, 73 }; + yield return new object [] { KeyCode.PageUp, true, false, false, 33, 73, KeyCode.Null | KeyCode.ShiftMask, 33, 73 }; + yield return new object [] { KeyCode.PageUp, true, true, false, 33, 73, KeyCode.Null | KeyCode.ShiftMask | KeyCode.AltMask, 33, 73 }; + yield return new object [] { KeyCode.PageUp, true, true, true, 33, 73, KeyCode.Null | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 33, 73 }; + } + } + + IEnumerator IEnumerable.GetEnumerator () + { + return GetEnumerator (); + } + } +} diff --git a/UnitTests/ConsoleDrivers/KeyCodeTests.cs b/UnitTests/ConsoleDrivers/KeyCodeTests.cs index 730f03b216..ef1801ecd8 100644 --- a/UnitTests/ConsoleDrivers/KeyCodeTests.cs +++ b/UnitTests/ConsoleDrivers/KeyCodeTests.cs @@ -1,8 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using Terminal.Gui; -using Terminal.Gui.ConsoleDrivers; using Xunit; using Xunit.Abstractions; @@ -182,211 +178,4 @@ public void Key_ToString () k = KeyCode.D | KeyCode.ShiftMask; Assert.Equal ("D, ShiftMask", k.ToString ()); } - - static object packetLock = new object (); - - /// - /// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'. - /// These are indicated with the wVirtualKeyCode of 231. When we see this code - /// then we need to look to the unicode character (UnicodeChar) instead of the key - /// when telling the rest of the framework what button was pressed. For full details - /// see: https://github.com/gui-cs/Terminal.Gui/issues/2008 - /// - [Theory] - [AutoInitShutdown] - [ClassData (typeof (PacketTest))] - public void TestVKPacket (uint unicodeCharacter, bool shift, bool alt, bool control, uint initialVirtualKey, - uint initialScanCode, KeyCode expectedRemapping, uint expectedVirtualKey, uint expectedScanCode) - { - lock (packetLock) { - Application._forceFakeConsole = true; - Application.Init (); - - var modifiers = new ConsoleModifiers (); - if (shift) { - modifiers |= ConsoleModifiers.Shift; - } - if (alt) { - modifiers |= ConsoleModifiers.Alt; - } - if (control) { - modifiers |= ConsoleModifiers.Control; - } - uint mappedConsoleKey = ConsoleKeyMapping.GetConsoleKeyFromKey (unicodeCharacter, modifiers, out uint scanCode, out uint outputChar); - - if ((scanCode > 0 || mappedConsoleKey == 0) && mappedConsoleKey == initialVirtualKey) { - Assert.Equal (mappedConsoleKey, initialVirtualKey); - } else { - Assert.Equal (mappedConsoleKey, outputChar < 0xff ? outputChar & 0xff | 0xff << 8 : outputChar); - } - Assert.Equal (scanCode, initialScanCode); - - uint keyChar = ConsoleKeyMapping.GetKeyCharFromConsoleKey (mappedConsoleKey, modifiers, out uint consoleKey, out scanCode); - - //if (scanCode > 0 && consoleKey == keyChar && consoleKey > 48 && consoleKey > 57 && consoleKey < 65 && consoleKey > 91) { - if (scanCode > 0 && keyChar == 0 && consoleKey == mappedConsoleKey) { - Assert.Equal (0, (double)keyChar); - } else { - //#if BROKE_WITH_2927 - // This test is now bogus? - //Assert.Equal (keyChar, unicodeCharacter); - //#endif - } - //#if BROKE_WITH_2927 - Assert.Equal (consoleKey, expectedVirtualKey); - //#endif - Assert.Equal (scanCode, expectedScanCode); - - var top = Application.Top; - - top.KeyDown += (s, e) => { - Assert.Equal (Key.ToString (expectedRemapping), Key.ToString (e.KeyCode)); - e.Handled = true; - Application.RequestStop (); - }; - - int iterations = -1; - - Application.Iteration += (s, a) => { - iterations++; - if (iterations == 0) { - Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control); - } - }; - Application.Run (); - Application.Shutdown (); - } - } - - public class PacketTest : IEnumerable, IEnumerable { - public IEnumerator GetEnumerator () - { - lock (packetLock) { - // unicodeCharacter, shift, alt, control, initialVirtualKey, initialScanCode, expectedRemapping, expectedVirtualKey, expectedScanCode - yield return new object [] { 'a', false, false, false, 'A', 30, KeyCode.A, 'A', 30 }; -#if BROKE_WITH_2927 - // If the input unicode char is `A`, the output should be `A` (which means Key.A | Key.ShiftMask) and not `a` . - // It think the bug is in GetKeyCharFromConsoleKey - yield return new object [] { 'A', false, false, false, 'A', 30, Key.A | Key.ShiftMask, 'A', 30 }; -#endif - yield return new object [] { 'A', true, false, false, 'A', 30, KeyCode.A | KeyCode.ShiftMask, 'A', 30 }; - yield return new object [] { 'A', true, true, false, 'A', 30, KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask, 'A', 30 }; - yield return new object [] { 'A', true, true, true, 'A', 30, KeyCode.A | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 'A', 30 }; - - yield return new object [] { 'z', false, false, false, 'Z', 44, KeyCode.Z, 'Z', 44 }; -#if BROKE_WITH_2927 - yield return new object [] { 'Z', false, false, false, 'Z', 44, Key.Z | Key.ShiftMask, 'Z', 44 }; -#endif - yield return new object [] { 'Z', true, false, false, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask, 'Z', 44 }; - yield return new object [] { 'Z', true, true, false, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask | KeyCode.AltMask, 'Z', 44 }; - yield return new object [] { 'Z', true, true, true, 'Z', 44, KeyCode.Z | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 'Z', 44 }; - yield return new object [] { '英', false, false, false, '\0', 0, (KeyCode)'英', '\0', 0 }; - yield return new object [] { '英', true, false, false, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask, '\0', 0 }; - yield return new object [] { '英', true, true, false, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask | KeyCode.AltMask, '\0', 0 }; - yield return new object [] { '英', true, true, true, '\0', 0, (KeyCode)'英' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '\0', 0 }; - yield return new object [] { '+', false, false, false, 187, 26, (KeyCode)'+', 187, 26 }; - yield return new object [] { '*', true, false, false, 187, 26, (KeyCode)'*' | KeyCode.ShiftMask, 187, 26 }; - yield return new object [] { '+', true, true, false, 187, 26, (KeyCode)'+' | KeyCode.ShiftMask | KeyCode.AltMask, 187, 26 }; - yield return new object [] { '+', true, true, true, 187, 26, (KeyCode)'+' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 187, 26 }; - yield return new object [] { '1', false, false, false, '1', 2, KeyCode.D1, '1', 2 }; - yield return new object [] { '!', true, false, false, '1', 2, (KeyCode)'!' | KeyCode.ShiftMask, '1', 2 }; - yield return new object [] { '1', true, true, false, '1', 2, KeyCode.D1 | KeyCode.ShiftMask | KeyCode.AltMask, '1', 2 }; - yield return new object [] { '1', true, true, true, '1', 2, KeyCode.D1 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '1', 2 }; - yield return new object [] { '1', false, true, true, '1', 2, KeyCode.D1 | KeyCode.AltMask | KeyCode.CtrlMask, '1', 2 }; - yield return new object [] { '2', false, false, false, '2', 3, KeyCode.D2, '2', 3 }; - yield return new object [] { '"', true, false, false, '2', 3, (KeyCode)'"' | KeyCode.ShiftMask, '2', 3 }; - yield return new object [] { '2', true, true, false, '2', 3, KeyCode.D2 | KeyCode.ShiftMask | KeyCode.AltMask, '2', 3 }; - yield return new object [] { '2', true, true, true, '2', 3, KeyCode.D2 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '2', 3 }; - yield return new object [] { '@', false, true, true, '2', 3, (KeyCode)'@' | KeyCode.AltMask | KeyCode.CtrlMask, '2', 3 }; - yield return new object [] { '3', false, false, false, '3', 4, KeyCode.D3, '3', 4 }; - yield return new object [] { '#', true, false, false, '3', 4, (KeyCode)'#' | KeyCode.ShiftMask, '3', 4 }; - yield return new object [] { '3', true, true, false, '3', 4, KeyCode.D3 | KeyCode.ShiftMask | KeyCode.AltMask, '3', 4 }; - yield return new object [] { '3', true, true, true, '3', 4, KeyCode.D3 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '3', 4 }; - yield return new object [] { '£', false, true, true, '3', 4, (KeyCode)'£' | KeyCode.AltMask | KeyCode.CtrlMask, '3', 4 }; - yield return new object [] { '4', false, false, false, '4', 5, KeyCode.D4, '4', 5 }; - yield return new object [] { '$', true, false, false, '4', 5, (KeyCode)'$' | KeyCode.ShiftMask, '4', 5 }; - yield return new object [] { '4', true, true, false, '4', 5, KeyCode.D4 | KeyCode.ShiftMask | KeyCode.AltMask, '4', 5 }; - yield return new object [] { '4', true, true, true, '4', 5, KeyCode.D4 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '4', 5 }; - yield return new object [] { '§', false, true, true, '4', 5, (KeyCode)'§' | KeyCode.AltMask | KeyCode.CtrlMask, '4', 5 }; - yield return new object [] { '5', false, false, false, '5', 6, KeyCode.D5, '5', 6 }; - yield return new object [] { '%', true, false, false, '5', 6, (KeyCode)'%' | KeyCode.ShiftMask, '5', 6 }; - yield return new object [] { '5', true, true, false, '5', 6, KeyCode.D5 | KeyCode.ShiftMask | KeyCode.AltMask, '5', 6 }; - yield return new object [] { '5', true, true, true, '5', 6, KeyCode.D5 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '5', 6 }; - yield return new object [] { '€', false, true, true, '5', 6, (KeyCode)'€' | KeyCode.AltMask | KeyCode.CtrlMask, '5', 6 }; - yield return new object [] { '6', false, false, false, '6', 7, KeyCode.D6, '6', 7 }; - yield return new object [] { '&', true, false, false, '6', 7, (KeyCode)'&' | KeyCode.ShiftMask, '6', 7 }; - yield return new object [] { '6', true, true, false, '6', 7, KeyCode.D6 | KeyCode.ShiftMask | KeyCode.AltMask, '6', 7 }; - yield return new object [] { '6', true, true, true, '6', 7, KeyCode.D6 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '6', 7 }; - yield return new object [] { '6', false, true, true, '6', 7, KeyCode.D6 | KeyCode.AltMask | KeyCode.CtrlMask, '6', 7 }; - yield return new object [] { '7', false, false, false, '7', 8, KeyCode.D7, '7', 8 }; - yield return new object [] { '/', true, false, false, '7', 8, (KeyCode)'/' | KeyCode.ShiftMask, '7', 8 }; - yield return new object [] { '7', true, true, false, '7', 8, KeyCode.D7 | KeyCode.ShiftMask | KeyCode.AltMask, '7', 8 }; - yield return new object [] { '7', true, true, true, '7', 8, KeyCode.D7 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '7', 8 }; - yield return new object [] { '{', false, true, true, '7', 8, (KeyCode)'{' | KeyCode.AltMask | KeyCode.CtrlMask, '7', 8 }; - yield return new object [] { '8', false, false, false, '8', 9, KeyCode.D8, '8', 9 }; - yield return new object [] { '(', true, false, false, '8', 9, (KeyCode)'(' | KeyCode.ShiftMask, '8', 9 }; - yield return new object [] { '8', true, true, false, '8', 9, KeyCode.D8 | KeyCode.ShiftMask | KeyCode.AltMask, '8', 9 }; - yield return new object [] { '8', true, true, true, '8', 9, KeyCode.D8 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '8', 9 }; - yield return new object [] { '[', false, true, true, '8', 9, (KeyCode)'[' | KeyCode.AltMask | KeyCode.CtrlMask, '8', 9 }; - yield return new object [] { '9', false, false, false, '9', 10, KeyCode.D9, '9', 10 }; - yield return new object [] { ')', true, false, false, '9', 10, (KeyCode)')' | KeyCode.ShiftMask, '9', 10 }; - yield return new object [] { '9', true, true, false, '9', 10, KeyCode.D9 | KeyCode.ShiftMask | KeyCode.AltMask, '9', 10 }; - yield return new object [] { '9', true, true, true, '9', 10, KeyCode.D9 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '9', 10 }; - yield return new object [] { ']', false, true, true, '9', 10, (KeyCode)']' | KeyCode.AltMask | KeyCode.CtrlMask, '9', 10 }; - yield return new object [] { '0', false, false, false, '0', 11, KeyCode.D0, '0', 11 }; - yield return new object [] { '=', true, false, false, '0', 11, (KeyCode)'=' | KeyCode.ShiftMask, '0', 11 }; - yield return new object [] { '0', true, true, false, '0', 11, KeyCode.D0 | KeyCode.ShiftMask | KeyCode.AltMask, '0', 11 }; - yield return new object [] { '0', true, true, true, '0', 11, KeyCode.D0 | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, '0', 11 }; - yield return new object [] { '}', false, true, true, '0', 11, (KeyCode)'}' | KeyCode.AltMask | KeyCode.CtrlMask, '0', 11 }; - yield return new object [] { '\'', false, false, false, 219, 12, (KeyCode)'\'', 219, 12 }; - yield return new object [] { '?', true, false, false, 219, 12, (KeyCode)'?' | KeyCode.ShiftMask, 219, 12 }; - yield return new object [] { '\'', true, true, false, 219, 12, (KeyCode)'\'' | KeyCode.ShiftMask | KeyCode.AltMask, 219, 12 }; - yield return new object [] { '\'', true, true, true, 219, 12, (KeyCode)'\'' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 219, 12 }; - yield return new object [] { '«', false, false, false, 221, 13, (KeyCode)'«', 221, 13 }; - yield return new object [] { '»', true, false, false, 221, 13, (KeyCode)'»' | KeyCode.ShiftMask, 221, 13 }; - yield return new object [] { '«', true, true, false, 221, 13, (KeyCode)'«' | KeyCode.ShiftMask | KeyCode.AltMask, 221, 13 }; - yield return new object [] { '«', true, true, true, 221, 13, (KeyCode)'«' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 221, 13 }; - yield return new object [] { 'á', false, false, false, 'á', 0, (KeyCode)'á', 'A', 30 }; - yield return new object [] { 'Á', true, false, false, 'Á', 0, (KeyCode)'Á' | KeyCode.ShiftMask, 'A', 30 }; - yield return new object [] { 'à', false, false, false, 'à', 0, (KeyCode)'à', 'A', 30 }; - yield return new object [] { 'À', true, false, false, 'À', 0, (KeyCode)'À' | KeyCode.ShiftMask, 'A', 30 }; - yield return new object [] { 'é', false, false, false, 'é', 0, (KeyCode)'é', 'E', 18 }; - yield return new object [] { 'É', true, false, false, 'É', 0, (KeyCode)'É' | KeyCode.ShiftMask, 'E', 18 }; - yield return new object [] { 'è', false, false, false, 'è', 0, (KeyCode)'è', 'E', 18 }; - yield return new object [] { 'È', true, false, false, 'È', 0, (KeyCode)'È' | KeyCode.ShiftMask, 'E', 18 }; - yield return new object [] { 'í', false, false, false, 'í', 0, (KeyCode)'í', 'I', 23 }; - yield return new object [] { 'Í', true, false, false, 'Í', 0, (KeyCode)'Í' | KeyCode.ShiftMask, 'I', 23 }; - yield return new object [] { 'ì', false, false, false, 'ì', 0, (KeyCode)'ì', 'I', 23 }; - yield return new object [] { 'Ì', true, false, false, 'Ì', 0, (KeyCode)'Ì' | KeyCode.ShiftMask, 'I', 23 }; - yield return new object [] { 'ó', false, false, false, 'ó', 0, (KeyCode)'ó', 'O', 24 }; - yield return new object [] { 'Ó', true, false, false, 'Ó', 0, (KeyCode)'Ó' | KeyCode.ShiftMask, 'O', 24 }; - yield return new object [] { 'ò', false, false, false, 'Ó', 0, (KeyCode)'ò', 'O', 24 }; - yield return new object [] { 'Ò', true, false, false, 'Ò', 0, (KeyCode)'Ò' | KeyCode.ShiftMask, 'O', 24 }; - yield return new object [] { 'ú', false, false, false, 'ú', 0, (KeyCode)'ú', 'U', 22 }; - yield return new object [] { 'Ú', true, false, false, 'Ú', 0, (KeyCode)'Ú' | KeyCode.ShiftMask, 'U', 22 }; - yield return new object [] { 'ù', false, false, false, 'ù', 0, (KeyCode)'ù', 'U', 22 }; - yield return new object [] { 'Ù', true, false, false, 'Ù', 0, (KeyCode)'Ù' | KeyCode.ShiftMask, 'U', 22 }; - yield return new object [] { 'ö', false, false, false, 'ó', 0, (KeyCode)'ö', 'O', 24 }; - yield return new object [] { 'Ö', true, false, false, 'Ó', 0, (KeyCode)'Ö' | KeyCode.ShiftMask, 'O', 24 }; - yield return new object [] { '<', false, false, false, 226, 86, (KeyCode)'<', 226, 86 }; - yield return new object [] { '>', true, false, false, 226, 86, (KeyCode)'>' | KeyCode.ShiftMask, 226, 86 }; - yield return new object [] { '<', true, true, false, 226, 86, (KeyCode)'<' | KeyCode.ShiftMask | KeyCode.AltMask, 226, 86 }; - yield return new object [] { '<', true, true, true, 226, 86, (KeyCode)'<' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 226, 86 }; - yield return new object [] { 'ç', false, false, false, 192, 39, (KeyCode)'ç', 192, 39 }; - yield return new object [] { 'Ç', true, false, false, 192, 39, (KeyCode)'Ç' | KeyCode.ShiftMask, 192, 39 }; - yield return new object [] { 'ç', true, true, false, 192, 39, (KeyCode)'ç' | KeyCode.ShiftMask | KeyCode.AltMask, 192, 39 }; - yield return new object [] { 'ç', true, true, true, 192, 39, (KeyCode)'ç' | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 192, 39 }; - yield return new object [] { '¨', false, true, true, 187, 26, (KeyCode)'¨' | KeyCode.AltMask | KeyCode.CtrlMask, 187, 26 }; - yield return new object [] { (uint)KeyCode.PageUp, false, false, false, 33, 73, KeyCode.PageUp, 33, 73 }; - yield return new object [] { (uint)KeyCode.PageUp, true, false, false, 33, 73, KeyCode.PageUp | KeyCode.ShiftMask, 33, 73 }; - yield return new object [] { (uint)KeyCode.PageUp, true, true, false, 33, 73, KeyCode.PageUp | KeyCode.ShiftMask | KeyCode.AltMask, 33, 73 }; - yield return new object [] { (uint)KeyCode.PageUp, true, true, true, 33, 73, KeyCode.PageUp | KeyCode.ShiftMask | KeyCode.AltMask | KeyCode.CtrlMask, 33, 73 }; - } - } - - IEnumerator IEnumerable.GetEnumerator () - { - return GetEnumerator (); - } - } } \ No newline at end of file