Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion Terminal.Gui/Clipboard/ClipboardBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public string GetClipboardData ()
return string.Empty;
}

return GetClipboardDataImpl ();
return result;
}
catch (NotSupportedException ex)
{
Expand Down
34 changes: 34 additions & 0 deletions Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,40 @@ public void OnMouseEvent (MouseEventArgs a)
/// <param name="ctrl">If <see langword="true"/> simulates the Ctrl key being pressed.</param>
public abstract void SendKeys (char keyChar, ConsoleKey key, bool shift, bool alt, bool ctrl);

internal char _highSurrogate = '\0';

internal bool IsValidInput (KeyCode keyCode, out KeyCode result)
{
result = keyCode;

if (char.IsHighSurrogate ((char)keyCode))
{
_highSurrogate = (char)keyCode;

return false;
}

if (_highSurrogate > 0 && char.IsLowSurrogate ((char)keyCode))
{
result = (KeyCode)new Rune (_highSurrogate, (char)keyCode).Value;
_highSurrogate = '\0';

return true;
}

if (char.IsSurrogate ((char)keyCode))
{
return false;
}

if (_highSurrogate > 0)
{
_highSurrogate = '\0';
}

return true;
}

#endregion

private AnsiRequestScheduler? _scheduler;
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/ConsoleDrivers/CursesDriver/ClipboardImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ protected override string GetClipboardDataImpl ()
}

(int exitCode, string output) =
ClipboardProcessRunner.Process (_powershellPath, "-noprofile -command \"Get-Clipboard\"");
ClipboardProcessRunner.Process (_powershellPath, "-noprofile -command \"[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Clipboard\"");

if (exitCode == 0)
{
Expand Down
7 changes: 5 additions & 2 deletions Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@
while (wch2 == Curses.KeyMouse)
{
// BUGBUG: Fix this nullable issue.
Key kea = null;

Check warning on line 732 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / Parallel Unit Tests (ubuntu-latest)

Converting null literal or possible null value to non-nullable type.

Check warning on line 732 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / build_and_test_debug (windows-latest)

Converting null literal or possible null value to non-nullable type.

Check warning on line 732 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / Non-Parallel Unit Tests (windows-latest)

Converting null literal or possible null value to non-nullable type.

ConsoleKeyInfo [] cki =
{
Expand All @@ -739,7 +739,7 @@
};
code = 0;
// BUGBUG: Fix this nullable issue.
HandleEscSeqResponse (ref code, ref k, ref wch2, ref kea, ref cki);

Check warning on line 742 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / build_and_test_debug (windows-latest)

Possible null reference assignment.

Check warning on line 742 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / Non-Parallel Unit Tests (windows-latest)

Possible null reference assignment.
}

return;
Expand Down Expand Up @@ -797,7 +797,7 @@
}

// BUGBUG: Fix this nullable issue.
Key key = null;

Check warning on line 800 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / build_and_test_debug (windows-latest)

Converting null literal or possible null value to non-nullable type.

Check warning on line 800 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / Non-Parallel Unit Tests (windows-latest)

Converting null literal or possible null value to non-nullable type.

if (code == 0)
{
Expand Down Expand Up @@ -828,7 +828,7 @@
new ((char)KeyCode.Esc, 0, false, false, false), new ((char)wch2, 0, false, false, false)
];
// BUGBUG: Fix this nullable issue.
HandleEscSeqResponse (ref code, ref k, ref wch2, ref key, ref cki);

Check warning on line 831 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / build_and_test_debug (windows-latest)

Possible null reference assignment.

Check warning on line 831 in Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

View workflow job for this annotation

GitHub Actions / Non-Parallel Unit Tests (windows-latest)

Possible null reference assignment.

return;
}
Expand Down Expand Up @@ -924,8 +924,11 @@
k &= ~KeyCode.Space;
}

