Quellcode durchsuchen

Fixes TextView to deal with CRLF format.

BDisp vor 4 Jahren
Ursprung
Commit
e78bba0cc2
3 geänderte Dateien mit 187 neuen und 83 gelöschten Zeilen
  1. 20 25
      Terminal.Gui/Views/TextView.cs
  2. 23 13
      UICatalog/Scenarios/Editor.cs
  3. 144 45
      UnitTests/TextViewTests.cs

+ 20 - 25
Terminal.Gui/Views/TextView.cs

@@ -40,7 +40,8 @@ namespace Terminal.Gui {
 		{
 			FilePath = file ?? throw new ArgumentNullException (nameof (file));
 
-			LoadStream (File.OpenRead (file));
+			var stream = File.OpenRead (file);
+			LoadStream (stream);
 			return true;
 		}
 
@@ -70,14 +71,21 @@ namespace Terminal.Gui {
 		{
 			var lines = new List<List<Rune>> ();
 			int start = 0, i = 0;
+			var hasCR = false;
+			// ASCII code 13 = Carriage Return.
 			// ASCII code 10 = Line Feed.
 			for (; i < content.Length; i++) {
+				if (content [i] == 13) {
+					hasCR = true;
+					continue;
+				}
 				if (content [i] == 10) {
 					if (i - start > 0)
-						lines.Add (ToRunes (content [start, i]));
+						lines.Add (ToRunes (content [start, hasCR ? i - 1 : i]));
 					else
 						lines.Add (ToRunes (ustring.Empty));
 					start = i + 1;
+					hasCR = false;
 				}
 			}
 			if (i - start >= 0)
@@ -100,16 +108,23 @@ namespace Terminal.Gui {
 			var buff = new BufferedStream (input);
 			int v;
 			var line = new List<byte> ();
+			var wasNewLine = false;
 			while ((v = buff.ReadByte ()) != -1) {
+				if (v == 13) {
+					continue;
+				}
 				if (v == 10) {
 					Append (line);
 					line.Clear ();
+					wasNewLine = true;
 					continue;
 				}
 				line.Add ((byte)v);
+				wasNewLine = false;
 			}
-			if (line.Count > 0)
+			if (line.Count > 0 || wasNewLine)
 				Append (line);
+			buff.Dispose ();
 		}
 
 		public void LoadString (ustring content)
@@ -1245,10 +1260,8 @@ namespace Terminal.Gui {
 		/// <param name="stream">Stream to load the contents from.</param>
 		public void LoadStream (Stream stream)
 		{
-			if (stream == null)
-				throw new ArgumentNullException (nameof (stream));
-			ResetPosition ();
 			model.LoadStream (stream);
+			ResetPosition ();
 			SetNeedsDisplay ();
 		}
 
@@ -1287,12 +1300,8 @@ namespace Terminal.Gui {
 				SetNeedsDisplay (new Rect (0, minRow, Frame.Width, maxRow));
 			}
 			var line = model.GetLine (currentRow);
-			var retreat = 0;
 			var col = 0;
 			if (line.Count > 0) {
-				retreat = Math.Max (SpecialRune (line [Math.Min (Math.Max (currentColumn - leftColumn - 1, 0), line.Count - 1)])
-					? 1 : 0, 0);
-
 				for (int idx = leftColumn; idx < line.Count; idx++) {
 					if (idx >= currentColumn)
 						break;
@@ -1303,7 +1312,6 @@ namespace Terminal.Gui {
 					TextModel.SetCol (ref col, Frame.Width, cols);
 				}
 			}
-			col += retreat;
 			if ((col >= leftColumn || col < Frame.Width)
 				&& topRow <= currentRow && currentRow - topRow + BottomOffset < Frame.Height) {
 				ResetCursorVisibility ();
@@ -1703,10 +1711,8 @@ namespace Terminal.Gui {
 								AddRune (col + i, row, ' ');
 							}
 						}
-					} else if (!SpecialRune (rune)) {
-						AddRune (col, row, rune);
 					} else {
-						col++;
+						AddRune (col, row, rune);
 					}
 					if (!TextModel.SetCol (ref col, bounds.Right, cols)) {
 						break;
@@ -1729,17 +1735,6 @@ namespace Terminal.Gui {
 			PositionCursor ();
 		}
 
-		bool SpecialRune (Rune rune)
-		{
-			switch (rune) {
-			case (uint)Key.Enter:
-			case 0xd:
-				return true;
-			default:
-				return false;
-			}
-		}
-
 		///<inheritdoc/>
 		public override bool CanFocus {
 			get => base.CanFocus;

+ 23 - 13
UICatalog/Scenarios/Editor.cs

@@ -35,6 +35,7 @@ namespace UICatalog {
 					new MenuItem ("_Open", "", () => Open()),
 					new MenuItem ("_Save", "", () => Save()),
 					new MenuItem ("_Save As", "", () => SaveAs()),
+					new MenuItem ("_Close", "", () => Close()),
 					null,
 					new MenuItem ("_Quit", "", () => Quit()),
 				}),
@@ -150,9 +151,9 @@ namespace UICatalog {
 		{
 		}
 
-		private void New ()
+		private void New (bool checkChanges = true)
 		{
-			if (!CanCloseFile ()) {
+			if (checkChanges && !CanCloseFile ()) {
 				return;
 			}
 
@@ -165,9 +166,9 @@ namespace UICatalog {
 		private void LoadFile ()
 		{
 			if (_fileName != null) {
-				// BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
-				//_textView.LoadFile(_fileName);
-				_textView.Text = System.IO.File.ReadAllText (_fileName);
+				// FIXED: BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
+				_textView.LoadFile (_fileName);
+				//_textView.Text = System.IO.File.ReadAllText (_fileName);
 				_originalText = _textView.Text.ToByteArray ();
 				Win.Title = _fileName;
 				_saved = true;
@@ -311,7 +312,7 @@ namespace UICatalog {
 			var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = false };
 			Application.Run (d);
 
-			if (!d.Canceled) {
+			if (!d.Canceled && d.FilePaths.Count > 0) {
 				_fileName = d.FilePaths [0];
 				LoadFile ();
 			}
@@ -320,7 +321,7 @@ namespace UICatalog {
 		private bool Save ()
 		{
 			if (_fileName != null) {
-				// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r 
+				// FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r 
 				// As a result files saved on Windows and then read back will show invalid chars.
 				return SaveFile (Win.Title.ToString (), _fileName);
 			} else {
@@ -358,6 +359,7 @@ namespace UICatalog {
 				Win.Title = title;
 				_fileName = file;
 				System.IO.File.WriteAllText (_fileName, _textView.Text.ToString ());
+				_originalText = _textView.Text.ToByteArray ();
 				_saved = true;
 				MessageBox.Query ("Save File", "File was successfully saved.", "Ok");
 
@@ -369,15 +371,28 @@ namespace UICatalog {
 			return true;
 		}
 
+		private void Close ()
+		{
+			if (!CanCloseFile () || _fileName == null) {
+				return;
+			}
+
+			New (false);
+		}
+
 		private void Quit ()
 		{
+			if (!CanCloseFile ()) {
+				return;
+			}
+
 			Application.RequestStop ();
 		}
 
 		private void CreateDemoFile (string fileName)
 		{
 			var sb = new StringBuilder ();
-			// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
+			// FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
 			sb.Append ("Hello world.\n");
 			sb.Append ("This is a test of the Emergency Broadcast System.\n");
 
@@ -673,10 +688,5 @@ namespace UICatalog {
 
 			return d;
 		}
-
-		public override void Run ()
-		{
-			base.Run ();
-		}
 	}
 }

+ 144 - 45
UnitTests/TextViewTests.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Linq;
 using System.Reflection;
 using Xunit;
 
@@ -42,7 +41,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Changing_Selection_Or_CursorPosition_Update_SelectedLength_And_SelectedText ()
 		{
 			_textView.SelectionStartColumn = 2;
@@ -58,7 +58,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("B to jump between ", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Selection_With_Value_Less_Than_Zero_Changes_To_Zero ()
 		{
 			_textView.SelectionStartColumn = -2;
@@ -69,7 +70,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Selection_With_Value_Greater_Than_Text_Length_Changes_To_Text_Length ()
 		{
 			_textView.CursorPosition = new Point (2, 0);
@@ -81,7 +83,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("B to jump between text fields.", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Selection_With_Empty_Text ()
 		{
 			_textView = new TextView ();
@@ -94,7 +97,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Selection_And_CursorPosition_With_Value_Greater_Than_Text_Length_Changes_Both_To_Text_Length ()
 		{
 			_textView.CursorPosition = new Point (33, 2);
@@ -108,7 +112,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void CursorPosition_With_Value_Less_Than_Zero_Changes_To_Zero ()
 		{
 			_textView.CursorPosition = new Point (-1, -1);
@@ -118,7 +123,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void CursorPosition_With_Value_Greater_Than_Text_Length_Changes_To_Text_Length ()
 		{
 			_textView.CursorPosition = new Point (33, 1);
@@ -128,7 +134,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordForward_With_No_Selection ()
 		{
 			_textView.CursorPosition = new Point (0, 0);
@@ -190,7 +197,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordBackward_With_No_Selection ()
 		{
 			_textView.CursorPosition = new Point (_textView.Text.Length, 0);
@@ -252,7 +260,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordForward_With_Selection ()
 		{
 			_textView.CursorPosition = new Point (0, 0);
@@ -316,7 +325,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordBackward_With_Selection ()
 		{
 			_textView.CursorPosition = new Point (_textView.Text.Length, 0);
@@ -380,7 +390,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordForward_With_The_Same_Values_For_SelectedStart_And_CursorPosition_And_Not_Starting_At_Beginning_Of_The_Text ()
 		{
 			_textView.CursorPosition = new Point (10, 0);
@@ -428,7 +439,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordBackward_With_The_Same_Values_For_SelectedStart_And_CursorPosition_And_Not_Starting_At_Beginning_Of_The_Text ()
 		{
 			_textView.CursorPosition = new Point (10, 0);
@@ -468,7 +480,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordForward_With_No_Selection_And_With_More_Than_Only_One_Whitespace_And_With_Only_One_Letter ()
 		{
 			//                          1         2         3         4         5    
@@ -565,7 +578,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordBackward_With_No_Selection_And_With_More_Than_Only_One_Whitespace_And_With_Only_One_Letter ()
 		{
 			//                          1         2         3         4         5    
@@ -670,7 +684,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordBackward_Multiline_With_Selection ()
 		{
 			//		          4         3          2         1
@@ -784,7 +799,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void WordForward_Multiline_With_Selection ()
 		{
 			//			    1         2          3         4
@@ -897,7 +913,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_To_End_Delete_Forwards_And_Copy_To_The_Clipboard ()
 		{
 			_textView.Text = "This is the first line.\nThis is the second line.";
@@ -932,7 +949,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_To_Start_Delete_Backwards_And_Copy_To_The_Clipboard ()
 		{
 			_textView.Text = "This is the first line.\nThis is the second line.";
@@ -968,7 +986,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_Delete_WordForward ()
 		{
 			_textView.Text = "This is the first line.";
@@ -1011,7 +1030,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_Delete_WordBackward ()
 		{
 			_textView.Text = "This is the first line.";
@@ -1055,7 +1075,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_Delete_WordForward_Multiline ()
 		{
 			_textView.Text = "This is the first line.\nThis is the second line.";
@@ -1134,7 +1155,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Kill_Delete_WordBackward_Multiline ()
 		{
 			_textView.Text = "This is the first line.\nThis is the second line.";
@@ -1213,7 +1235,8 @@ namespace Terminal.Gui.Views {
 			}
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Copy_Or_Cut_Null_If_No_Selection ()
 		{
 			_textView.SelectionStartColumn = 0;
@@ -1224,7 +1247,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Copy_Or_Cut_Not_Null_If_Has_Selection ()
 		{
 			_textView.SelectionStartColumn = 20;
@@ -1236,7 +1260,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Copy_Or_Cut_And_Paste_With_Selection ()
 		{
 			_textView.SelectionStartColumn = 20;
@@ -1254,7 +1279,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("TAB to jump between text fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Copy_Or_Cut_And_Paste_With_No_Selection ()
 		{
 			_textView.SelectionStartColumn = 20;
@@ -1282,7 +1308,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("TAB to jump between texttext fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Cut_Not_Allowed_If_ReadOnly_Is_True ()
 		{
 			_textView.ReadOnly = true;
@@ -1302,7 +1329,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Paste_Always_Clear_The_SelectedText ()
 		{
 			_textView.SelectionStartColumn = 20;
@@ -1314,7 +1342,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("", _textView.SelectedText);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void TextChanged_Event ()
 		{
 			_textView.TextChanged += () => {
@@ -1328,7 +1357,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("changed", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Used_Is_True_By_Default ()
 		{
 			_textView.CursorPosition = new Point (10, 0);
@@ -1343,7 +1373,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("TAB to jumusedp between text fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Used_Is_False ()
 		{
 			_textView.Used = false;
@@ -1359,7 +1390,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("TAB to jumusedtween text fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Copy_Without_Selection ()
 		{
 			_textView.Text = "This is the first line.\nThis is the second line.\n";
@@ -1377,7 +1409,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal (new Point (3, 3), _textView.CursorPosition);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void TabWidth_Setting_To_Zero_Changes_AllowsTab_To_False_If_True ()
 		{
 			Assert.Equal (4, _textView.TabWidth);
@@ -1395,7 +1428,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("TAB to jump between text fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void AllowsTab_Setting_To_True_Changes_TabWidth_To_Default_If_It_Is_Zero ()
 		{
 			_textView.TabWidth = 0;
@@ -1410,7 +1444,8 @@ namespace Terminal.Gui.Views {
 			Assert.True (_textView.Multiline);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void AllowsReturn_Setting_To_True_Changes_Multiline_To_True_If_It_Is_False ()
 		{
 			Assert.True (_textView.AllowsReturn);
@@ -1431,7 +1466,8 @@ namespace Terminal.Gui.Views {
 				"TAB to jump between text fields.", _textView.Text);
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Multiline_Setting_Changes_AllowsReturn_And_AllowsTab_And_Height ()
 		{
 			Assert.True (_textView.Multiline);
@@ -1458,7 +1494,8 @@ namespace Terminal.Gui.Views {
 			Assert.Equal ("Dim.Absolute(10)", _textView.Height.ToString ());
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Tab_Test_Follow_By_BackTab ()
 		{
 			Application.Top.Add (_textView);
@@ -1493,7 +1530,8 @@ namespace Terminal.Gui.Views {
 			Application.Run ();
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void BackTab_Test_Follow_By_Tab ()
 		{
 			Application.Top.Add (_textView);
@@ -1535,7 +1573,8 @@ namespace Terminal.Gui.Views {
 			Application.Run ();
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight ()
 		{
 			Application.Top.Add (_textView);
@@ -1577,7 +1616,8 @@ namespace Terminal.Gui.Views {
 			Application.Run ();
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Tab_Test_Follow_By_BackTab_With_Text ()
 		{
 			Application.Top.Add (_textView);
@@ -1612,7 +1652,8 @@ namespace Terminal.Gui.Views {
 			Application.Run ();
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Tab_Test_Follow_By_Home_And_Then_Follow_By_End_And_Then_Follow_By_BackTab_With_Text ()
 		{
 			Application.Top.Add (_textView);
@@ -1669,7 +1710,8 @@ namespace Terminal.Gui.Views {
 			Application.Run ();
 		}
 
-		[Fact][InitShutdown]
+		[Fact]
+		[InitShutdown]
 		public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight_With_Text ()
 		{
 			Application.Top.Add (_textView);
@@ -1766,12 +1808,69 @@ namespace Terminal.Gui.Views {
 			Assert.Throws<ArgumentException> (() => tv.LoadFile (""));
 		}
 
+		[Fact]
+		public void LoadFile_Throws_If_File_Not_Exist ()
+		{
+			var tv = new TextView ();
+			Assert.Throws<System.IO.FileNotFoundException> (() => tv.LoadFile ("blabla"));
+		}
+
+		[Fact]
+		public void LoadStream_Throws_If_Stream_Is_Null ()
+		{
+			var tv = new TextView ();
+			Assert.Throws<ArgumentNullException> (() => tv.LoadStream (null));
+		}
+
+		[Fact]
+		public void LoadStream_Stream_Is_Empty ()
+		{
+			var tv = new TextView ();
+			tv.LoadStream (new System.IO.MemoryStream ());
+			Assert.Equal ("", tv.Text);
+		}
+
+		[Fact]
+		public void LoadStream_CRLF ()
+		{
+			var text = "This is the first line.\r\nThis is the second line.\r\n";
+			var tv = new TextView ();
+			tv.LoadStream (new System.IO.MemoryStream (System.Text.Encoding.ASCII.GetBytes (text)));
+			Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
+		}
+
+		[Fact]
+		public void LoadStream_LF ()
+		{
+			var text = "This is the first line.\nThis is the second line.\n";
+			var tv = new TextView ();
+			tv.LoadStream (new System.IO.MemoryStream (System.Text.Encoding.ASCII.GetBytes (text)));
+			Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
+		}
+
+		[Fact]
+		public void StringToRunes_Slipts_CRLF ()
+		{
+			var text = "This is the first line.\r\nThis is the second line.\r\n";
+			var tv = new TextView ();
+			tv.Text = text;
+			Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
+		}
+
+		[Fact]
+		public void StringToRunes_Slipts_LF ()
+		{
+			var text = "This is the first line.\nThis is the second line.\n";
+			var tv = new TextView ();
+			tv.Text = text;
+			Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
+		}
+
 		[Fact]
 		public void CloseFile_Throws_If_FilePath_Is_Null ()
 		{
 			var tv = new TextView ();
 			Assert.Throws<ArgumentNullException> (() => tv.CloseFile ());
 		}
-
 	}
 }