From 554ef0b7802526e6245cdfb8ea65ae3ec298aafd Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 20 Jul 2016 11:30:22 -0700 Subject: [PATCH] Use GetCharFromConsoleKey on Windows Due to virtual key codes on Windows, simple chords like Ctrl+] are not recognized as such. Instead, the ConsoleKey is Oem6, and the KeyChar is an control code. --- .../ConsoleKeyChordConverter.cs | 33 +++++++++++++++++-- .../ConsoleLib.cs | 6 ++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs b/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs index cb5444a1e4..a6248e8bec 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ConsoleKeyChordConverter.cs @@ -6,9 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -#if UNIX -using System.Reflection; -#endif using System.Runtime.InteropServices; using Microsoft.PowerShell.Internal; @@ -306,6 +303,36 @@ namespace Microsoft.PowerShell return default(ConsoleKey); } +#else + internal static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers) + { + // default for unprintables and unhandled + char keyChar = '\u0000'; + + // emulate GetKeyboardState bitmap - set high order bit for relevant modifier virtual keys + var state = new byte[256]; + state[NativeMethods.VK_SHIFT] = (byte)(((modifiers & ConsoleModifiers.Shift) != 0) ? 0x80 : 0); + state[NativeMethods.VK_CONTROL] = (byte)(((modifiers & ConsoleModifiers.Control) != 0) ? 0x80 : 0); + state[NativeMethods.VK_ALT] = (byte)(((modifiers & ConsoleModifiers.Alt) != 0) ? 0x80 : 0); + + // a ConsoleKey enum's value is a virtual key code + uint virtualKey = (uint)key; + + // get corresponding scan code + uint scanCode = NativeMethods.MapVirtualKey(virtualKey, NativeMethods.MAPVK_VK_TO_VSC); + + // get corresponding character - maybe be 0, 1 or 2 in length (diacriticals) + var chars = new char[2]; + int charCount = NativeMethods.ToUnicode( + virtualKey, scanCode, state, chars, chars.Length, NativeMethods.MENU_IS_INACTIVE); + + // TODO: support diacriticals (charCount == 2) + if (charCount == 1) + { + keyChar = chars[0]; + } + return keyChar; + } #endif } } diff --git a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs index 1b3f648b06..f9d1b7cc7f 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs @@ -386,7 +386,13 @@ namespace Microsoft.PowerShell.Internal sb.Append("Alt"); } +#if UNIX char c = key.KeyChar; +#else + // Windows cannot use KeyChar as some chords (like Ctrl+[) show up as control characters. + char c = ConsoleKeyChordConverter.GetCharFromConsoleKey(key.Key, + (mods & ConsoleModifiers.Shift) != 0 ? ConsoleModifiers.Shift : 0); +#endif if (char.IsControl(c) || char.IsWhiteSpace(c)) { if (key.Modifiers.HasFlag(ConsoleModifiers.Shift))