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;