OnKeyDown (new Key (k));
OnKeyUp (new Key (k));
if (IsValidInput (k, out k))
{
OnKeyDown (new (k));
OnKeyUp (new (k));
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,12 @@ private void MockKeyPressedHandler (ConsoleKeyInfo consoleKeyInfo)
}

KeyCode map = MapKey (consoleKeyInfo);
OnKeyDown (new Key (map));
OnKeyUp (new Key (map));

if (IsValidInput (map, out map))
{
OnKeyDown (new (map));
OnKeyUp (new (map));
}

//OnKeyPressed (new KeyEventArgs (map));
}
Expand Down
7 changes: 5 additions & 2 deletions Terminal.Gui/ConsoleDrivers/NetDriver/NetDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@

// BUGBUG: Fix this nullable issue.
/// <inheritdoc />
internal override IAnsiResponseParser GetParser () => _mainLoopDriver._netEvents.Parser;

Check warning on line 229 in Terminal.Gui/ConsoleDrivers/NetDriver/NetDriver.cs

View workflow job for this annotation

GitHub Actions / build_and_test_debug (macos-latest)

Dereference of a possibly null reference.

Check warning on line 229 in Terminal.Gui/ConsoleDrivers/NetDriver/NetDriver.cs

View workflow job for this annotation

GitHub Actions / Parallel Unit Tests (windows-latest)

Dereference of a possibly null reference.

Check warning on line 229 in Terminal.Gui/ConsoleDrivers/NetDriver/NetDriver.cs

View workflow job for this annotation

GitHub Actions / Parallel Unit Tests (windows-latest)

Dereference of a possibly null reference.
internal NetMainLoop? _mainLoopDriver;

/// <inheritdoc />
Expand Down Expand Up @@ -321,8 +321,11 @@
break;
}

OnKeyDown (new (map));
OnKeyUp (new (map));
if (IsValidInput (map, out map))
{
OnKeyDown (new (map));
OnKeyUp (new (map));
}

break;
case EventType.Mouse:
Expand Down
9 changes: 6 additions & 3 deletions Terminal.Gui/ConsoleDrivers/WindowsDriver/WindowsDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,9 +507,12 @@ internal void ProcessInputAfterParsing (WindowsConsole.InputRecord inputEvent)
break;
}

// This follows convention in NetDriver
OnKeyDown (new Key (map));
OnKeyUp (new Key (map));
if (IsValidInput (map, out map))
{
// This follows convention in NetDriver
OnKeyDown (new (map));
OnKeyUp (new (map));
}

break;

Expand Down
52 changes: 51 additions & 1 deletion Terminal.Gui/Input/Keyboard/Key.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,44 @@ public Key (string str)
KeyCode = key.KeyCode;
}

/// <summary>
/// Constructs a new Key from an integer describing the key.
/// It parses the integer as Key by calling the constructor with a char or calls the constructor with a
/// KeyCode.
/// </summary>
/// <remarks>
/// Don't rely on <paramref name="value"/> passed from <see cref="KeyCode.A"/> to <see cref="KeyCode.Z"/> because
/// would not return the expected keys from 'a' to 'z'.
/// </remarks>
/// <param name="value">The integer describing the key.</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
public Key (int value)
{
if (value < 0 || value > RuneExtensions.MaxUnicodeCodePoint)
{
throw new ArgumentOutOfRangeException (@$"Invalid key value: {value}", nameof (value));
}

if (char.IsSurrogate ((char)value))
{
throw new ArgumentException (@$"Surrogate key not allowed: {value}", nameof (value));
}

Key key;

if (((Rune)value).IsBmp)
{
key = new ((char)value);
}
else
{
key = new ((KeyCode)value);
}

KeyCode = key.KeyCode;
}

/// <summary>
/// The key value as a Rune. This is the actual value of the key pressed, and is independent of the modifiers.
/// Useful for determining if a key represents is a printable character.
Expand Down Expand Up @@ -388,6 +426,11 @@ public static Rune ToRune (KeyCode key)
/// <param name="str"></param>
public static implicit operator Key (string str) { return new (str); }

