From 015abde3414f1f3e674569a2a8bfe5b08d0b14f3 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Tue, 2 Oct 2018 10:47:56 -0700 Subject: [PATCH 1/4] only change outputencoding to utf8 if not using rasterfont and not already using utf8 --- PSReadLine/PlatformWindows.cs | 35 +++++++++++++++++++++++++++++++++++ PSReadLine/ReadLine.cs | 22 +++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/PSReadLine/PlatformWindows.cs b/PSReadLine/PlatformWindows.cs index 61a4faa6..24c99569 100644 --- a/PSReadLine/PlatformWindows.cs +++ b/PSReadLine/PlatformWindows.cs @@ -93,6 +93,41 @@ private static bool OnBreak(ConsoleBreakSignal signal) return false; } + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + private struct CONSOLE_FONT_INFO_EX + { + internal int cbSize; + internal int nFont; + internal short FontWidth; + internal short FontHeight; + internal FontFamily FontFamily; + internal uint FontWeight; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + internal string FontFace; + } + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern bool GetCurrentConsoleFontEx(IntPtr consoleOutput, bool bMaximumWindow, ref CONSOLE_FONT_INFO_EX consoleFontInfo); + + [Flags()] + internal enum FontFamily : uint + { + TMPF_FIXED_PITCH = 0x01 + } + + internal static bool IsUsingRasterFont() + { + CONSOLE_FONT_INFO_EX fontInfo = new CONSOLE_FONT_INFO_EX(); + fontInfo.cbSize = Marshal.SizeOf(fontInfo); + var handle = _outputHandle.Value.DangerousGetHandle(); + bool result = GetCurrentConsoleFontEx(handle, false, ref fontInfo); + // If this bit is set the font is a variable pitch font. + // If this bit is clear the font is a fixed pitch font. + // Note very carefully that those meanings are the opposite of what the constant name implies. + return !fontInfo.FontFamily.HasFlag(FontFamily.TMPF_FIXED_PITCH); + } + + private static PSConsoleReadLine _singleton; internal static IConsole OneTimeInit(PSConsoleReadLine singleton) { diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 39ac26c1..de4450fd 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -2,6 +2,7 @@ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ +using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; using System; using System.Collections.Generic; using System.Diagnostics; @@ -44,7 +45,7 @@ public partial class PSConsoleReadLine : IPSConsoleReadLineMockableMethods private IConsole _console; private ICharMap _charMap; private Encoding _initialOutputEncoding; - + private bool _changeOutputEncoding; private EngineIntrinsics _engineIntrinsics; private Thread _readKeyThread; private AutoResetEvent _readKeyWaitHandle; @@ -531,7 +532,10 @@ T CallPossibleExternalApplication(Func func) } finally { - _console.OutputEncoding = Encoding.UTF8; + if (_changeOutputEncoding) + { + _console.OutputEncoding = Encoding.UTF8; + } } } @@ -647,7 +651,19 @@ private void Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) _statusIsErrorMessage = false; _initialOutputEncoding = _console.OutputEncoding; - _console.OutputEncoding = Encoding.UTF8; + + // Don't change the OutputEncoding if already UTF8 or using raster font on Windows + _changeOutputEncoding = _initialOutputEncoding != Encoding.UTF8; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && PlatformWindows.IsUsingRasterFont()) + { + _changeOutputEncoding = false; + } + + if (_changeOutputEncoding) + { + _console.OutputEncoding = Encoding.UTF8; + } + _lastRenderTime = Stopwatch.StartNew(); _killCommandCount = 0; From 668b01d40cc8efdc40f5792a3eda93be8e41c61b Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Thu, 4 Oct 2018 13:58:31 -0700 Subject: [PATCH 2/4] add check if stdin is using console before font check --- PSReadLine/PlatformWindows.cs | 9 +++++++-- PSReadLine/ReadLine.cs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/PSReadLine/PlatformWindows.cs b/PSReadLine/PlatformWindows.cs index 24c99569..eddbca0a 100644 --- a/PSReadLine/PlatformWindows.cs +++ b/PSReadLine/PlatformWindows.cs @@ -368,13 +368,18 @@ private static bool SetConsoleOutputVirtualTerminalProcessing() && SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); } + internal static bool IsConsoleInput() + { + var handle = GetStdHandle((uint)StandardHandleId.Input); + return GetFileType(handle) == FILE_TYPE_CHAR; + } + private static bool IsHandleRedirected(bool stdin) { var handle = GetStdHandle((uint)(stdin ? StandardHandleId.Input : StandardHandleId.Output)); // If handle is not to a character device, we must be redirected: - int fileType = GetFileType(handle); - if ((fileType & FILE_TYPE_CHAR) != FILE_TYPE_CHAR) + if (GetFileType(handle) != FILE_TYPE_CHAR) return true; // Char device - if GetConsoleMode succeeds, we are NOT redirected. diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index de4450fd..385270eb 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -654,7 +654,7 @@ private void Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) // Don't change the OutputEncoding if already UTF8 or using raster font on Windows _changeOutputEncoding = _initialOutputEncoding != Encoding.UTF8; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && PlatformWindows.IsUsingRasterFont()) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && PlatformWindows.IsConsoleInput() && PlatformWindows.IsUsingRasterFont()) { _changeOutputEncoding = false; } From 081e8f19dcf8ccc8c7259f3364b249c8873988b1 Mon Sep 17 00:00:00 2001 From: "Steve Lee (POWERSHELL)" Date: Tue, 9 Oct 2018 11:07:58 -0700 Subject: [PATCH 3/4] invert the outputencoding check --- PSReadLine/ReadLine.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 385270eb..a3a00a04 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -45,7 +45,7 @@ public partial class PSConsoleReadLine : IPSConsoleReadLineMockableMethods private IConsole _console; private ICharMap _charMap; private Encoding _initialOutputEncoding; - private bool _changeOutputEncoding; + private bool _skipOutputEncodingChange; private EngineIntrinsics _engineIntrinsics; private Thread _readKeyThread; private AutoResetEvent _readKeyWaitHandle; @@ -532,7 +532,7 @@ T CallPossibleExternalApplication(Func func) } finally { - if (_changeOutputEncoding) + if (!_skipOutputEncodingChange) { _console.OutputEncoding = Encoding.UTF8; } @@ -652,15 +652,13 @@ private void Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) _initialOutputEncoding = _console.OutputEncoding; - // Don't change the OutputEncoding if already UTF8 or using raster font on Windows - _changeOutputEncoding = _initialOutputEncoding != Encoding.UTF8; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && PlatformWindows.IsConsoleInput() && PlatformWindows.IsUsingRasterFont()) - { - _changeOutputEncoding = false; - } + // Don't change the OutputEncoding if already UTF8, no console, or using raster font on Windows + _skipOutputEncodingChange = _initialOutputEncoding == Encoding.UTF8 + || (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + && PlatformWindows.IsConsoleInput() + && PlatformWindows.IsUsingRasterFont()); - if (_changeOutputEncoding) - { + if (!_skipOutputEncodingChange) { _console.OutputEncoding = Encoding.UTF8; } From b5c8daf750bfa2357f2e3edf1c2d09f0cebeddc4 Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Wed, 10 Oct 2018 09:03:44 -0700 Subject: [PATCH 4/4] Remove unused using --- PSReadLine/ReadLine.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index a3a00a04..57fd6ae0 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -2,7 +2,6 @@ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ -using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; using System; using System.Collections.Generic; using System.Diagnostics;