diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index 41a679076..7eecf711c 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -15,6 +15,9 @@
runtime; build; native; contentfiles; analyzers
+
+ <_Parameter1>UnitTests
+
true
diff --git a/Terminal.Gui/Views/ScrollBarView.cs b/Terminal.Gui/Views/ScrollBarView.cs
index c89070783..ed08c607a 100644
--- a/Terminal.Gui/Views/ScrollBarView.cs
+++ b/Terminal.Gui/Views/ScrollBarView.cs
@@ -645,7 +645,7 @@ namespace Terminal.Gui {
internal bool CanScroll (int n, out int max, bool isVertical = false)
{
- if (Host == null) {
+ if (Host?.Bounds.IsEmpty != false) {
max = 0;
return false;
}
@@ -660,7 +660,7 @@ namespace Terminal.Gui {
int GetBarsize (bool isVertical)
{
- if (Host == null) {
+ if (Host?.Bounds.IsEmpty != false) {
return 0;
}
return isVertical ?
diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs
index 4b7e78b56..fb6d5a7ab 100644
--- a/Terminal.Gui/Views/TextField.cs
+++ b/Terminal.Gui/Views/TextField.cs
@@ -141,7 +141,7 @@ namespace Terminal.Gui {
if (oldText == value)
return;
- var newText = OnTextChanging (value.Split ("\n") [0]);
+ var newText = OnTextChanging (value.Replace ("\t", "").Split ("\n") [0]);
if (newText.Cancel) {
if (point > text.Count) {
point = text.Count;
diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs
index 74b1b3a83..b6084e4b9 100644
--- a/Terminal.Gui/Views/TextView.cs
+++ b/Terminal.Gui/Views/TextView.cs
@@ -348,7 +348,8 @@ namespace Terminal.Gui {
if (toFind.found) {
toFind.currentPointToFind.X++;
}
- var foundPos = GetFoundPreviousTextPoint (text, toFind.currentPointToFind.Y, matchCase, matchWholeWord, toFind.currentPointToFind);
+ var linesCount = toFind.currentPointToFind.IsEmpty ? lines.Count - 1 : toFind.currentPointToFind.Y;
+ var foundPos = GetFoundPreviousTextPoint (text, linesCount, matchCase, matchWholeWord, toFind.currentPointToFind);
if (!foundPos.found && toFind.currentPointToFind != toFind.startPointToFind) {
foundPos = GetFoundPreviousTextPoint (text, lines.Count - 1, matchCase, matchWholeWord,
new Point (lines [lines.Count - 1].Count, lines.Count));
@@ -365,23 +366,41 @@ namespace Terminal.Gui {
for (int i = 0; i < lines.Count; i++) {
var x = lines [i];
+ var txt = GetText (x);
+ var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString ();
+ var col = txt.IndexOf (matchText);
+ while (col > -1) {
+ if (matchWholeWord && !MatchWholeWord (txt, matchText, col)) {
+ if (col + 1 > txt.Length) {
+ break;
+ }
+ col = txt.IndexOf (matchText, col + 1);
+ continue;
+ }
+ if (col > -1) {
+ if (!found) {
+ found = true;
+ }
+ lines [i] = ReplaceText (x, textToReplace, matchText, col).ToRuneList ();
+ x = lines [i];
+ txt = GetText (x);
+ pos = new Point (col, i);
+ col += (textToReplace.Length - matchText.Length);
+ }
+ if (col + 1 > txt.Length) {
+ break;
+ }
+ col = txt.IndexOf (matchText, col + 1);
+ }
+ }
+
+ string GetText (List x)
+ {
var txt = ustring.Make (x).ToString ();
if (!matchCase) {
txt = txt.ToUpper ();
}
- var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString ();
- var col = txt.IndexOf (matchText);
- if (col > -1 && matchWholeWord && !MatchWholeWord (txt, matchText, col)) {
- continue;
- }
- if (col > -1) {
- if (!found) {
- found = true;
- }
- pos = new Point (col, i);
- lines [i] = ReplaceText (x, textToReplace, matchText, col).ToRuneList ();
- i--;
- }
+ return txt;
}
return (pos, found);
@@ -453,11 +472,11 @@ namespace Terminal.Gui {
start.X = Math.Max (x.Count - 1, 0);
}
var matchText = !matchCase ? text.ToUpper ().ToString () : text.ToString ();
- var col = txt.LastIndexOf (matchText, start.X);
+ var col = txt.LastIndexOf (matchText, toFind.found ? start.X - 1 : start.X);
if (col > -1 && matchWholeWord && !MatchWholeWord (txt, matchText, col)) {
continue;
}
- if (col > -1 && ((i == linesCount && col <= start.X)
+ if (col > -1 && ((i <= linesCount && col <= start.X)
|| i < start.Y)
&& txt.Contains (matchText)) {
return (new Point (col, i), true);
diff --git a/UnitTests/ApplicationTests.cs b/UnitTests/ApplicationTests.cs
index 59406f0f1..4f8d99caf 100644
--- a/UnitTests/ApplicationTests.cs
+++ b/UnitTests/ApplicationTests.cs
@@ -1127,5 +1127,20 @@ namespace Terminal.Gui.Core {
Assert.Null (Application.Top);
}
+
+ [Fact]
+ [AutoInitShutdown]
+ public void Internal_Tests ()
+ {
+ Assert.True (Application._initialized);
+ Assert.NotNull (Application.Top);
+ var rs = Application.Begin (Application.Top);
+ Assert.Equal (Application.Top, rs.Toplevel);
+ Assert.Null (Application.mouseGrabView);
+ Assert.Null (Application.wantContinuousButtonPressedView);
+ Assert.False (Application.DebugDrawBounds);
+ Assert.False (Application.ShowChild (Application.Top));
+ Application.End (Application.Top);
+ }
}
}
diff --git a/UnitTests/ConsoleDriverTests.cs b/UnitTests/ConsoleDriverTests.cs
index f2429e11a..cf03f98cb 100644
--- a/UnitTests/ConsoleDriverTests.cs
+++ b/UnitTests/ConsoleDriverTests.cs
@@ -413,5 +413,12 @@ namespace Terminal.Gui.ConsoleDrivers {
Application.Shutdown ();
}
+
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var cs = new ColorScheme ();
+ Assert.Equal ("", cs.caller);
+ }
}
}
diff --git a/UnitTests/DimTests.cs b/UnitTests/DimTests.cs
index e14354c39..e0a81d550 100644
--- a/UnitTests/DimTests.cs
+++ b/UnitTests/DimTests.cs
@@ -8,7 +8,7 @@ using System.Threading;
using Terminal.Gui;
using Xunit;
-// Alais Console to MockConsole so we don't accidentally use Console
+// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
namespace Terminal.Gui.Core {
@@ -699,7 +699,30 @@ namespace Terminal.Gui.Core {
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
+ }
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var dimFactor = new Dim.DimFactor (0.10F);
+ Assert.Equal (10, dimFactor.Anchor (100));
+
+ var dimAbsolute = new Dim.DimAbsolute (10);
+ Assert.Equal (10, dimAbsolute.Anchor (0));
+
+ var dimFill = new Dim.DimFill (1);
+ Assert.Equal (99, dimFill.Anchor (100));
+
+ var dimCombine = new Dim.DimCombine (true, dimFactor, dimAbsolute);
+ Assert.Equal (dimCombine.left, dimFactor);
+ Assert.Equal (dimCombine.right, dimAbsolute);
+ Assert.Equal (20, dimCombine.Anchor (100));
+
+ var view = new View (new Rect (20, 10, 20, 1));
+ var dimViewHeight = new Dim.DimView (view, 0);
+ Assert.Equal (1, dimViewHeight.Anchor (0));
+ var dimViewWidth = new Dim.DimView (view, 1);
+ Assert.Equal (20, dimViewWidth.Anchor (0));
}
}
}
diff --git a/UnitTests/MainLoopTests.cs b/UnitTests/MainLoopTests.cs
index c85409021..8d4330d11 100644
--- a/UnitTests/MainLoopTests.cs
+++ b/UnitTests/MainLoopTests.cs
@@ -10,7 +10,7 @@ using Terminal.Gui;
using Xunit;
using Xunit.Sdk;
-// Alais Console to MockConsole so we don't accidentally use Console
+// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
namespace Terminal.Gui.Core {
@@ -463,6 +463,43 @@ namespace Terminal.Gui.Core {
Assert.Equal (1, actionCalled);
}
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var testMainloop = new TestMainloop ();
+ var mainloop = new MainLoop (testMainloop);
+ Assert.Empty (mainloop.timeouts);
+ Assert.Empty (mainloop.idleHandlers);
+ Assert.NotNull (new MainLoop.Timeout () {
+ Span = new TimeSpan (),
+ Callback = (_) => true
+ });
+ }
+
+ private class TestMainloop : IMainLoopDriver {
+ private MainLoop mainLoop;
+
+ public bool EventsPending (bool wait)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void MainIteration ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Setup (MainLoop mainLoop)
+ {
+ this.mainLoop = mainLoop;
+ }
+
+ public void Wakeup ()
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
// TODO: EventsPending tests
// - wait = true
// - wait = false
diff --git a/UnitTests/PosTests.cs b/UnitTests/PosTests.cs
index 77e1b382e..aca856084 100644
--- a/UnitTests/PosTests.cs
+++ b/UnitTests/PosTests.cs
@@ -7,7 +7,7 @@ using System.Linq;
using Terminal.Gui;
using Xunit;
-// Alais Console to MockConsole so we don't accidentally use Console
+// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
namespace Terminal.Gui.Core {
@@ -652,5 +652,36 @@ namespace Terminal.Gui.Core {
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
+
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var posFactor = new Pos.PosFactor (0.10F);
+ Assert.Equal (10, posFactor.Anchor (100));
+
+ var posAnchorEnd = new Pos.PosAnchorEnd (1);
+ Assert.Equal (99, posAnchorEnd.Anchor (100));
+
+ var posCenter = new Pos.PosCenter ();
+ Assert.Equal (50, posCenter.Anchor (100));
+
+ var posAbsolute = new Pos.PosAbsolute (10);
+ Assert.Equal (10, posAbsolute.Anchor (0));
+
+ var posCombine = new Pos.PosCombine (true, posFactor, posAbsolute);
+ Assert.Equal (posCombine.left, posFactor);
+ Assert.Equal (posCombine.right, posAbsolute);
+ Assert.Equal (20, posCombine.Anchor (100));
+
+ var view = new View (new Rect (20, 10, 20, 1));
+ var posViewX = new Pos.PosView (view, 0);
+ Assert.Equal (20, posViewX.Anchor (0));
+ var posViewY = new Pos.PosView (view, 1);
+ Assert.Equal (10, posViewY.Anchor (0));
+ var posRight = new Pos.PosView (view, 2);
+ Assert.Equal (40, posRight.Anchor (0));
+ var posViewBottom = new Pos.PosView (view, 3);
+ Assert.Equal (11, posViewBottom.Anchor (0));
+ }
}
}
diff --git a/UnitTests/ScrollBarViewTests.cs b/UnitTests/ScrollBarViewTests.cs
index 382847a04..388f5de88 100644
--- a/UnitTests/ScrollBarViewTests.cs
+++ b/UnitTests/ScrollBarViewTests.cs
@@ -590,5 +590,50 @@ namespace Terminal.Gui.Views {
Assert.Null (exception);
}
+
+ [Fact]
+ [AutoInitShutdown]
+ public void Internal_Tests ()
+ {
+ var top = Application.Top;
+ Assert.Equal (new Rect (0, 0, 80, 25), top.Bounds);
+ var view = new View () { Width = Dim.Fill (), Height = Dim.Fill () };
+ top.Add (view);
+ var sbv = new ScrollBarView (view, true);
+ top.Add (sbv);
+ Assert.Equal (view, sbv.Host);
+ sbv.Size = 40;
+ sbv.Position = 0;
+ sbv.OtherScrollBarView.Size = 100;
+ sbv.OtherScrollBarView.Position = 0;
+ // Host bounds is empty.
+ Assert.False (sbv.CanScroll (10, out int max, sbv.IsVertical));
+ Assert.Equal (0, max);
+ Assert.False (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical));
+ Assert.Equal (0, max);
+ // They are visible but are not drawn.
+ Assert.True (sbv.Visible);
+ Assert.True (sbv.OtherScrollBarView.Visible);
+ top.LayoutSubviews ();
+ // Now the host bounds is not empty.
+ Assert.True (sbv.CanScroll (10, out max, sbv.IsVertical));
+ Assert.Equal (10, max);
+ Assert.True (sbv.OtherScrollBarView.CanScroll (10, out max, sbv.OtherScrollBarView.IsVertical));
+ Assert.Equal (10, max);
+ Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical));
+ Assert.Equal (17, max); // 17+23=40
+ Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical));
+ Assert.Equal (22, max); // 22+78=100
+ Assert.True (sbv.Visible);
+ Assert.True (sbv.OtherScrollBarView.Visible);
+ sbv.KeepContentAlwaysInViewport = false;
+ sbv.OtherScrollBarView.KeepContentAlwaysInViewport = false;
+ Assert.True (sbv.CanScroll (50, out max, sbv.IsVertical));
+ Assert.Equal (40, max);
+ Assert.True (sbv.OtherScrollBarView.CanScroll (150, out max, sbv.OtherScrollBarView.IsVertical));
+ Assert.Equal (100, max);
+ Assert.True (sbv.Visible);
+ Assert.True (sbv.OtherScrollBarView.Visible);
+ }
}
}
diff --git a/UnitTests/TextFieldTests.cs b/UnitTests/TextFieldTests.cs
index 9b0453411..95054eb2f 100644
--- a/UnitTests/TextFieldTests.cs
+++ b/UnitTests/TextFieldTests.cs
@@ -773,5 +773,17 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", tf.Text);
}
+
+ [Fact]
+ [InitShutdown]
+ public void Text_Replaces_Tabs_With_Empty_String ()
+ {
+ _textField.Text = "\t\tTAB to jump between text fields.";
+ Assert.Equal ("TAB to jump between text fields.", _textField.Text);
+ _textField.Text = "";
+ Clipboard.Contents = "\t\tTAB to jump between text fields.";
+ _textField.Paste ();
+ Assert.Equal ("TAB to jump between text fields.", _textField.Text);
+ }
}
}
diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs
index 3ec3b14d0..a06cd3b1c 100644
--- a/UnitTests/TextFormatterTests.cs
+++ b/UnitTests/TextFormatterTests.cs
@@ -2568,5 +2568,15 @@ namespace Terminal.Gui.Core {
// Shutdown must be called to safely clean up Application if Init has been called
Application.Shutdown ();
}
+
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var tf = new TextFormatter ();
+ Assert.Equal (Key.Null, tf.HotKey);
+ tf.HotKey = Key.CtrlMask | Key.Q;
+ Assert.Equal (Key.CtrlMask | Key.Q, tf.HotKey);
+
+ }
}
}
\ No newline at end of file
diff --git a/UnitTests/TextViewTests.cs b/UnitTests/TextViewTests.cs
index 2aa6b97f6..359338791 100644
--- a/UnitTests/TextViewTests.cs
+++ b/UnitTests/TextViewTests.cs
@@ -1942,5 +1942,83 @@ line.
GraphViewTests.AssertDriverContentsAre (expected, output);
}
+
+ [Fact]
+ public void Internal_Tests ()
+ {
+ var txt = "This is a text.";
+ var txtRunes = TextModel.ToRunes (txt);
+ Assert.Equal (txt.Length, txtRunes.Count);
+ Assert.Equal ('T', txtRunes [0]);
+ Assert.Equal ('h', txtRunes [1]);
+ Assert.Equal ('i', txtRunes [2]);
+ Assert.Equal ('s', txtRunes [3]);
+ Assert.Equal (' ', txtRunes [4]);
+ Assert.Equal ('i', txtRunes [5]);
+ Assert.Equal ('s', txtRunes [6]);
+ Assert.Equal (' ', txtRunes [7]);
+ Assert.Equal ('a', txtRunes [8]);
+ Assert.Equal (' ', txtRunes [9]);
+ Assert.Equal ('t', txtRunes [10]);
+ Assert.Equal ('e', txtRunes [11]);
+ Assert.Equal ('x', txtRunes [12]);
+ Assert.Equal ('t', txtRunes [13]);
+ Assert.Equal ('.', txtRunes [^1]);
+
+ int col = 0;
+ Assert.True (TextModel.SetCol (ref col, 80, 79));
+ Assert.False (TextModel.SetCol (ref col, 80, 80));
+
+ var start = 0;
+ var x = 8;
+ Assert.Equal (8, TextModel.GetColFromX (txtRunes, start, x));
+ Assert.Equal ('a', txtRunes [start + x]);
+ start = 1;
+ x = 7;
+ Assert.Equal (7, TextModel.GetColFromX (txtRunes, start, x));
+ Assert.Equal ('a', txtRunes [start + x]);
+
+ Assert.Equal ((15, 15), TextModel.DisplaySize (txtRunes));
+ Assert.Equal ((6, 6), TextModel.DisplaySize (txtRunes, 1, 7));
+
+ Assert.Equal (0, TextModel.CalculateLeftColumn (txtRunes, 0, 7, 8));
+ Assert.Equal (1, TextModel.CalculateLeftColumn (txtRunes, 0, 8, 8));
+ Assert.Equal (2, TextModel.CalculateLeftColumn (txtRunes, 0, 9, 8));
+
+ var tm = new TextModel ();
+ tm.AddLine (0, TextModel.ToRunes ("This is first line."));
+ tm.AddLine (1, TextModel.ToRunes ("This is last line."));
+ Assert.Equal ((new Point (2, 0), true), tm.FindNextText ("is", out bool gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (5, 0), true), tm.FindNextText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (2, 1), true), tm.FindNextText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (5, 1), true), tm.FindNextText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (2, 0), true), tm.FindNextText ("is", out gaveFullTurn));
+ Assert.True (gaveFullTurn);
+ tm.ResetContinuousFind (new Point (0, 0));
+ Assert.Equal ((new Point (5, 1), true), tm.FindPreviousText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (2, 1), true), tm.FindPreviousText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (5, 0), true), tm.FindPreviousText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (2, 0), true), tm.FindPreviousText ("is", out gaveFullTurn));
+ Assert.False (gaveFullTurn);
+ Assert.Equal ((new Point (5, 1), true), tm.FindPreviousText ("is", out gaveFullTurn));
+ Assert.True (gaveFullTurn);
+
+ Assert.Equal ((new Point (9, 1), true), tm.ReplaceAllText ("is", false, false, "really"));
+ Assert.Equal (TextModel.ToRunes ("Threally really first line."), tm.GetLine (0));
+ Assert.Equal (TextModel.ToRunes ("Threally really last line."), tm.GetLine (1));
+ tm = new TextModel ();
+ tm.AddLine (0, TextModel.ToRunes ("This is first line."));
+ tm.AddLine (1, TextModel.ToRunes ("This is last line."));
+ Assert.Equal ((new Point (5, 1), true), tm.ReplaceAllText ("is", false, true, "really"));
+ Assert.Equal (TextModel.ToRunes ("This really first line."), tm.GetLine (0));
+ Assert.Equal (TextModel.ToRunes ("This really last line."), tm.GetLine (1));
+ }
}
}
diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs
index cd4b6a52f..7b73705f8 100644
--- a/UnitTests/ViewTests.cs
+++ b/UnitTests/ViewTests.cs
@@ -1370,5 +1370,47 @@ namespace Terminal.Gui.Views {
Application.Shutdown ();
}
}
+
+ [Fact]
+ [AutoInitShutdown]
+ public void Internal_Tests ()
+ {
+ Assert.Equal (new [] { View.Direction.Forward, View.Direction.Backward },
+ Enum.GetValues (typeof (View.Direction)));
+
+ var rect = new Rect (1, 1, 10, 1);
+ var view = new View (rect);
+ var top = Application.Top;
+ top.Add (view);
+ Assert.Equal (View.Direction.Forward, view.FocusDirection);
+ view.FocusDirection = View.Direction.Backward;
+ Assert.Equal (View.Direction.Backward, view.FocusDirection);
+ Assert.Empty (view.InternalSubviews);
+ Assert.Equal (new Rect (new Point (0, 0), rect.Size), view.NeedDisplay);
+ Assert.True (view.LayoutNeeded);
+ Assert.False (view.ChildNeedsDisplay);
+ Assert.False (view.addingView);
+ view.addingView = true;
+ Assert.True (view.addingView);
+ view.ViewToScreen (0, 0, out int rcol, out int rrow);
+ Assert.Equal (1, rcol);
+ Assert.Equal (1, rrow);
+ Assert.Equal (rect, view.ViewToScreen (view.Bounds));
+ Assert.Equal (top.Bounds, view.ScreenClip (top.Bounds));
+ view.Width = Dim.Fill ();
+ view.Height = Dim.Fill ();
+ Assert.Equal (10, view.Bounds.Width);
+ Assert.Equal (1, view.Bounds.Height);
+ view.SetRelativeLayout (top.Bounds);
+ Assert.Equal (79, view.Bounds.Width);
+ Assert.Equal (24, view.Bounds.Height);
+ bool layoutStarted = false;
+ view.LayoutStarted += (_) => { layoutStarted = true; };
+ view.OnLayoutStarted (null);
+ Assert.True (layoutStarted);
+ view.LayoutComplete += (_) => { layoutStarted = false; };
+ view.OnLayoutComplete (null);
+ Assert.False (layoutStarted);
+ }
}
}