/// <summary>Cast <see langword="int"/> to a <see cref="Key"/>.</summary>
/// <remarks>See <see cref="Key(int)"/> for more information.</remarks>
/// <param name="value"></param>
public static implicit operator Key (int value) { return new (value); }

/// <summary>Cast a <see cref="Key"/> to a <see langword="string"/>.</summary>
/// <remarks>See <see cref="Key(string)"/> for more information.</remarks>
/// <param name="key"></param>
Expand Down Expand Up @@ -550,7 +593,7 @@ private static string TrimEndSeparator (string input, Rune separator)
// "Ctrl+" (trim)
// "Ctrl++" (trim)

if (input.Length > 1 && new Rune (input [^1]) == separator && new Rune (input [^2]) != separator)
if (input.Length > 1 && !char.IsHighSurrogate (input [^2]) && new Rune (input [^1]) == separator && new Rune (input [^2]) != separator)
{
return input [..^1];
}
Expand Down Expand Up @@ -640,6 +683,13 @@ public static bool TryParse (string text, out Key key)
return false;
}

if (text.Length == 2 && char.IsHighSurrogate (text [^2]) && char.IsLowSurrogate (text [^1]))
{
// It's a surrogate pair and there is no modifiers
key = new (new Rune (text [^2], text [^1]).Value);
return true;
}

// e.g. "Ctrl++"
if ((Rune)text [^1] != separator && parts.Any (string.IsNullOrEmpty))
{
Expand Down
30 changes: 13 additions & 17 deletions Terminal.Gui/Views/TextField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -729,21 +729,11 @@ public virtual void DeleteCharRight ()
/// <param name="useOldCursorPos">Use the previous cursor position.</param>
public void InsertText (string toAdd, bool useOldCursorPos = true)
{
foreach (char ch in toAdd)
foreach (Rune rune in toAdd.EnumerateRunes ())
{
Key key;

try
{
key = ch;
}
catch (Exception)
{
throw new ArgumentException (
$"Cannot insert character '{ch}' because it does not map to a Key"
);
}

// All rune can be mapped to a Key and no exception will throw here because
// EnumerateRunes will replace a surrogate char with the Rune.ReplacementChar
Key key = rune.Value;
InsertText (key, useOldCursorPos);
}
}
Expand Down Expand Up @@ -1072,14 +1062,20 @@ public bool OnTextChanging (CancelEventArgs<string> args)
/// <summary>Paste the selected text from the clipboard.</summary>
public virtual void Paste ()
{
if (ReadOnly || string.IsNullOrEmpty (Clipboard.Contents))
if (ReadOnly)
{
return;
}

string cbTxt = Clipboard.Contents.Split ("\n") [0] ?? "";

if (string.IsNullOrEmpty (cbTxt))
{
return;
}

SetSelectedStartSelectedLength ();
int selStart = _start == -1 ? CursorPosition : _start;
string cbTxt = Clipboard.Contents.Split ("\n") [0] ?? "";

Text = StringExtensions.ToString (_text.GetRange (0, selStart))
+ cbTxt
Expand Down Expand Up @@ -1114,7 +1110,7 @@ public virtual void Paste ()
TextModel.SetCol (ref col, Viewport.Width - 1, cols);
}

int pos = _cursorPosition - ScrollOffset + Math.Min (Viewport.X, 0);
int pos = col - ScrollOffset + Math.Min (Viewport.X, 0);
Move (pos, 0);

return new Point (pos, 0);
Expand Down

This file was deleted.

25 changes: 0 additions & 25 deletions TerminalGuiFluentTesting.Xunit/XunitContextExtensions.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<ItemGroup>
<ProjectReference Include="..\TerminalGuiFluentTestingXunit.Generator\TerminalGuiFluentTestingXunit.Generator.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\TerminalGuiFluentTesting\TerminalGuiFluentTesting.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>

</Project>
Loading
Loading