diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs index 0f0c7f5cc4..7b8685778b 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs @@ -2608,109 +2608,6 @@ namespace Microsoft.PowerShell #endregion Window -#if !CORECLR -#region Font Selection - - /// - /// UpdateLocaleSpecificFont is a helper method used to update - /// the console font based on the locale. - /// The default font face used for Powershell Console is Lucida Console. - /// However certain locales dont support Lucida Console font. Hence for such - /// locales the console font is updated to Raster dynamically. - /// - internal static void UpdateLocaleSpecificFont() - { - // Default Powershell shortcut.lnk settings. - const string defaultFontFace = "Lucida Console"; - - // Default CJK locale shortcut.lnk settings. - // Font size is hard coded here to ensure we select a supported size. - // GDI does a poor job of selecting raster font size if the requested - // size is not supported. - const string CJKFontFace = "Terminal"; - const int CJKFontFamily = 48; - const int CJKnFont = 6; - const int CJKFontWidth = 8; - const int CJKFontHeight = 12; - const int CKJFontWeight = 400; - - uint currentLocaleCodePage = (uint)ConsoleControl.NativeMethods.GetConsoleCP(); - - ConsoleHandle handle = ConsoleControl.GetActiveScreenBufferHandle(); - CONSOLE_FONT_INFO_EX fontInfo; - try - { - fontInfo = ConsoleControl.GetConsoleFontInfo(handle); - } - catch (Exception) - { - return; - } - - bool isLucidaConsoleSupportedLocale = CodePageSupportsLucida(currentLocaleCodePage); - - // The Raster font is updated for Japanese and Korean locales if the user has not manually - // altered the default settings. If the default settings are altered then the - // setting chosen by the user would be used. - if (!isLucidaConsoleSupportedLocale && - fontInfo.FontFace.Equals(defaultFontFace, StringComparison.OrdinalIgnoreCase)) - { - fontInfo.FontFace = CJKFontFace; - fontInfo.FontFamily = CJKFontFamily; - fontInfo.nFont = CJKnFont; - fontInfo.FontWidth = CJKFontWidth; - fontInfo.FontHeight = CJKFontHeight; - fontInfo.FontWeight = CKJFontWeight; - - bool result = NativeMethods.SetCurrentConsoleFontEx(handle.DangerousGetHandle(), false, ref fontInfo); - - if (result == false) - { - int err = Marshal.GetLastWin32Error(); - - HostException e = CreateHostException(err, - "SetConsoleFontInfo", - ErrorCategory.ResourceUnavailable, - ConsoleControlStrings.SetConsoleFontInfoExceptionTemplate); - - throw e; - } - } - } - - /// - /// Supported Lucida code pages obtained from Font group. - /// Contacts: alib, judysa, simonda - /// - private static HashSet LucidaSupportedCodePages = new HashSet() - { - 1251, // Latin 1 - 1250, // Latin 2 - 1251, // Cyrillic - 1253, // Greek - 1254, // Turkish - 869, // IBM Greek - 866, // MS-DOS Russian - 865, // MS-DOS Nordic - 863, // MS-DOS Canadian French - 861, // MS-DOS Icelandic - 860, // MS-DOS Portuguese - 857, // IBM Turkish - 855, // IBM Cyrillic - 852, // Latin 2 - 737, // Greek - 850, // WE/Latin 1 - 437 // US - //936, // SimplifiedChinese - According to font team this is *not* supported. - //950 // TraditionalChinese - According to font team this is *not* supported. - }; - private static bool CodePageSupportsLucida(uint currentLocaleCodePage) - { - return LucidaSupportedCodePages.Contains(currentLocaleCodePage); - } - -#endregion -#endif /// /// /// Wrap Win32 WriteConsole @@ -2821,49 +2718,6 @@ namespace Microsoft.PowerShell #region Dealing with CJK #if !UNIX - /// - /// From IsConsoleFullWidth in \windows\core\ntcon\server\dbcs.c - /// Gets the CharSet for a code page - /// - /// - /// The CharSet corresponding to the codePage; defaults to OEM_CHARSET (255) - private static uint CodePageToCharSet(uint codePage) - { - const uint OEM_CHARSET = 255; - // Suppress the PreFAST warning about not using Marshal.GetLastWin32Error() to - // get the error code. -#pragma warning disable 56523 -#if CORECLR // TranslateCharsetInfo exists in an extension API set 'ext-ms-win-gdi-font-l1-1-1.dll', which is not available in NanoServer. - return OEM_CHARSET; -#else - CHARSETINFO csi; - const DWORD TCI_SRCCODEPAGE = 2; - if (!NativeMethods.TranslateCharsetInfo((IntPtr)codePage, out csi, TCI_SRCCODEPAGE)) - { - csi.ciCharset = OEM_CHARSET; - } - return csi.ciCharset; -#endif - } - - // From \windows\core\ntcon\server\dbcs.c - private static bool IsAvailableFarEastCodePage(uint codePage) - { - uint charSet = CodePageToCharSet(codePage); - return IsAnyDBCSCharSet(charSet); - } - - // From \windows\core\ntcon\server\dbcs.c - private static bool IsAnyDBCSCharSet(uint charSet) - { - const uint SHIFTJIS_CHARSET = 128; - const uint HANGUL_CHARSET = 129; - const uint CHINESEBIG5_CHARSET = 136; - const uint GB2312_CHARSET = 134; - return charSet == SHIFTJIS_CHARSET || charSet == HANGUL_CHARSET || - charSet == CHINESEBIG5_CHARSET || charSet == GB2312_CHARSET; - } - /// /// From IsConsoleFullWidth in \windows\core\ntcon\server\dbcs.c /// Precondition: the current code page needs to be a Far East code page. @@ -2944,103 +2798,9 @@ namespace Microsoft.PowerShell /* Han Compatibility Ideographs */ return 2; } - else - { - // GetTextMetrics / GetCharWidth32 exist in an extension API set 'ext-ms-win-gdi-font-l1-1-1.dll', which is not available in NanoServer. -#if !CORECLR - /* Unknown character: need to use GDI*/ - if (hDC == (IntPtr)0) - { - hwnd = NativeMethods.GetConsoleWindow(); - if ((IntPtr)0 == hwnd) - { - int err = Marshal.GetLastWin32Error(); - //Don't throw exception so that output can continue - tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the window handle to the console.", - err); - return 1; - } - hDC = NativeMethods.GetDC(hwnd); - if ((IntPtr)0 == hDC) - { - int err = Marshal.GetLastWin32Error(); - //Don't throw exception so that output can continue - tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the Device Context of the console window.", - err); - return 1; - } - } - bool result = true; - if (!istmInitialized) - { - result = NativeMethods.GetTextMetrics(hDC, out tm); - if (!result) - { - int err = Marshal.GetLastWin32Error(); - //Don't throw exception so that output can continue - tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the Text Metric of the console window's Device Context.", - err); - return 1; - } - istmInitialized = true; - } - int width; - result = NativeMethods.GetCharWidth32(hDC, (uint)c, (uint)c, out width); - if (!result) - { - int err = Marshal.GetLastWin32Error(); - //Don't throw exception so that output can continue - tracer.TraceError("Win32 Error 0x{0:X} occurred when getting the width of a char.", - err); - return 1; - } - if (width >= tm.tmMaxCharWidth) - { - return 2; - } -#endif - } tracer.WriteLine("failed to locate char {0}, return 1", (int)c); return 1; } - - internal static int LengthInBufferCells(char c) - { - uint codePage = NativeMethods.GetConsoleOutputCP(); - return LengthInBufferCells(c, codePage); - } - - /// - /// From IsConsoleFullWidth in \windows\core\ntcon\server\dbcs.c - /// - /// - /// - /// - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", - MessageId = "Microsoft.PowerShell.ConsoleControl+NativeMethods.ReleaseDC(System.IntPtr,System.IntPtr)")] - private static int LengthInBufferCells(char c, uint codePage) - { - if (!IsAvailableFarEastCodePage(codePage)) - { - return 1; - } - HWND hwnd = (HWND)0; - HDC hDC = (HDC)0; - bool istmInitialized = false; - TEXTMETRIC tm = new TEXTMETRIC(); ; - try - { - return LengthInBufferCellsFE(c, ref hwnd, ref hDC, ref istmInitialized, ref tm); - } - finally - { - if (hwnd != (IntPtr)0 && hDC != (IntPtr)0) - { - NativeMethods.ReleaseDC(hwnd, hDC); - } - } - } - #endif // Return the length of a VT100 control sequence character in str starting @@ -3108,38 +2868,7 @@ namespace Microsoft.PowerShell } } -#if UNIX return str.Length - offset - escapeSequenceAdjustment; -#else - uint codePage = NativeMethods.GetConsoleOutputCP(); - if (!IsAvailableFarEastCodePage(codePage)) - { - return str.Length - offset - escapeSequenceAdjustment; - } - - HWND hwnd = (HWND)0; - HDC hDC = (HDC)0; - bool istmInitialized = false; - TEXTMETRIC tm = new TEXTMETRIC(); ; - int length = 0; - try - { - int n = str.Length; - for (int i = offset; i < n; i++) - { - char c = str[i]; - length += LengthInBufferCellsFE(c, ref hwnd, ref hDC, ref istmInitialized, ref tm); - } - return length - escapeSequenceAdjustment; - } - finally - { - if (hwnd != (IntPtr)0 && hDC != (IntPtr)0) - { - NativeMethods.ReleaseDC(hwnd, hDC); - } - } -#endif } #if !UNIX @@ -3321,6 +3050,33 @@ namespace Microsoft.PowerShell #endregion helper +#region + + internal static int LengthInBufferCells(char c) + { + // The following is based on http://www.cl.cam.ac.uk/~mgk25/c/wcwidth.c + // which is derived from http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt + + bool isWide = c >= 0x1100 && + (c <= 0x115f || /* Hangul Jamo init. consonants */ + c == 0x2329 || c == 0x232a || + (c >= 0x2e80 && c <= 0xa4cf && + c != 0x303f) || /* CJK ... Yi */ + (c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */ + (c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */ + (c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */ + (c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */ + (c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */ + (c >= 0xffe0 && c <= 0xffe6)); + // We can ignore these ranges because .Net strings use surrogate pairs + // for this range and we do not handle surrogage pairs. + // (c >= 0x20000 && c <= 0x2fffd) || + // (c >= 0x30000 && c <= 0x3fffd) + return 1 + (isWide ? 1 : 0); + } + +#endregion + #region SendInput internal static void MimicKeyPress(INPUT[] inputs) @@ -3396,9 +3152,6 @@ namespace Microsoft.PowerShell #region Code Page - [DllImport(PinvokeDllNames.GetConsoleCPDllName, SetLastError = false, CharSet = CharSet.Unicode)] - internal static extern uint GetConsoleCP(); - [DllImport(PinvokeDllNames.GetConsoleOutputCPDllName, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern uint GetConsoleOutputCP(); @@ -3413,15 +3166,6 @@ namespace Microsoft.PowerShell [DllImport(PinvokeDllNames.ReleaseDCDllName, SetLastError = false, CharSet = CharSet.Unicode)] internal static extern int ReleaseDC(HWND hwnd, HDC hdc); - [DllImport(PinvokeDllNames.TranslateCharsetInfoDllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern bool TranslateCharsetInfo(IntPtr src, out CHARSETINFO Cs, DWORD options); - - [DllImport(PinvokeDllNames.GetTextMetricsDllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern bool GetTextMetrics(HDC hdc, out TEXTMETRIC tm); - - [DllImport(PinvokeDllNames.GetCharWidth32DllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern bool GetCharWidth32(HDC hdc, uint first, uint last, out int width); - [DllImport(PinvokeDllNames.FlushConsoleInputBufferDllName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool FlushConsoleInputBuffer(NakedWin32Handle consoleInput); @@ -3476,15 +3220,9 @@ namespace Microsoft.PowerShell Pipe }; - [DllImport(PinvokeDllNames.GetFileTypeDllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern FileType GetFileType(NakedWin32Handle fileHandle); - [DllImport(PinvokeDllNames.GetLargestConsoleWindowSizeDllName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern COORD GetLargestConsoleWindowSize(NakedWin32Handle consoleOutput); - [DllImport(PinvokeDllNames.GetStdHandleDllName, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern IntPtr GetStdHandle(int handleId); - [DllImport(PinvokeDllNames.ReadConsoleDllName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool ReadConsole ( @@ -3563,10 +3301,6 @@ namespace Microsoft.PowerShell [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool GetCurrentConsoleFontEx(NakedWin32Handle consoleOutput, bool bMaximumWindow, ref CONSOLE_FONT_INFO_EX consoleFontInfo); - // There is no SetCurrentConsoleFontEx on Core - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern bool SetCurrentConsoleFontEx(NakedWin32Handle consoleOutput, bool bMaximumWindow, ref CONSOLE_FONT_INFO_EX consoleFontInfo); - [DllImport(PinvokeDllNames.GetConsoleCursorInfoDllName, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool GetConsoleCursorInfo(NakedWin32Handle consoleOutput, out CONSOLE_CURSOR_INFO consoleCursorInfo); diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index a58906c913..56d80e6d71 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -251,13 +251,6 @@ namespace Microsoft.PowerShell throw hostException; } -#if !CORECLR - // The default font face used for Powershell Console is Lucida Console. - // However certain CJK locales dont support Lucida Console font. Hence for such - // locales the console font is updated to Raster dynamically. - ConsoleControl.UpdateLocaleSpecificFont(); -#endif - s_theConsoleHost.BindBreakHandler(); PSHost.IsStdOutputRedirected = Console.IsOutputRedirected;