Explorar o código

Fixes #2653. TextField is using the UTF8 encoding to handle substring not compatible with string. (#2654)

BDisp %!s(int64=2) %!d(string=hai) anos
pai
achega
ef6f355f50

+ 12 - 12
Terminal.Gui/Views/TextField.cs

@@ -1129,8 +1129,8 @@ namespace Terminal.Gui {
 				length = Math.Abs (x + direction <= text.Count ? x + direction - selectedStart : text.Count - selectedStart);
 				length = Math.Abs (x + direction <= text.Count ? x + direction - selectedStart : text.Count - selectedStart);
 				SetSelectedStartSelectedLength ();
 				SetSelectedStartSelectedLength ();
 				if (start > -1 && length > 0) {
 				if (start > -1 && length > 0) {
-					selectedText = length > 0 ? StringExtensions.ToString (text).Substring (
-						start < 0 ? 0 : start, length > text.Count ? text.Count : length) : "";
+					selectedText = length > 0 ? StringExtensions.ToString (text.GetRange (
+						start < 0 ? 0 : start, length > text.Count ? text.Count : length)) : "";
 					if (first > start) {
 					if (first > start) {
 						first = start;
 						first = start;
 					}
 					}
@@ -1198,11 +1198,11 @@ namespace Terminal.Gui {
 			string actualText = Text;
 			string actualText = Text;
 			SetSelectedStartSelectedLength ();
 			SetSelectedStartSelectedLength ();
 			int selStart = SelectedStart > -1 ? start : point;
 			int selStart = SelectedStart > -1 ? start : point;
-			(var _, var len) = TextModel.DisplaySize (text, 0, selStart, false);
-			(var _, var len2) = TextModel.DisplaySize (text, selStart, selStart + length, false);
-			(var _, var len3) = TextModel.DisplaySize (text, selStart + length, actualText.GetRuneCount (), false);
-			var newText = actualText [..len] +
-				actualText.Substring (len + len2, len3);
+			(var size, var _) = TextModel.DisplaySize (text, 0, selStart, false);
+			(var size2, var _) = TextModel.DisplaySize (text, selStart, selStart + length, false);
+			(var size3, var _) = TextModel.DisplaySize (text, selStart + length, actualText.GetRuneCount (), false);
+			var newText = actualText [..size] +
+				actualText.Substring (size + size2, size3);
 			ClearAllSelection ();
 			ClearAllSelection ();
 			point = selStart >= newText.GetRuneCount () ? newText.GetRuneCount () : selStart;
 			point = selStart >= newText.GetRuneCount () ? newText.GetRuneCount () : selStart;
 			return newText.ToRuneList ();
 			return newText.ToRuneList ();
@@ -1220,13 +1220,13 @@ namespace Terminal.Gui {
 			SetSelectedStartSelectedLength ();
 			SetSelectedStartSelectedLength ();
 			int selStart = start == -1 ? CursorPosition : start;
 			int selStart = start == -1 ? CursorPosition : start;
 			string actualText = Text;
 			string actualText = Text;
-			(int _, int len) = TextModel.DisplaySize (text, 0, selStart, false);
-			(var _, var len2) = TextModel.DisplaySize (text, selStart, selStart + length, false);
-			(var _, var len3) = TextModel.DisplaySize (text, selStart + length, actualText.GetRuneCount (), false);
+			(int size, int _) = TextModel.DisplaySize (text, 0, selStart, false);
+			(var size2, var _) = TextModel.DisplaySize (text, selStart, selStart + length, false);
+			(var size3, var _) = TextModel.DisplaySize (text, selStart + length, actualText.GetRuneCount (), false);
 			string cbTxt = Clipboard.Contents.Split ("\n") [0] ?? "";
 			string cbTxt = Clipboard.Contents.Split ("\n") [0] ?? "";
-			Text = actualText [..len] +
+			Text = actualText [..size] +
 				cbTxt +
 				cbTxt +
-				actualText.Substring (len + len2, len3);
+				actualText.Substring (size + size2, size3);
 			point = selStart + cbTxt.GetRuneCount ();
 			point = selStart + cbTxt.GetRuneCount ();
 			ClearAllSelection ();
 			ClearAllSelection ();
 			SetNeedsDisplay ();
 			SetNeedsDisplay ();

+ 13 - 1
UnitTests/Views/TextFieldTests.cs

@@ -914,7 +914,7 @@ namespace Terminal.Gui.ViewsTests {
 		}
 		}
 
 
 		[Fact]
 		[Fact]
-		[AutoInitShutdown(useFakeClipboard:true)]
+		[AutoInitShutdown (useFakeClipboard: true)]
 		public void KeyBindings_Command ()
 		public void KeyBindings_Command ()
 		{
 		{
 			var tf = new TextField ("This is a test.") { Width = 20 };
 			var tf = new TextField ("This is a test.") { Width = 20 };
@@ -1598,5 +1598,17 @@ Les Miśerables", output);
 			Assert.Null (_textField.SelectedText);
 			Assert.Null (_textField.SelectedText);
 			Assert.Equal ("TAB to jump between text fields.", _textField.Text);
 			Assert.Equal ("TAB to jump between text fields.", _textField.Text);
 		}
 		}
+
+		[Fact, TextFieldTestsAutoInitShutdown]
+		public void Copy_Paste_Surrogate_Pairs ()
+		{
+			_textField.Text = "TextField with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!";
+			_textField.SelectAll ();
+			_textField.Cut ();
+			Assert.Equal ("TextField with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!", Application.Driver.Clipboard.GetClipboardData ());
+			Assert.Equal (string.Empty, _textField.Text);
+			_textField.Paste ();
+			Assert.Equal ("TextField with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!", _textField.Text);
+		}
 	}
 	}
 }
 }

