Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 30 additions & 28 deletions src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2781,7 +2781,36 @@ internal static int LengthInBufferCells(string str, int offset, bool checkEscape
}
}

return str.Length - offset - escapeSequenceAdjustment;
int length = 0;
foreach (char c in str)
{
length += LengthInBufferCells(c);
}

return length - offset - escapeSequenceAdjustment;
}

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 https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
bool isWide = c >= 0x1100 &&
(c <= 0x115f || /* Hangul Jamo init. consonants */
c == 0x2329 || c == 0x232a ||
((uint)(c - 0x2e80) <= (0xa4cf - 0x2e80) &&
c != 0x303f) || /* CJK ... Yi */
((uint)(c - 0xac00) <= (0xd7a3 - 0xac00)) || /* Hangul Syllables */
((uint)(c - 0xf900) <= (0xfaff - 0xf900)) || /* CJK Compatibility Ideographs */
((uint)(c - 0xfe10) <= (0xfe19 - 0xfe10)) || /* Vertical forms */
((uint)(c - 0xfe30) <= (0xfe6f - 0xfe30)) || /* CJK Compatibility Forms */
((uint)(c - 0xff00) <= (0xff60 - 0xff00)) || /* Fullwidth Forms */
((uint)(c - 0xffe0) <= (0xffe6 - 0xffe0)));

// 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);
}

#if !UNIX
Expand Down Expand Up @@ -2950,33 +2979,6 @@ private static HostException CreateHostException(

#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 https://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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ internal virtual int Length(string str)

internal virtual int Length(string str, int offset)
{
return str.Length - offset;
int length = 0;

foreach (char c in str)
{
length += LengthInBufferCells(c);
}

return length - offset;
}

internal virtual int Length(char character) { return 1; }
Expand Down Expand Up @@ -58,6 +65,29 @@ internal virtual int GetTailSplitLength(string str, int offset, int displayCells

#region Helpers

protected static int LengthInBufferCells(char c)
{
// The following is based on http://www.cl.cam.ac.uk/~mgk25/c/wcwidth.c
// which is derived from https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
bool isWide = c >= 0x1100 &&
(c <= 0x115f || /* Hangul Jamo init. consonants */
c == 0x2329 || c == 0x232a ||
((uint)(c - 0x2e80) <= (0xa4cf - 0x2e80) &&
c != 0x303f) || /* CJK ... Yi */
((uint)(c - 0xac00) <= (0xd7a3 - 0xac00)) || /* Hangul Syllables */
((uint)(c - 0xf900) <= (0xfaff - 0xf900)) || /* CJK Compatibility Ideographs */
((uint)(c - 0xfe10) <= (0xfe19 - 0xfe10)) || /* Vertical forms */
((uint)(c - 0xfe30) <= (0xfe6f - 0xfe30)) || /* CJK Compatibility Forms */
((uint)(c - 0xff00) <= (0xff60 - 0xff00)) || /* Fullwidth Forms */
((uint)(c - 0xffe0) <= (0xffe6 - 0xffe0)));

// 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);
}

/// <summary>
/// Given a string and a number of display cells, it computes how many
/// characters would fit starting from the beginning or end of the string.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,24 @@ Describe "Format-List DRT basic functionality" -Tags "CI" {
$result | Should -Match "Name\s*:\s*test.txt"
$result | Should -Match "Length\s*:\s*5"
}

It "Format-List should work with double byte wide chars" {
$obj = [pscustomobject]@{
"哇" = "62";
"dbda" = "KM";
"消息" = "千"
}

$expected = @"

哇 : 62
dbda : KM
消息 : 千



"@

$obj | Format-List | Out-String | Should -BeExactly $expected
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -812,4 +812,23 @@ A Name B
$output = [pscustomobject] @{ one = 1 } | Format-Table @{ l='one'; e='one'; width=10; alignment='center' } | Out-String
$output.Replace("`r","").Replace(" ",".").Replace("`n","^") | Should -BeExactly $expectedTable.Replace("`r","").Replace(" ",".").Replace("`n","^")
}

It "Should be formatted correctly with double byte wide chars" {
$obj = [pscustomobject]@{
"哇" = "62";
"dbda" = "KM";
"消息" = "千"
}

$expected = @"

哇 dbda 消息
-- ---- ----
62 KM 千


"@

$obj | Format-Table | Out-String | Should -BeExactly $expected
}
}