+ 14 - 3
UnitTests/Views/TextViewTests.cs

@@ -33,7 +33,7 @@ namespace Terminal.Gui.ViewsTests {
 
 
 				//                   1         2         3 
 				//                   1         2         3 
 				//         01234567890123456789012345678901=32 (Length)
 				//         01234567890123456789012345678901=32 (Length)
-				var buff = Encoding.Unicode.GetBytes(txt);
+				var buff = Encoding.Unicode.GetBytes (txt);
 				var ms = new System.IO.MemoryStream (buff).ToArray ();
 				var ms = new System.IO.MemoryStream (buff).ToArray ();
 				_textView = new TextView () { Width = 30, Height = 10 };
 				_textView = new TextView () { Width = 30, Height = 10 };
 				_textView.Text = Encoding.Unicode.GetString (ms);
 				_textView.Text = Encoding.Unicode.GetString (ms);
@@ -2527,7 +2527,7 @@ line.
 		}
 		}
 
 
 		[Fact]
 		[Fact]
-		[AutoInitShutdown (useFakeClipboard:true)]
+		[AutoInitShutdown (useFakeClipboard: true)]
 		public void KeyBindings_Command ()
 		public void KeyBindings_Command ()
 		{
 		{
 			var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
 			var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
@@ -4657,7 +4657,7 @@ line.
 		}
 		}
 
 
 		[Fact]
 		[Fact]
-		[AutoInitShutdown (useFakeClipboard:true)]
+		[AutoInitShutdown (useFakeClipboard: true)]
 		public void HistoryText_Undo_Redo_Copy_Without_Selection_Multi_Line_Paste ()
 		public void HistoryText_Undo_Redo_Copy_Without_Selection_Multi_Line_Paste ()
 		{
 		{
 			var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
 			var text = "This is the first line.\nThis is the second line.\nThis is the third line.";
@@ -6947,5 +6947,16 @@ This is the second line.
 			Assert.Equal ("TAB to jump between text fields.", _textView.Text);
 			Assert.Equal ("TAB to jump between text fields.", _textView.Text);
 		}
 		}
 
 
+		[Fact, TextViewTestsAutoInitShutdown]
+		public void Copy_Paste_Surrogate_Pairs ()
+		{
+			_textView.Text = "TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!";
+			_textView.SelectAll ();
+			_textView.Cut ();
+			Assert.Equal ("TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!", Application.Driver.Clipboard.GetClipboardData ());
+			Assert.Equal (string.Empty, _textView.Text);
+			_textView.Paste ();
+			Assert.Equal ("TextView with some more test text. Unicode shouldn't 𝔹Aℝ𝔽!", _textView.Text);
+		}
 	}
 	}
 }
 }