浏览代码

Merge branch 'develop' into splitcontainer

Tig 2 年之前
父节点
当前提交
e92d2ccabe

+ 24 - 20
.devcontainer/devcontainer.json

@@ -1,25 +1,29 @@
 {
 {
 	"name": "Terminal.Gui Codespace",
 	"name": "Terminal.Gui Codespace",
-	"image": "mcr.microsoft.com/vscode/devcontainers/dotnet:6.0",
-	"settings": {
-		"terminal.integrated.defaultProfile.linux": "pwsh"
-	},
-	"extensions": [
-		"eamodio.gitlens",
-		"ms-dotnettools.csharp",
-		"VisualStudioExptTeam.vscodeintellicode",
-		"ms-vscode.powershell",
-		"cschleiden.vscode-github-actions",
-		"redhat.vscode-yaml",
-		"bierner.markdown-preview-github-styles",
-		"ban.spellright",
-		"jmrog.vscode-nuget-package-manager",
-		"coenraads.bracket-pair-colorizer",
-		"vscode-icons-team.vscode-icons",
-		"editorconfig.editorconfig",
-		"formulahendry.dotnet-test-explorer"
-	],
-	"postCreateCommand": "dotnet restore && dotnet clean && dotnet build --configuration Release --no-restore && dotnet test --configuration Debug --no-restore --verbosity normal --collect:'XPlat Code Coverage' --settings UnitTests/coverlet.runsettings"
+	"image": "mcr.microsoft.com/vscode/devcontainers/dotnet:7.0",
+	"customizations": {
+		"vscode": {
+			"settings": {
+				"terminal.integrated.defaultProfile.linux": "pwsh"
+			},
+			"extensions": [
+				"eamodio.gitlens",
+				"ms-dotnettools.csharp",
+				"VisualStudioExptTeam.vscodeintellicode",
+				"ms-vscode.powershell",
+				"cschleiden.vscode-github-actions",
+				"redhat.vscode-yaml",
+				"bierner.markdown-preview-github-styles",
+				"ban.spellright",
+				"jmrog.vscode-nuget-package-manager",
+				"coenraads.bracket-pair-colorizer",
+				"vscode-icons-team.vscode-icons",
+				"editorconfig.editorconfig",
+				"formulahendry.dotnet-test-explorer"
+			],
+			"postCreateCommand": "dotnet restore && dotnet clean && dotnet build --configuration Release --no-restore && dotnet test --configuration Debug --no-restore --verbosity normal --collect:'XPlat Code Coverage' --settings UnitTests/coverlet.runsettings"		
+		}
+	}
 }
 }
 
 
 // Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)
 // Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)

+ 1 - 1
ReactiveExample/ReactiveExample.csproj

@@ -3,7 +3,7 @@
     <OutputType>Exe</OutputType>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
     <TargetFramework>net6.0</TargetFramework>
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
-    <!-- In the source tree the version will always be 1.0 for all projects. -->
+    <!-- In the source tree the version will always be 2.0 for all projects. -->
     <!-- Do not modify these. -->
     <!-- Do not modify these. -->
     <AssemblyVersion>1.0</AssemblyVersion>
     <AssemblyVersion>1.0</AssemblyVersion>
     <FileVersion>1.0</FileVersion>
     <FileVersion>1.0</FileVersion>

+ 25 - 37
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -74,14 +74,14 @@ namespace Terminal.Gui {
 					var c = sn [0];
 					var c = sn [0];
 					Curses.mvaddch (crow, ccol - 1, (int)(uint)c);
 					Curses.mvaddch (crow, ccol - 1, (int)(uint)c);
 					contents [crow, ccol - 1, 0] = c;
 					contents [crow, ccol - 1, 0] = c;
-					contents [crow, ccol - 1, 1] = currentAttribute;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
 					contents [crow, ccol - 1, 2] = 1;
 					contents [crow, ccol - 1, 2] = 1;
 
 
 				} else {
 				} else {
 					if (runeWidth < 2 && ccol > 0
 					if (runeWidth < 2 && ccol > 0
 						&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
 						&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
 
 
-						var curAtttib = currentAttribute;
+						var curAtttib = CurrentAttribute;
 						Curses.attrset (contents [crow, ccol - 1, 1]);
 						Curses.attrset (contents [crow, ccol - 1, 1]);
 						Curses.mvaddch (crow, ccol - 1, (int)(uint)' ');
 						Curses.mvaddch (crow, ccol - 1, (int)(uint)' ');
 						contents [crow, ccol - 1, 0] = (int)(uint)' ';
 						contents [crow, ccol - 1, 0] = (int)(uint)' ';
@@ -91,7 +91,7 @@ namespace Terminal.Gui {
 					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
 					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
 						&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
 						&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
 
 
-						var curAtttib = currentAttribute;
+						var curAtttib = CurrentAttribute;
 						Curses.attrset (contents [crow, ccol + 1, 1]);
 						Curses.attrset (contents [crow, ccol + 1, 1]);
 						Curses.mvaddch (crow, ccol + 1, (int)(uint)' ');
 						Curses.mvaddch (crow, ccol + 1, (int)(uint)' ');
 						contents [crow, ccol + 1, 0] = (int)(uint)' ';
 						contents [crow, ccol + 1, 0] = (int)(uint)' ';
@@ -106,25 +106,28 @@ namespace Terminal.Gui {
 						Curses.addch ((int)(uint)rune);
 						Curses.addch ((int)(uint)rune);
 						contents [crow, ccol, 0] = (int)(uint)rune;
 						contents [crow, ccol, 0] = (int)(uint)rune;
 					}
 					}
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 1;
 					contents [crow, ccol, 2] = 1;
 				}
 				}
-			} else
+			} else {
 				needMove = true;
 				needMove = true;
+			}
 
 
 			if (runeWidth < 0 || runeWidth > 0) {
 			if (runeWidth < 0 || runeWidth > 0) {
 				ccol++;
 				ccol++;
 			}
 			}
+			
 			if (runeWidth > 1) {
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 				if (validClip && ccol < Clip.Right) {
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 0;
 					contents [crow, ccol, 2] = 0;
 				}
 				}
 				ccol++;
 				ccol++;
 			}
 			}
 
 
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
 				UpdateScreen ();
+			}
 		}
 		}
 
 
 		public override void AddStr (ustring str)
 		public override void AddStr (ustring str)
@@ -179,12 +182,10 @@ namespace Terminal.Gui {
 
 
 		public override void UpdateScreen () => window.redrawwin ();
 		public override void UpdateScreen () => window.redrawwin ();
 
 
-		Attribute currentAttribute;
-
 		public override void SetAttribute (Attribute c)
 		public override void SetAttribute (Attribute c)
 		{
 		{
-			currentAttribute = c;
-			Curses.attrset (currentAttribute);
+			base.SetAttribute (c);
+			Curses.attrset (CurrentAttribute);
 		}
 		}
 
 
 		public Curses.Window window;
 		public Curses.Window window;
@@ -220,6 +221,7 @@ namespace Terminal.Gui {
 
 
 		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
 		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
 		{
 		{
+			// BUGBUG: This code is never called ?? See Issue #2300
 			int f = (short)foreground;
 			int f = (short)foreground;
 			int b = (short)background;
 			int b = (short)background;
 			var v = colorPairs [f, b];
 			var v = colorPairs [f, b];
@@ -237,6 +239,7 @@ namespace Terminal.Gui {
 		Dictionary<int, int> rawPairs = new Dictionary<int, int> ();
 		Dictionary<int, int> rawPairs = new Dictionary<int, int> ();
 		public override void SetColors (short foreColorId, short backgroundColorId)
 		public override void SetColors (short foreColorId, short backgroundColorId)
 		{
 		{
+			// BUGBUG: This code is never called ?? See Issue #2300
 			int key = ((ushort)foreColorId << 16) | (ushort)backgroundColorId;
 			int key = ((ushort)foreColorId << 16) | (ushort)backgroundColorId;
 			if (!rawPairs.TryGetValue (key, out var v)) {
 			if (!rawPairs.TryGetValue (key, out var v)) {
 				v = MakeColor (foreColorId, backgroundColorId);
 				v = MakeColor (foreColorId, backgroundColorId);
@@ -894,34 +897,18 @@ namespace Terminal.Gui {
 			if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition))
 			if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition))
 				StartReportingMouseMoves ();
 				StartReportingMouseMoves ();
 
 
-			ResizeScreen ();
-			UpdateOffScreen ();
-
-			//HLine = Curses.ACS_HLINE;
-			//VLine = Curses.ACS_VLINE;
-			//Stipple = Curses.ACS_CKBOARD;
-			//Diamond = Curses.ACS_DIAMOND;
-			//ULCorner = Curses.ACS_ULCORNER;
-			//LLCorner = Curses.ACS_LLCORNER;
-			//URCorner = Curses.ACS_URCORNER;
-			//LRCorner = Curses.ACS_LRCORNER;
-			//LeftTee = Curses.ACS_LTEE;
-			//RightTee = Curses.ACS_RTEE;
-			//TopTee = Curses.ACS_TTEE;
-			//BottomTee = Curses.ACS_BTEE;
-			//RightArrow = Curses.ACS_RARROW;
-			//LeftArrow = Curses.ACS_LARROW;
-			//UpArrow = Curses.ACS_UARROW;
-			//DownArrow = Curses.ACS_DARROW;
+			CurrentAttribute = MakeColor (Color.White, Color.Black);
 
 
 			if (Curses.HasColors) {
 			if (Curses.HasColors) {
 				Curses.StartColor ();
 				Curses.StartColor ();
 				Curses.UseDefaultColors ();
 				Curses.UseDefaultColors ();
 
 
-				CreateColors ();
+				InitalizeColorSchemes ();
 			} else {
 			} else {
-				CreateColors (false);
+				InitalizeColorSchemes (false);
 
 
+				// BUGBUG: This is a hack to make the colors work on the Mac?
+				// The new Theme support overwrites these colors, so this is not needed?
 				Colors.TopLevel.Normal = Curses.COLOR_GREEN;
 				Colors.TopLevel.Normal = Curses.COLOR_GREEN;
 				Colors.TopLevel.Focus = Curses.COLOR_WHITE;
 				Colors.TopLevel.Focus = Curses.COLOR_WHITE;
 				Colors.TopLevel.HotNormal = Curses.COLOR_YELLOW;
 				Colors.TopLevel.HotNormal = Curses.COLOR_YELLOW;
@@ -948,6 +935,10 @@ namespace Terminal.Gui {
 				Colors.Error.HotFocus = Curses.A_REVERSE;
 				Colors.Error.HotFocus = Curses.A_REVERSE;
 				Colors.Error.Disabled = Curses.A_BOLD | Curses.COLOR_GRAY;
 				Colors.Error.Disabled = Curses.A_BOLD | Curses.COLOR_GRAY;
 			}
 			}
+
+			ResizeScreen ();
+			UpdateOffScreen ();
+
 		}
 		}
 
 
 		public override void ResizeScreen ()
 		public override void ResizeScreen ()
@@ -1022,6 +1013,8 @@ namespace Terminal.Gui {
 				return Curses.COLOR_YELLOW | Curses.A_BOLD | Curses.COLOR_GRAY;
 				return Curses.COLOR_YELLOW | Curses.A_BOLD | Curses.COLOR_GRAY;
 			case Color.White:
 			case Color.White:
 				return Curses.COLOR_WHITE | Curses.A_BOLD | Curses.COLOR_GRAY;
 				return Curses.COLOR_WHITE | Curses.A_BOLD | Curses.COLOR_GRAY;
+			case Color.Invalid:
+				return Curses.COLOR_BLACK; 
 			}
 			}
 			throw new ArgumentException ("Invalid color code");
 			throw new ArgumentException ("Invalid color code");
 		}
 		}
@@ -1112,11 +1105,6 @@ namespace Terminal.Gui {
 			//Curses.mouseinterval (lastMouseInterval);
 			//Curses.mouseinterval (lastMouseInterval);
 		}
 		}
 
 
-		public override Attribute GetAttribute ()
-		{
-			return currentAttribute;
-		}
-
 		/// <inheritdoc/>
 		/// <inheritdoc/>
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		{
 		{

+ 12 - 16
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -142,7 +142,7 @@ namespace Terminal.Gui {
 					}
 					}
 					var c = sn [0];
 					var c = sn [0];
 					contents [crow, ccol - 1, 0] = c;
 					contents [crow, ccol - 1, 0] = c;
-					contents [crow, ccol - 1, 1] = currentAttribute;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
 					contents [crow, ccol - 1, 2] = 1;
 					contents [crow, ccol - 1, 2] = 1;
 
 
 				} else {
 				} else {
@@ -163,20 +163,22 @@ namespace Terminal.Gui {
 					} else {
 					} else {
 						contents [crow, ccol, 0] = (int)(uint)rune;
 						contents [crow, ccol, 0] = (int)(uint)rune;
 					}
 					}
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 1;
 					contents [crow, ccol, 2] = 1;
 
 
 					dirtyLine [crow] = true;
 					dirtyLine [crow] = true;
 				}
 				}
-			} else
+			} else {
 				needMove = true;
 				needMove = true;
+			}
 
 
 			if (runeWidth < 0 || runeWidth > 0) {
 			if (runeWidth < 0 || runeWidth > 0) {
 				ccol++;
 				ccol++;
 			}
 			}
+
 			if (runeWidth > 1) {
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 				if (validClip && ccol < Clip.Right) {
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 0;
 					contents [crow, ccol, 2] = 0;
 				}
 				}
 				ccol++;
 				ccol++;
@@ -187,8 +189,9 @@ namespace Terminal.Gui {
 			//	if (crow + 1 < Rows)
 			//	if (crow + 1 < Rows)
 			//		crow++;
 			//		crow++;
 			//}
 			//}
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
 				UpdateScreen ();
+			}
 		}
 		}
 
 
 		public override void AddStr (ustring str)
 		public override void AddStr (ustring str)
@@ -226,11 +229,10 @@ namespace Terminal.Gui {
 			rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
 			rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
 			FakeConsole.Clear ();
 			FakeConsole.Clear ();
 			ResizeScreen ();
 			ResizeScreen ();
+			// Call InitalizeColorSchemes before UpdateOffScreen as it references Colors
+			CurrentAttribute = MakeColor (Color.White, Color.Black);
+			InitalizeColorSchemes ();
 			UpdateOffScreen ();
 			UpdateOffScreen ();
-
-			CreateColors ();
-
-			//MockConsole.Clear ();
 		}
 		}
 
 
 		public override Attribute MakeAttribute (Color fore, Color back)
 		public override Attribute MakeAttribute (Color fore, Color back)
@@ -301,10 +303,9 @@ namespace Terminal.Gui {
 			UpdateCursor ();
 			UpdateCursor ();
 		}
 		}
 
 
-		Attribute currentAttribute;
 		public override void SetAttribute (Attribute c)
 		public override void SetAttribute (Attribute c)
 		{
 		{
-			currentAttribute = c;
+			base.SetAttribute (c);
 		}
 		}
 
 
 		public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
 		public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
@@ -493,11 +494,6 @@ namespace Terminal.Gui {
 			keyUpHandler (new KeyEvent (map, keyModifiers));
 			keyUpHandler (new KeyEvent (map, keyModifiers));
 		}
 		}
 
 
-		public override Attribute GetAttribute ()
-		{
-			return currentAttribute;
-		}
-
 		/// <inheritdoc/>
 		/// <inheritdoc/>
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		{
 		{

+ 9 - 11
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -1252,7 +1252,7 @@ namespace Terminal.Gui {
 					}
 					}
 					var c = sn [0];
 					var c = sn [0];
 					contents [crow, ccol - 1, 0] = c;
 					contents [crow, ccol - 1, 0] = c;
-					contents [crow, ccol - 1, 1] = currentAttribute;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
 					contents [crow, ccol - 1, 2] = 1;
 					contents [crow, ccol - 1, 2] = 1;
 
 
 				} else {
 				} else {
@@ -1273,7 +1273,7 @@ namespace Terminal.Gui {
 					} else {
 					} else {
 						contents [crow, ccol, 0] = (int)(uint)rune;
 						contents [crow, ccol, 0] = (int)(uint)rune;
 					}
 					}
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 1;
 					contents [crow, ccol, 2] = 1;
 
 
 				}
 				}
@@ -1283,9 +1283,10 @@ namespace Terminal.Gui {
 			if (runeWidth < 0 || runeWidth > 0) {
 			if (runeWidth < 0 || runeWidth > 0) {
 				ccol++;
 				ccol++;
 			}
 			}
+			
 			if (runeWidth > 1) {
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 				if (validClip && ccol < Clip.Right) {
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 0;
 					contents [crow, ccol, 2] = 0;
 				}
 				}
 				ccol++;
 				ccol++;
@@ -1358,12 +1359,14 @@ namespace Terminal.Gui {
 			cols = Console.WindowWidth;
 			cols = Console.WindowWidth;
 			rows = Console.WindowHeight;
 			rows = Console.WindowHeight;
 
 
+			CurrentAttribute = MakeColor (Color.White, Color.Black);
+			InitalizeColorSchemes ();
+
 			ResizeScreen ();
 			ResizeScreen ();
 			UpdateOffScreen ();
 			UpdateOffScreen ();
 
 
 			StartReportingMouseMoves ();
 			StartReportingMouseMoves ();
 
 
-			CreateColors ();
 
 
 			Clear ();
 			Clear ();
 		}
 		}
@@ -1631,10 +1634,10 @@ namespace Terminal.Gui {
 		{
 		{
 		}
 		}
 
 
-		Attribute currentAttribute;
+
 		public override void SetAttribute (Attribute c)
 		public override void SetAttribute (Attribute c)
 		{
 		{
-			currentAttribute = c;
+			base.SetAttribute (c);
 		}
 		}
 
 
 		public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
 		public ConsoleKeyInfo FromVKPacketToKConsoleKeyInfo (ConsoleKeyInfo consoleKeyInfo)
@@ -1952,11 +1955,6 @@ namespace Terminal.Gui {
 			};
 			};
 		}
 		}
 
 
-		public override Attribute GetAttribute ()
-		{
-			return currentAttribute;
-		}
-
 		/// <inheritdoc/>
 		/// <inheritdoc/>
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		{
 		{

+ 17 - 18
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -116,6 +116,10 @@ namespace Terminal.Gui {
 
 
 		public bool GetCursorVisibility (out CursorVisibility visibility)
 		public bool GetCursorVisibility (out CursorVisibility visibility)
 		{
 		{
+			if (ScreenBuffer == IntPtr.Zero) {
+				visibility = CursorVisibility.Invisible;
+				return false;
+			}
 			if (!GetConsoleCursorInfo (ScreenBuffer, out ConsoleCursorInfo info)) {
 			if (!GetConsoleCursorInfo (ScreenBuffer, out ConsoleCursorInfo info)) {
 				var err = Marshal.GetLastWin32Error ();
 				var err = Marshal.GetLastWin32Error ();
 				if (err != 0) {
 				if (err != 0) {
@@ -1455,13 +1459,13 @@ namespace Terminal.Gui {
 				var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
 				var winSize = WinConsole.GetConsoleOutputWindow (out Point pos);
 				cols = winSize.Width;
 				cols = winSize.Width;
 				rows = winSize.Height;
 				rows = winSize.Height;
-
 				WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
 				WindowsConsole.SmallRect.MakeEmpty (ref damageRegion);
 
 
+				CurrentAttribute = MakeColor (Color.White, Color.Black);
+				InitalizeColorSchemes ();
+				
 				ResizeScreen ();
 				ResizeScreen ();
 				UpdateOffScreen ();
 				UpdateOffScreen ();
-
-				CreateColors ();
 			} catch (Win32Exception e) {
 			} catch (Win32Exception e) {
 				throw new InvalidOperationException ("The Windows Console output window is not available.", e);
 				throw new InvalidOperationException ("The Windows Console output window is not available.", e);
 			}
 			}
@@ -1530,8 +1534,8 @@ namespace Terminal.Gui {
 					var prevPosition = crow * Cols + (ccol - 1);
 					var prevPosition = crow * Cols + (ccol - 1);
 					OutputBuffer [prevPosition].Char.UnicodeChar = c;
 					OutputBuffer [prevPosition].Char.UnicodeChar = c;
 					contents [crow, ccol - 1, 0] = c;
 					contents [crow, ccol - 1, 0] = c;
-					OutputBuffer [prevPosition].Attributes = (ushort)currentAttribute;
-					contents [crow, ccol - 1, 1] = currentAttribute;
+					OutputBuffer [prevPosition].Attributes = (ushort)CurrentAttribute;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
 					contents [crow, ccol - 1, 2] = 1;
 					contents [crow, ccol - 1, 2] = 1;
 					WindowsConsole.SmallRect.Update (ref damageRegion, (short)(ccol - 1), (short)crow);
 					WindowsConsole.SmallRect.Update (ref damageRegion, (short)(ccol - 1), (short)crow);
 				} else {
 				} else {
@@ -1557,8 +1561,8 @@ namespace Terminal.Gui {
 						OutputBuffer [position].Char.UnicodeChar = (char)rune;
 						OutputBuffer [position].Char.UnicodeChar = (char)rune;
 						contents [crow, ccol, 0] = (int)(uint)rune;
 						contents [crow, ccol, 0] = (int)(uint)rune;
 					}
 					}
-					OutputBuffer [position].Attributes = (ushort)currentAttribute;
-					contents [crow, ccol, 1] = currentAttribute;
+					OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 1;
 					contents [crow, ccol, 2] = 1;
 					WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow);
 					WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow);
 				}
 				}
@@ -1567,20 +1571,22 @@ namespace Terminal.Gui {
 			if (runeWidth < 0 || runeWidth > 0) {
 			if (runeWidth < 0 || runeWidth > 0) {
 				ccol++;
 				ccol++;
 			}
 			}
+			
 			if (runeWidth > 1) {
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 				if (validClip && ccol < Clip.Right) {
 					position = GetOutputBufferPosition ();
 					position = GetOutputBufferPosition ();
-					OutputBuffer [position].Attributes = (ushort)currentAttribute;
+					OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
 					OutputBuffer [position].Char.UnicodeChar = (char)0x00;
 					OutputBuffer [position].Char.UnicodeChar = (char)0x00;
 					contents [crow, ccol, 0] = (int)(uint)0x00;
 					contents [crow, ccol, 0] = (int)(uint)0x00;
-					contents [crow, ccol, 1] = currentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
 					contents [crow, ccol, 2] = 0;
 					contents [crow, ccol, 2] = 0;
 				}
 				}
 				ccol++;
 				ccol++;
 			}
 			}
 
 
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
 				UpdateScreen ();
+			}
 		}
 		}
 
 
 		public override void AddStr (ustring str)
 		public override void AddStr (ustring str)
@@ -1589,11 +1595,9 @@ namespace Terminal.Gui {
 				AddRune (rune);
 				AddRune (rune);
 		}
 		}
 
 
-		Attribute currentAttribute;
-
 		public override void SetAttribute (Attribute c)
 		public override void SetAttribute (Attribute c)
 		{
 		{
-			currentAttribute = c;
+			base.SetAttribute (c);
 		}
 		}
 
 
 		public override Attribute MakeColor (Color foreground, Color background)
 		public override Attribute MakeColor (Color foreground, Color background)
@@ -1695,11 +1699,6 @@ namespace Terminal.Gui {
 			WinConsole = null;
 			WinConsole = null;
 		}
 		}
 
 
-		public override Attribute GetAttribute ()
-		{
-			return currentAttribute;
-		}
-
 		/// <inheritdoc/>
 		/// <inheritdoc/>
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		{
 		{

+ 24 - 22
Terminal.Gui/Core/Application.cs

@@ -57,7 +57,7 @@ namespace Terminal.Gui {
 	///   </para>
 	///   </para>
 	/// </remarks>
 	/// </remarks>
 	public static class Application {
 	public static class Application {
-		static Stack<Toplevel> toplevels = new Stack<Toplevel> ();
+		static readonly Stack<Toplevel> toplevels = new Stack<Toplevel> ();
 
 
 		/// <summary>
 		/// <summary>
 		/// The current <see cref="ConsoleDriver"/> in use.
 		/// The current <see cref="ConsoleDriver"/> in use.
@@ -111,28 +111,33 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public static View WantContinuousButtonPressedView { get; private set; }
 		public static View WantContinuousButtonPressedView { get; private set; }
 
 
+		private static bool? _heightAsBuffer;
+
 		/// <summary>
 		/// <summary>
 		/// The current <see cref="ConsoleDriver.HeightAsBuffer"/> used in the terminal.
 		/// The current <see cref="ConsoleDriver.HeightAsBuffer"/> used in the terminal.
 		/// </summary>
 		/// </summary>
+		/// 
 		public static bool HeightAsBuffer {
 		public static bool HeightAsBuffer {
 			get {
 			get {
 				if (Driver == null) {
 				if (Driver == null) {
-					throw new ArgumentNullException ("The driver must be initialized first.");
+					return _heightAsBuffer.HasValue && _heightAsBuffer.Value;
 				}
 				}
 				return Driver.HeightAsBuffer;
 				return Driver.HeightAsBuffer;
 			}
 			}
 			set {
 			set {
+				_heightAsBuffer = value;
 				if (Driver == null) {
 				if (Driver == null) {
-					throw new ArgumentNullException ("The driver must be initialized first.");
+					return;
 				}
 				}
-				Driver.HeightAsBuffer = value;
+
+				Driver.HeightAsBuffer = _heightAsBuffer.Value;
 			}
 			}
 		}
 		}
 
 
 		static Key alternateForwardKey = Key.PageDown | Key.CtrlMask;
 		static Key alternateForwardKey = Key.PageDown | Key.CtrlMask;
 
 
 		/// <summary>
 		/// <summary>
-		/// Alternative key to navigate forwards through all views. Ctrl+Tab is always used.
+		/// Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.
 		/// </summary>
 		/// </summary>
 		public static Key AlternateForwardKey {
 		public static Key AlternateForwardKey {
 			get => alternateForwardKey;
 			get => alternateForwardKey;
@@ -147,7 +152,7 @@ namespace Terminal.Gui {
 
 
 		static void OnAlternateForwardKeyChanged (Key oldKey)
 		static void OnAlternateForwardKeyChanged (Key oldKey)
 		{
 		{
-			foreach (var top in toplevels) {
+			foreach (var top in toplevels.ToArray()) {
 				top.OnAlternateForwardKeyChanged (oldKey);
 				top.OnAlternateForwardKeyChanged (oldKey);
 			}
 			}
 		}
 		}
@@ -155,7 +160,7 @@ namespace Terminal.Gui {
 		static Key alternateBackwardKey = Key.PageUp | Key.CtrlMask;
 		static Key alternateBackwardKey = Key.PageUp | Key.CtrlMask;
 
 
 		/// <summary>
 		/// <summary>
-		/// Alternative key to navigate backwards through all views. Shift+Ctrl+Tab is always used.
+		/// Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.
 		/// </summary>
 		/// </summary>
 		public static Key AlternateBackwardKey {
 		public static Key AlternateBackwardKey {
 			get => alternateBackwardKey;
 			get => alternateBackwardKey;
@@ -170,7 +175,7 @@ namespace Terminal.Gui {
 
 
 		static void OnAlternateBackwardKeyChanged (Key oldKey)
 		static void OnAlternateBackwardKeyChanged (Key oldKey)
 		{
 		{
-			foreach (var top in toplevels) {
+			foreach (var top in toplevels.ToArray()) {
 				top.OnAlternateBackwardKeyChanged (oldKey);
 				top.OnAlternateBackwardKeyChanged (oldKey);
 			}
 			}
 		}
 		}
@@ -200,7 +205,8 @@ namespace Terminal.Gui {
 
 
 		static void OnQuitKeyChanged (Key oldKey)
 		static void OnQuitKeyChanged (Key oldKey)
 		{
 		{
-			foreach (var top in toplevels) {
+			// Duplicate the list so if it changes during enumeration we're safe
+			foreach (var top in toplevels.ToArray()) {
 				top.OnQuitKeyChanged (oldKey);
 				top.OnQuitKeyChanged (oldKey);
 			}
 			}
 		}
 		}
@@ -212,7 +218,7 @@ namespace Terminal.Gui {
 		public static MainLoop MainLoop { get; private set; }
 		public static MainLoop MainLoop { get; private set; }
 
 
 		/// <summary>
 		/// <summary>
-		/// Disable or enable the mouse in this <see cref="Application"/>
+		/// Disable or enable the mouse. The mouse is enabled by default.
 		/// </summary>
 		/// </summary>
 		public static bool IsMouseDisabled { get; set; }
 		public static bool IsMouseDisabled { get; set; }
 
 
@@ -266,7 +272,7 @@ namespace Terminal.Gui {
 		// users use async/await on their code
 		// users use async/await on their code
 		//
 		//
 		class MainLoopSyncContext : SynchronizationContext {
 		class MainLoopSyncContext : SynchronizationContext {
-			MainLoop mainLoop;
+			readonly MainLoop mainLoop;
 
 
 			public MainLoopSyncContext (MainLoop mainLoop)
 			public MainLoopSyncContext (MainLoop mainLoop)
 			{
 			{
@@ -305,9 +311,9 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// If set, it forces the use of the System.Console-based driver.
+		/// If <see langword="true"/>, forces the use of the System.Console-based (see <see cref="NetDriver"/>) driver. The default is <see langword="false"/>.
 		/// </summary>
 		/// </summary>
-		public static bool UseSystemConsole;
+		public static bool UseSystemConsole { get; set; } = false;
 
 
 		// For Unit testing - ignores UseSystemConsole
 		// For Unit testing - ignores UseSystemConsole
 		internal static bool ForceFakeConsole;
 		internal static bool ForceFakeConsole;
@@ -422,6 +428,7 @@ namespace Terminal.Gui {
 			MainLoop = new MainLoop (mainLoopDriver);
 			MainLoop = new MainLoop (mainLoopDriver);
 
 
 			try {
 			try {
+				Driver.HeightAsBuffer = HeightAsBuffer;
 				Driver.Init (TerminalResized);
 				Driver.Init (TerminalResized);
 			} catch (InvalidOperationException ex) {
 			} catch (InvalidOperationException ex) {
 				// This is a case where the driver is unable to initialize the console.
 				// This is a case where the driver is unable to initialize the console.
@@ -933,6 +940,8 @@ namespace Terminal.Gui {
 				if (Top != null && toplevel != Top && !toplevels.Contains (Top)) {
 				if (Top != null && toplevel != Top && !toplevels.Contains (Top)) {
 					Top.Dispose ();
 					Top.Dispose ();
 					Top = null;
 					Top = null;
+				} else if (Top != null && toplevel != Top && toplevels.Contains (Top)) {
+					Top.OnLeave (toplevel);
 				}
 				}
 				if (string.IsNullOrEmpty (toplevel.Id.ToString ())) {
 				if (string.IsNullOrEmpty (toplevel.Id.ToString ())) {
 					var count = 1;
 					var count = 1;
@@ -986,9 +995,7 @@ namespace Terminal.Gui {
 			toplevel.PositionToplevels ();
 			toplevel.PositionToplevels ();
 			toplevel.WillPresent ();
 			toplevel.WillPresent ();
 			if (refreshDriver) {
 			if (refreshDriver) {
-				if (MdiTop != null) {
-					MdiTop.OnChildLoaded (toplevel);
-				}
+				MdiTop?.OnChildLoaded (toplevel);
 				toplevel.OnLoaded ();
 				toplevel.OnLoaded ();
 				Redraw (toplevel);
 				Redraw (toplevel);
 				toplevel.PositionCursor ();
 				toplevel.PositionCursor ();
@@ -1043,6 +1050,7 @@ namespace Terminal.Gui {
 					MdiTop.OnAllChildClosed ();
 					MdiTop.OnAllChildClosed ();
 				} else {
 				} else {
 					SetCurrentAsTop ();
 					SetCurrentAsTop ();
+					Current.OnEnter (Current);
 				}
 				}
 				Refresh ();
 				Refresh ();
 			}
 			}
@@ -1111,12 +1119,6 @@ namespace Terminal.Gui {
 			Driver.Refresh ();
 			Driver.Refresh ();
 		}
 		}
 
 
-		static void Refresh (View view)
-		{
-			view.Redraw (view.Bounds);
-			Driver.Refresh ();
-		}
-
 		/// <summary>
 		/// <summary>
 		/// Triggers a refresh of the entire display.
 		/// Triggers a refresh of the entire display.
 		/// </summary>
 		/// </summary>

+ 45 - 22
Terminal.Gui/Core/Autocomplete/Autocomplete.cs

@@ -324,6 +324,7 @@ namespace Terminal.Gui {
 			if (IsWordChar ((char)kb.Key)) {
 			if (IsWordChar ((char)kb.Key)) {
 				Visible = true;
 				Visible = true;
 				closed = false;
 				closed = false;
+				return false;
 			}
 			}
 
 
 			if (kb.Key == Reopen) {
 			if (kb.Key == Reopen) {
@@ -332,6 +333,9 @@ namespace Terminal.Gui {
 
 
 			if (closed || Suggestions.Count == 0) {
 			if (closed || Suggestions.Count == 0) {
 				Visible = false;
 				Visible = false;
+				if (!closed) {
+					Close ();
+				}
 				return false;
 				return false;
 			}
 			}
 
 
@@ -345,6 +349,17 @@ namespace Terminal.Gui {
 				return true;
 				return true;
 			}
 			}
 
 
+			if (kb.Key == Key.CursorLeft || kb.Key == Key.CursorRight) {
+				GenerateSuggestions (kb.Key == Key.CursorLeft ? -1 : 1);
+				if (Suggestions.Count == 0) {
+					Visible = false;
+					if (!closed) {
+						Close ();
+					}
+				}
+				return false;
+			}
+
 			if (kb.Key == SelectionKey) {
 			if (kb.Key == SelectionKey) {
 				return Select ();
 				return Select ();
 			}
 			}
@@ -368,6 +383,9 @@ namespace Terminal.Gui {
 		public virtual bool MouseEvent (MouseEvent me, bool fromHost = false)
 		public virtual bool MouseEvent (MouseEvent me, bool fromHost = false)
 		{
 		{
 			if (fromHost) {
 			if (fromHost) {
+				if (!Visible) {
+					return false;
+				}
 				GenerateSuggestions ();
 				GenerateSuggestions ();
 				if (Visible && Suggestions.Count == 0) {
 				if (Visible && Suggestions.Count == 0) {
 					Visible = false;
 					Visible = false;
@@ -444,7 +462,8 @@ namespace Terminal.Gui {
 		/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
 		/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
 		/// match with the current cursor position/text in the <see cref="HostControl"/>
 		/// match with the current cursor position/text in the <see cref="HostControl"/>
 		/// </summary>
 		/// </summary>
-		public virtual void GenerateSuggestions ()
+		/// <param name="columnOffset">The column offset.</param>
+		public virtual void GenerateSuggestions (int columnOffset = 0)
 		{
 		{
 			// if there is nothing to pick from
 			// if there is nothing to pick from
 			if (AllSuggestions.Count == 0) {
 			if (AllSuggestions.Count == 0) {
@@ -452,7 +471,7 @@ namespace Terminal.Gui {
 				return;
 				return;
 			}
 			}
 
 
-			var currentWord = GetCurrentWord ();
+			var currentWord = GetCurrentWord (columnOffset);
 
 
 			if (string.IsNullOrWhiteSpace (currentWord)) {
 			if (string.IsNullOrWhiteSpace (currentWord)) {
 				ClearSuggestions ();
 				ClearSuggestions ();
@@ -524,11 +543,12 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Returns the currently selected word from the <see cref="HostControl"/>.
 		/// Returns the currently selected word from the <see cref="HostControl"/>.
 		/// <para>
 		/// <para>
-		/// When overriding this method views can make use of <see cref="IdxToWord(List{Rune}, int)"/>
+		/// When overriding this method views can make use of <see cref="IdxToWord(List{Rune}, int, int)"/>
 		/// </para>
 		/// </para>
 		/// </summary>
 		/// </summary>
+		/// <param name="columnOffset">The column offset.</param>
 		/// <returns></returns>
 		/// <returns></returns>
-		protected abstract string GetCurrentWord ();
+		protected abstract string GetCurrentWord (int columnOffset = 0);
 
 
 		/// <summary>
 		/// <summary>
 		/// <para>
 		/// <para>
@@ -536,37 +556,40 @@ namespace Terminal.Gui {
 		/// or null.  Also returns null if the <paramref name="idx"/> is positioned in the middle of a word.
 		/// or null.  Also returns null if the <paramref name="idx"/> is positioned in the middle of a word.
 		/// </para>
 		/// </para>
 		/// 
 		/// 
-		/// <para>Use this method to determine whether autocomplete should be shown when the cursor is at
-		/// a given point in a line and to get the word from which suggestions should be generated.</para>
+		/// <para>
+		/// Use this method to determine whether autocomplete should be shown when the cursor is at
+		/// a given point in a line and to get the word from which suggestions should be generated.
+		/// Use the <paramref name="columnOffset"/> to indicate if search the word at left (negative),
+		/// at right (positive) or at the current column (zero) which is the default.
+		/// </para>
 		/// </summary>
 		/// </summary>
 		/// <param name="line"></param>
 		/// <param name="line"></param>
 		/// <param name="idx"></param>
 		/// <param name="idx"></param>
+		/// <param name="columnOffset"></param>
 		/// <returns></returns>
 		/// <returns></returns>
-		protected virtual string IdxToWord (List<Rune> line, int idx)
+		protected virtual string IdxToWord (List<Rune> line, int idx, int columnOffset = 0)
 		{
 		{
 			StringBuilder sb = new StringBuilder ();
 			StringBuilder sb = new StringBuilder ();
+			var endIdx = idx;
 
 
-			// do not generate suggestions if the cursor is positioned in the middle of a word
-			bool areMidWord;
-
-			if (idx == line.Count) {
-				// the cursor positioned at the very end of the line
-				areMidWord = false;
-			} else {
-				// we are in the middle of a word if the cursor is over a letter/number
-				areMidWord = IsWordChar (line [idx]);
+			// get the ending word index
+			while (endIdx < line.Count) {
+				if (IsWordChar (line [endIdx])) {
+					endIdx++;
+				} else {
+					break;
+				}
 			}
 			}
 
 
-			// if we are in the middle of a word then there is no way to autocomplete that word
-			if (areMidWord) {
+			// It isn't a word char then there is no way to autocomplete that word
+			if (endIdx == idx && columnOffset != 0) {
 				return null;
 				return null;
 			}
 			}
 
 
 			// we are at the end of a word.  Work out what has been typed so far
 			// we are at the end of a word.  Work out what has been typed so far
-			while (idx-- > 0) {
-
-				if (IsWordChar (line [idx])) {
-					sb.Insert (0, (char)line [idx]);
+			while (endIdx-- > 0) {
+				if (IsWordChar (line [endIdx])) {
+					sb.Insert (0, (char)line [endIdx]);
 				} else {
 				} else {
 					break;
 					break;
 				}
 				}

+ 2 - 1
Terminal.Gui/Core/Autocomplete/IAutocomplete.cs

@@ -109,6 +109,7 @@ namespace Terminal.Gui {
 		/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
 		/// Populates <see cref="Suggestions"/> with all strings in <see cref="AllSuggestions"/> that
 		/// match with the current cursor position/text in the <see cref="HostControl"/>.
 		/// match with the current cursor position/text in the <see cref="HostControl"/>.
 		/// </summary>
 		/// </summary>
-		void GenerateSuggestions ();
+		/// <param name="columnOffset">The column offset. Current (zero - default), left (negative), right (positive).</param>
+		void GenerateSuggestions (int columnOffset = 0);
 	}
 	}
 }
 }

+ 315 - 69
Terminal.Gui/Core/ConsoleDriver.cs

@@ -1,23 +1,22 @@
 //
 //
-// ConsoleDriver.cs: Definition for the Console Driver API
+// ConsoleDriver.cs: Base class for Terminal.Gui ConsoleDriver implementations.
 //
 //
-// Authors:
-//   Miguel de Icaza ([email protected])
-//
-// Define this to enable diagnostics drawing for Window Frames
 using NStack;
 using NStack;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Linq;
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using Unix.Terminal;
 
 
 namespace Terminal.Gui {
 namespace Terminal.Gui {
 	/// <summary>
 	/// <summary>
-	/// Basic colors that can be used to set the foreground and background colors in console applications.
+	/// Colors that can be used to set the foreground and background colors in console applications.
 	/// </summary>
 	/// </summary>
+	/// <remarks>
+	/// The <see cref="Color.Invalid"/> value indicates either no-color has been set or the color is invalid.
+	/// </remarks>
 	public enum Color {
 	public enum Color {
 		/// <summary>
 		/// <summary>
 		/// The black color.
 		/// The black color.
@@ -82,26 +81,112 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// The White color.
 		/// The White color.
 		/// </summary>
 		/// </summary>
-		White
+		White,
+		/// <summary>
+		/// Indicates an invalid or un-set color value. 
+		/// </summary>
+		Invalid = -1
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>
-	/// Attributes are used as elements that contain both a foreground and a background or platform specific features
+	/// 
+	/// </summary>
+	public class TrueColor {
+		/// <summary>
+		/// Red color component.
+		/// </summary>
+		public int Red { get; }
+		/// <summary>
+		/// Green color component.
+		/// </summary>
+		public int Green { get; }
+		/// <summary>
+		/// Blue color component.
+		/// </summary>
+		public int Blue { get; }
+
+		/// <summary>
+		/// Initializes a new instance of the <see cref="TrueColor"/> struct.
+		/// </summary>
+		/// <param name="red"></param>
+		/// <param name="green"></param>
+		/// <param name="blue"></param>
+		public TrueColor (int red, int green, int blue)
+		{
+			Red = red;
+			Green = green;
+			Blue = blue;
+		}
+
+		/// <summary>
+		/// 
+		/// </summary>
+		/// <returns></returns>
+		public Color ToConsoleColor ()
+		{
+			var trueColorMap = new Dictionary<TrueColor, Color> () {
+				{ new TrueColor (0,0,0),Color.Black},
+				{ new TrueColor (0, 0, 0x80),Color.Blue},
+				{ new TrueColor (0, 0x80, 0),Color.Green},
+				{ new TrueColor (0, 0x80, 0x80),Color.Cyan},
+				{ new TrueColor (0x80, 0, 0),Color.Red},
+				{ new TrueColor (0x80, 0, 0x80),Color.Magenta},
+				{ new TrueColor (0xC1, 0x9C, 0x00),Color.Brown},  // TODO confirm this
+				{ new TrueColor (0xC0, 0xC0, 0xC0),Color.Gray},
+				{ new TrueColor (0x80, 0x80, 0x80),Color.DarkGray},
+				{ new TrueColor (0, 0, 0xFF),Color.BrightBlue},
+				{ new TrueColor (0, 0xFF, 0),Color.BrightGreen},
+				{ new TrueColor (0, 0xFF, 0xFF),Color.BrightCyan},
+				{ new TrueColor (0xFF, 0, 0),Color.BrightRed},
+				{ new TrueColor (0xFF, 0, 0xFF),Color.BrightMagenta },
+				{ new TrueColor (0xFF, 0xFF, 0),Color.BrightYellow},
+				{ new TrueColor (0xFF, 0xFF, 0xFF),Color.White},
+				};
+			// Iterate over all colors in the map
+			var distances = trueColorMap.Select (
+							k => Tuple.Create (
+								// the candidate we are considering matching against (RGB)
+								k.Key,
+
+								CalculateDistance (k.Key, this)
+							));
+
+			// get the closest
+			var match = distances.OrderBy (t => t.Item2).First ();
+			return trueColorMap [match.Item1];
+		}
+
+		private float CalculateDistance (TrueColor color1, TrueColor color2)
+		{
+			// use RGB distance
+			return
+				Math.Abs (color1.Red - color2.Red) +
+				Math.Abs (color1.Green - color2.Green) +
+				Math.Abs (color1.Blue - color2.Blue);
+		}
+	}
+
+	/// <summary>
+	/// Attributes are used as elements that contain both a foreground and a background or platform specific features.
 	/// </summary>
 	/// </summary>
 	/// <remarks>
 	/// <remarks>
-	///   <see cref="Attribute"/>s are needed to map colors to terminal capabilities that might lack colors, on color
-	///   scenarios, they encode both the foreground and the background color and are used in the <see cref="ColorScheme"/>
-	///   class to define color schemes that can be used in your application.
+	///   <see cref="Attribute"/>s are needed to map colors to terminal capabilities that might lack colors. 
+	///   They encode both the foreground and the background color and are used in the <see cref="ColorScheme"/>
+	///   class to define color schemes that can be used in an application.
 	/// </remarks>
 	/// </remarks>
 	public struct Attribute {
 	public struct Attribute {
 		/// <summary>
 		/// <summary>
-		/// The color attribute value.
+		/// The <see cref="ConsoleDriver"/>-specific color attribute value. If <see cref="Initialized"/> is <see langword="false"/> 
+		/// the value of this property is invalid (typcially because the Attribute was created before a driver was loaded)
+		/// and the attribute should be re-made (see <see cref="Make(Color, Color)"/>) before it is used.
 		/// </summary>
 		/// </summary>
 		public int Value { get; }
 		public int Value { get; }
+
 		/// <summary>
 		/// <summary>
 		/// The foreground color.
 		/// The foreground color.
 		/// </summary>
 		/// </summary>
 		public Color Foreground { get; }
 		public Color Foreground { get; }
+
 		/// <summary>
 		/// <summary>
 		/// The background color.
 		/// The background color.
 		/// </summary>
 		/// </summary>
@@ -114,11 +199,13 @@ namespace Terminal.Gui {
 		/// <param name="value">Value.</param>
 		/// <param name="value">Value.</param>
 		public Attribute (int value)
 		public Attribute (int value)
 		{
 		{
-			Color foreground = default;
-			Color background = default;
+			Color foreground = Color.Invalid;
+			Color background = Color.Invalid;
 
 
+			Initialized = false;
 			if (Application.Driver != null) {
 			if (Application.Driver != null) {
 				Application.Driver.GetColors (value, out foreground, out background);
 				Application.Driver.GetColors (value, out foreground, out background);
+				Initialized = true;
 			}
 			}
 			Value = value;
 			Value = value;
 			Foreground = foreground;
 			Foreground = foreground;
@@ -136,6 +223,7 @@ namespace Terminal.Gui {
 			Value = value;
 			Value = value;
 			Foreground = foreground;
 			Foreground = foreground;
 			Background = background;
 			Background = background;
+			Initialized = true;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -145,7 +233,9 @@ namespace Terminal.Gui {
 		/// <param name="background">Background</param>
 		/// <param name="background">Background</param>
 		public Attribute (Color foreground = new Color (), Color background = new Color ())
 		public Attribute (Color foreground = new Color (), Color background = new Color ())
 		{
 		{
-			Value = Make (foreground, background).Value;
+			var make = Make (foreground, background);
+			Initialized = make.Initialized;
+			Value = make.Value;
 			Foreground = foreground;
 			Foreground = foreground;
 			Background = background;
 			Background = background;
 		}
 		}
@@ -158,29 +248,42 @@ namespace Terminal.Gui {
 		public Attribute (Color color) : this (color, color) { }
 		public Attribute (Color color) : this (color, color) { }
 
 
 		/// <summary>
 		/// <summary>
-		/// Implicit conversion from an <see cref="Attribute"/> to the underlying Int32 representation
+		/// Implicit conversion from an <see cref="Attribute"/> to the underlying, driver-specific, Int32 representation
+		/// of the color.
 		/// </summary>
 		/// </summary>
-		/// <returns>The integer value stored in the attribute.</returns>
+		/// <returns>The driver-specific color value stored in the attribute.</returns>
 		/// <param name="c">The attribute to convert</param>
 		/// <param name="c">The attribute to convert</param>
-		public static implicit operator int (Attribute c) => c.Value;
+		public static implicit operator int (Attribute c)
+		{
+			if (!c.Initialized) throw new InvalidOperationException ("Attribute: Attributes must be initialized by a driver before use.");
+			return c.Value;
+		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Implicitly convert an integer value into an <see cref="Attribute"/>
+		/// Implicitly convert an driver-specific color value into an <see cref="Attribute"/>
 		/// </summary>
 		/// </summary>
-		/// <returns>An attribute with the specified integer value.</returns>
+		/// <returns>An attribute with the specified driver-specific color value.</returns>
 		/// <param name="v">value</param>
 		/// <param name="v">value</param>
 		public static implicit operator Attribute (int v) => new Attribute (v);
 		public static implicit operator Attribute (int v) => new Attribute (v);
 
 
 		/// <summary>
 		/// <summary>
-		/// Creates an <see cref="Attribute"/> from the specified foreground and background.
+		/// Creates an <see cref="Attribute"/> from the specified foreground and background colors.
 		/// </summary>
 		/// </summary>
-		/// <returns>The make.</returns>
+		/// <remarks>
+		/// If a <see cref="ConsoleDriver"/> has not been loaded (<c>Application.Driver == null</c>) this
+		/// method will return an attribute with <see cref="Initialized"/> set to  <see langword="false"/>.
+		/// </remarks>
+		/// <returns>The new attribute.</returns>
 		/// <param name="foreground">Foreground color to use.</param>
 		/// <param name="foreground">Foreground color to use.</param>
 		/// <param name="background">Background color to use.</param>
 		/// <param name="background">Background color to use.</param>
 		public static Attribute Make (Color foreground, Color background)
 		public static Attribute Make (Color foreground, Color background)
 		{
 		{
-			if (Application.Driver == null)
-				throw new InvalidOperationException ("The Application has not been initialized");
+			if (Application.Driver == null) {
+				// Create the attribute, but show it's not been initialized
+				var a = new Attribute (-1, foreground, background);
+				a.Initialized = false;
+				return a;
+			}
 			return Application.Driver.MakeAttribute (foreground, background);
 			return Application.Driver.MakeAttribute (foreground, background);
 		}
 		}
 
 
@@ -194,45 +297,114 @@ namespace Terminal.Gui {
 				throw new InvalidOperationException ("The Application has not been initialized");
 				throw new InvalidOperationException ("The Application has not been initialized");
 			return Application.Driver.GetAttribute ();
 			return Application.Driver.GetAttribute ();
 		}
 		}
+
+		/// <summary>
+		/// If <see langword="true"/> the attribute has been initialzed by a <see cref="ConsoleDriver"/> and 
+		/// thus has <see cref="Value"/> that is valid for that driver. If <see langword="false"/> the <see cref="Foreground"/>
+		/// and <see cref="Background"/> colors may have been set (see <see cref="Color.Invalid"/>) but
+		/// the attribute has not been mapped to a <see cref="ConsoleDriver"/> specific color value. 
+		/// </summary>
+		/// <remarks>
+		/// Attributes that have not been initialized must eventually be initialized before being passed to a driver.
+		/// </remarks>
+		public bool Initialized { get; internal set; }
+
+		/// <summary>
+		/// Returns <see langword="true"/> if the Atrribute is valid (both foreground and background have valid color values).
+		/// </summary>
+		/// <returns></returns>
+		public bool HasValidColors {
+			get {
+				return Foreground != Color.Invalid && Background != Color.Invalid;
+			}
+		}
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>
-	/// Color scheme definitions, they cover some common scenarios and are used
-	/// typically in containers such as <see cref="Window"/> and <see cref="FrameView"/> to set the scheme that is used by all the
-	/// views contained inside.
+	/// Defines the color <see cref="Attribute"/>s for common visible elements in a <see cref="View"/>. 
+	/// Containers such as <see cref="Window"/> and <see cref="FrameView"/> use <see cref="ColorScheme"/> to determine
+	/// the colors used by sub-views.
 	/// </summary>
 	/// </summary>
+	/// <remarks>
+	/// See also: <see cref="Colors.ColorSchemes"/>.
+	/// </remarks>
 	public class ColorScheme : IEquatable<ColorScheme> {
 	public class ColorScheme : IEquatable<ColorScheme> {
-		Attribute _normal;
-		Attribute _focus;
-		Attribute _hotNormal;
-		Attribute _hotFocus;
-		Attribute _disabled;
-		internal string caller = "";
+		Attribute _normal = new Attribute(Color.White, Color.Black);
+		Attribute _focus = new Attribute (Color.White, Color.Black);
+		Attribute _hotNormal = new Attribute (Color.White, Color.Black);
+		Attribute _hotFocus = new Attribute (Color.White, Color.Black);
+		Attribute _disabled = new Attribute (Color.White, Color.Black);
 
 
 		/// <summary>
 		/// <summary>
-		/// The default color for text, when the view is not focused.
+		/// Used by <see cref="Colors.SetColorScheme(ColorScheme, string)"/> and <see cref="Colors.GetColorScheme(string)"/> to track which ColorScheme 
+		/// is being accessed.
 		/// </summary>
 		/// </summary>
-		public Attribute Normal { get { return _normal; } set { _normal = value; } }
+		internal string schemeBeingSet = "";
 
 
 		/// <summary>
 		/// <summary>
-		/// The color for text when the view has the focus.
+		/// The foreground and background color for text when the view is not focused, hot, or disabled.
 		/// </summary>
 		/// </summary>
-		public Attribute Focus { get { return _focus; } set { _focus = value; } }
+		public Attribute Normal {
+			get { return _normal; }
+			set {
+				if (!value.HasValidColors) {
+					return;
+				}
+				_normal = value;
+			}
+		}
 
 
 		/// <summary>
 		/// <summary>
-		/// The color for the hotkey when a view is not focused
+		/// The foreground and background color for text when the view has the focus.
 		/// </summary>
 		/// </summary>
-		public Attribute HotNormal { get { return _hotNormal; } set { _hotNormal = value; } }
+		public Attribute Focus {
+			get { return _focus; }
+			set {
+				if (!value.HasValidColors) {
+					return;
+				}
+				_focus = value;
+			}
+		}
 
 
 		/// <summary>
 		/// <summary>
-		/// The color for the hotkey when the view is focused.
+		/// The foreground and background color for text when the view is highlighted (hot).
 		/// </summary>
 		/// </summary>
-		public Attribute HotFocus { get { return _hotFocus; } set { _hotFocus = value; } }
+		public Attribute HotNormal {
+			get { return _hotNormal; }
+			set {
+				if (!value.HasValidColors) {
+					return;
+				}
+				_hotNormal = value;
+			}
+		}
+
+		/// <summary>
+		/// The foreground and background color for text when the view is highlighted (hot) and has focus.
+		/// </summary>
+		public Attribute HotFocus {
+			get { return _hotFocus; }
+			set {
+				if (!value.HasValidColors) {
+					return;
+				}
+				_hotFocus = value;
+			}
+		}
 
 
 		/// <summary>
 		/// <summary>
-		/// The default color for text, when the view is disabled.
+		/// The default foreground and background color for text, when the view is disabled.
 		/// </summary>
 		/// </summary>
-		public Attribute Disabled { get { return _disabled; } set { _disabled = value; } }
+		public Attribute Disabled {
+			get { return _disabled; }
+			set {
+				if (!value.HasValidColors) {
+					return;
+				}
+				_disabled = value;
+			}
+		}
 
 
 		/// <summary>
 		/// <summary>
 		/// Compares two <see cref="ColorScheme"/> objects for equality.
 		/// Compares two <see cref="ColorScheme"/> objects for equality.
@@ -295,20 +467,67 @@ namespace Terminal.Gui {
 		{
 		{
 			return !(left == right);
 			return !(left == right);
 		}
 		}
+
+		internal void Initialize ()
+		{
+			// If the new scheme was created before a driver was loaded, we need to re-make
+			// the attributes
+			if (!_normal.Initialized) {
+				_normal = new Attribute (_normal.Foreground, _normal.Background);
+			}
+			if (!_focus.Initialized) {
+				_focus = new Attribute (_focus.Foreground, _focus.Background);
+			}
+			if (!_hotNormal.Initialized) {
+				_hotNormal = new Attribute (_hotNormal.Foreground, _hotNormal.Background);
+			}
+			if (!_hotFocus.Initialized) {
+				_hotFocus = new Attribute (_hotFocus.Foreground, _hotFocus.Background);
+			}
+			if (!_disabled.Initialized) {
+				_disabled = new Attribute (_disabled.Foreground, _disabled.Background);
+			}
+		}
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>
 	/// The default <see cref="ColorScheme"/>s for the application.
 	/// The default <see cref="ColorScheme"/>s for the application.
 	/// </summary>
 	/// </summary>
+	/// <remarks>
+	/// This property can be set in a Theme to change the default <see cref="Colors"/> for the application.
+	/// </remarks>
 	public static class Colors {
 	public static class Colors {
+		private class SchemeNameComparerIgnoreCase : IEqualityComparer<string> {
+			public bool Equals (string x, string y)
+			{
+				if (x != null && y != null) {
+					return x.ToLowerInvariant () == y.ToLowerInvariant ();
+				}
+				return false;
+			}
+
+			public int GetHashCode (string obj)
+			{
+				return obj.ToLowerInvariant ().GetHashCode ();
+			}
+		}
+
 		static Colors ()
 		static Colors ()
+		{
+			ColorSchemes = Create ();
+		}
+
+		/// <summary>
+		/// Creates a new dictionary of new <see cref="ColorScheme"/> objects.
+		/// </summary>
+		public static Dictionary<string, ColorScheme> Create () 
 		{
 		{
 			// Use reflection to dynamically create the default set of ColorSchemes from the list defined 
 			// Use reflection to dynamically create the default set of ColorSchemes from the list defined 
 			// by the class. 
 			// by the class. 
-			ColorSchemes = typeof (Colors).GetProperties ()
+			return typeof (Colors).GetProperties ()
 				.Where (p => p.PropertyType == typeof (ColorScheme))
 				.Where (p => p.PropertyType == typeof (ColorScheme))
-				.Select (p => new KeyValuePair<string, ColorScheme> (p.Name, new ColorScheme ())) // (ColorScheme)p.GetValue (p)))
-				.ToDictionary (t => t.Key, t => t.Value);
+				.Select (p => new KeyValuePair<string, ColorScheme> (p.Name, new ColorScheme()))
+				.ToDictionary (t => t.Key, t => t.Value, comparer: new SchemeNameComparerIgnoreCase ());
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -361,21 +580,21 @@ namespace Terminal.Gui {
 		/// </remarks>
 		/// </remarks>
 		public static ColorScheme Error { get => GetColorScheme (); set => SetColorScheme (value); }
 		public static ColorScheme Error { get => GetColorScheme (); set => SetColorScheme (value); }
 
 
-		static ColorScheme GetColorScheme ([CallerMemberName] string callerMemberName = null)
+		static ColorScheme GetColorScheme ([CallerMemberName] string schemeBeingSet = null)
 		{
 		{
-			return ColorSchemes [callerMemberName];
+			return ColorSchemes [schemeBeingSet];
 		}
 		}
 
 
-		static void SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string callerMemberName = null)
+		static void SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string schemeBeingSet = null)
 		{
 		{
-			ColorSchemes [callerMemberName] = colorScheme;
-			colorScheme.caller = callerMemberName;
+			ColorSchemes [schemeBeingSet] = colorScheme;
+			colorScheme.schemeBeingSet = schemeBeingSet;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
 		/// Provides the defined <see cref="ColorScheme"/>s.
 		/// Provides the defined <see cref="ColorScheme"/>s.
 		/// </summary>
 		/// </summary>
-		public static Dictionary<string, ColorScheme> ColorSchemes { get; }
+		public static Dictionary<string, ColorScheme> ColorSchemes { get; private set; }
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>
@@ -659,13 +878,35 @@ namespace Terminal.Gui {
 		public abstract void UpdateScreen ();
 		public abstract void UpdateScreen ();
 
 
 		/// <summary>
 		/// <summary>
-		/// Selects the specified attribute as the attribute to use for future calls to AddRune, AddString.
+		/// The current attribute the driver is using. 
 		/// </summary>
 		/// </summary>
+		public virtual Attribute CurrentAttribute {
+			get => currentAttribute; 
+			set {
+				if (!value.Initialized && value.HasValidColors && Application.Driver != null) {
+					CurrentAttribute = Application.Driver.MakeAttribute (value.Foreground, value.Background);
+					return;
+				}
+				if (!value.Initialized) Debug.WriteLine ("ConsoleDriver.CurrentAttribute: Attributes must be initialized before use.");
+
+				currentAttribute = value;
+			}
+		}
+
+		/// <summary>
+		/// Selects the specified attribute as the attribute to use for future calls to AddRune and AddString.
+		/// </summary>
+		/// <remarks>
+		/// Implementations should call <c>base.SetAttribute(c)</c>.
+		/// </remarks>
 		/// <param name="c">C.</param>
 		/// <param name="c">C.</param>
-		public abstract void SetAttribute (Attribute c);
+		public virtual void SetAttribute (Attribute c)
+		{
+			CurrentAttribute = c;
+		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Set Colors from limit sets of colors.
+		/// Set Colors from limit sets of colors. Not implemented by any driver: See Issue #2300.
 		/// </summary>
 		/// </summary>
 		/// <param name="foreground">Foreground.</param>
 		/// <param name="foreground">Foreground.</param>
 		/// <param name="background">Background.</param>
 		/// <param name="background">Background.</param>
@@ -675,7 +916,7 @@ namespace Terminal.Gui {
 		// that independently with the R, G, B values.
 		// that independently with the R, G, B values.
 		/// <summary>
 		/// <summary>
 		/// Advanced uses - set colors to any pre-set pairs, you would need to init_color
 		/// Advanced uses - set colors to any pre-set pairs, you would need to init_color
-		/// that independently with the R, G, B values.
+		/// that independently with the R, G, B values. Not implemented by any driver: See Issue #2300.
 		/// </summary>
 		/// </summary>
 		/// <param name="foregroundColorId">Foreground color identifier.</param>
 		/// <param name="foregroundColorId">Foreground color identifier.</param>
 		/// <param name="backgroundColorId">Background color identifier.</param>
 		/// <param name="backgroundColorId">Background color identifier.</param>
@@ -998,12 +1239,13 @@ namespace Terminal.Gui {
 		public abstract void StopReportingMouseMoves ();
 		public abstract void StopReportingMouseMoves ();
 
 
 		/// <summary>
 		/// <summary>
-		/// Disables the cooked event processing from the mouse driver.  At startup, it is assumed mouse events are cooked.
+		/// Disables the cooked event processing from the mouse driver. 
+		/// At startup, it is assumed mouse events are cooked. Not implemented by any driver: See Issue #2300.
 		/// </summary>
 		/// </summary>
 		public abstract void UncookMouse ();
 		public abstract void UncookMouse ();
 
 
 		/// <summary>
 		/// <summary>
-		/// Enables the cooked event processing from the mouse driver
+		/// Enables the cooked event processing from the mouse driver. Not implemented by any driver: See Issue #2300.
 		/// </summary>
 		/// </summary>
 		public abstract void CookMouse ();
 		public abstract void CookMouse ();
 
 
@@ -1196,6 +1438,7 @@ namespace Terminal.Gui {
 		/// Lower right rounded corner
 		/// Lower right rounded corner
 		/// </summary>
 		/// </summary>
 		public Rune LRRCorner = '\u256f';
 		public Rune LRRCorner = '\u256f';
+		private Attribute currentAttribute;
 
 
 		/// <summary>
 		/// <summary>
 		/// Make the attribute for the foreground and background colors.
 		/// Make the attribute for the foreground and background colors.
@@ -1209,7 +1452,7 @@ namespace Terminal.Gui {
 		/// Gets the current <see cref="Attribute"/>.
 		/// Gets the current <see cref="Attribute"/>.
 		/// </summary>
 		/// </summary>
 		/// <returns>The current attribute.</returns>
 		/// <returns>The current attribute.</returns>
-		public abstract Attribute GetAttribute ();
+		public Attribute GetAttribute () => CurrentAttribute;
 
 
 		/// <summary>
 		/// <summary>
 		/// Make the <see cref="Colors"/> for the <see cref="ColorScheme"/>.
 		/// Make the <see cref="Colors"/> for the <see cref="ColorScheme"/>.
@@ -1220,21 +1463,24 @@ namespace Terminal.Gui {
 		public abstract Attribute MakeColor (Color foreground, Color background);
 		public abstract Attribute MakeColor (Color foreground, Color background);
 
 
 		/// <summary>
 		/// <summary>
-		/// Create all <see cref="Colors"/> with the <see cref="ColorScheme"/> for the console driver.
+		/// Ensures all <see cref="Attribute"/>s in <see cref="Colors.ColorSchemes"/> are correclty 
+		/// initalized by the driver.
 		/// </summary>
 		/// </summary>
-		/// <param name="hasColors">Flag indicating if colors are supported.</param>
-		public void CreateColors (bool hasColors = true)
+		/// <param name="supportsColors">Flag indicating if colors are supported (not used).</param>
+		public void InitalizeColorSchemes (bool supportsColors = true)
 		{
 		{
-			Colors.TopLevel = new ColorScheme ();
-			Colors.Base = new ColorScheme ();
-			Colors.Dialog = new ColorScheme ();
-			Colors.Menu = new ColorScheme ();
-			Colors.Error = new ColorScheme ();
+			// Ensure all Attributes are initlaized by the driver
+			foreach (var s in Colors.ColorSchemes) {
+				s.Value.Initialize ();
+			}
 
 
-			if (!hasColors) {
+			if (!supportsColors) {
 				return;
 				return;
 			}
 			}
 
 
+
+			// Define the default color theme only if the user has not defined one.
+			
 			Colors.TopLevel.Normal = MakeColor (Color.BrightGreen, Color.Black);
 			Colors.TopLevel.Normal = MakeColor (Color.BrightGreen, Color.Black);
 			Colors.TopLevel.Focus = MakeColor (Color.White, Color.Cyan);
 			Colors.TopLevel.Focus = MakeColor (Color.White, Color.Cyan);
 			Colors.TopLevel.HotNormal = MakeColor (Color.Brown, Color.Black);
 			Colors.TopLevel.HotNormal = MakeColor (Color.Brown, Color.Black);

+ 12 - 1
Terminal.Gui/Core/Toplevel.cs

@@ -821,7 +821,6 @@ namespace Terminal.Gui {
 
 
 			if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && dragPosition.HasValue) {
 			if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) && dragPosition.HasValue) {
 				Application.UngrabMouse ();
 				Application.UngrabMouse ();
-				Driver.UncookMouse ();
 				dragPosition = null;
 				dragPosition = null;
 			}
 			}
 
 
@@ -960,6 +959,18 @@ namespace Terminal.Gui {
 			}
 			}
 			return false;
 			return false;
 		}
 		}
+
+		///<inheritdoc/>
+		public override bool OnEnter (View view)
+		{
+			return MostFocused?.OnEnter (view) ?? base.OnEnter (view);
+		}
+
+		///<inheritdoc/>
+		public override bool OnLeave (View view)
+		{
+			return MostFocused?.OnLeave (view) ?? base.OnLeave (view);
+		}
 	}
 	}
 
 
 	/// <summary>
 	/// <summary>

+ 2 - 1
Terminal.Gui/Core/View.cs

@@ -1447,8 +1447,9 @@ namespace Terminal.Gui {
 		/// </summary>
 		/// </summary>
 		public virtual ColorScheme ColorScheme {
 		public virtual ColorScheme ColorScheme {
 			get {
 			get {
-				if (colorScheme == null)
+				if (colorScheme == null) {
 					return SuperView?.ColorScheme;
 					return SuperView?.ColorScheme;
+				}
 				return colorScheme;
 				return colorScheme;
 			}
 			}
 			set {
 			set {

+ 4 - 3
Terminal.Gui/Terminal.Gui.csproj

@@ -10,9 +10,10 @@
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- In the source tree the version will always be 1.0 for all projects. -->
     <!-- In the source tree the version will always be 1.0 for all projects. -->
     <!-- Do not modify these. Do NOT commit after manually running `dotnet-gitversion /updateprojectfiles` -->
     <!-- Do not modify these. Do NOT commit after manually running `dotnet-gitversion /updateprojectfiles` -->
-    <AssemblyVersion>1.9</AssemblyVersion>
-    <Version>1.9</Version>
-    <InformationalVersion>1.9</InformationalVersion>
+    <AssemblyVersion>1.0</AssemblyVersion>
+    <FileVersion>1.0</FileVersion>
+    <Version>1.0</Version>
+    <InformationalVersion>1.0</InformationalVersion>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
     <PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />

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

@@ -1346,12 +1346,12 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		/// <inheritdoc/>
 		/// <inheritdoc/>
-		protected override string GetCurrentWord ()
+		protected override string GetCurrentWord (int columnOffset = 0)
 		{
 		{
 			var host = (TextField)HostControl;
 			var host = (TextField)HostControl;
 			var currentLine = host.Text.ToRuneList ();
 			var currentLine = host.Text.ToRuneList ();
-			var cursorPosition = Math.Min (host.CursorPosition, currentLine.Count);
-			return IdxToWord (currentLine, cursorPosition);
+			var cursorPosition = Math.Min (host.CursorPosition + columnOffset, currentLine.Count);
+			return IdxToWord (currentLine, cursorPosition, columnOffset);
 		}
 		}
 
 
 		/// <inheritdoc/>
 		/// <inheritdoc/>

+ 23 - 15
Terminal.Gui/Views/TextView.cs

@@ -2035,6 +2035,16 @@ namespace Terminal.Gui {
 			return base.OnEnter (view);
 			return base.OnEnter (view);
 		}
 		}
 
 
+		///<inheritdoc/>
+		public override bool OnLeave (View view)
+		{
+			if (Application.MouseGrabView != null && Application.MouseGrabView == this) {
+				Application.UngrabMouse ();
+			}
+
+			return base.OnLeave (view);
+		}
+
 		// Returns an encoded region start..end (top 32 bits are the row, low32 the column)
 		// Returns an encoded region start..end (top 32 bits are the row, low32 the column)
 		void GetEncodedRegionBounds (out long start, out long end,
 		void GetEncodedRegionBounds (out long start, out long end,
 			int? startRow = null, int? startCol = null, int? cRow = null, int? cCol = null)
 			int? startRow = null, int? startCol = null, int? cRow = null, int? cCol = null)
@@ -2437,6 +2447,10 @@ namespace Terminal.Gui {
 
 
 			PositionCursor ();
 			PositionCursor ();
 
 
+			if (clickWithSelecting) {
+				clickWithSelecting = false;
+				return;
+			}
 			if (SelectedLength > 0)
 			if (SelectedLength > 0)
 				return;
 				return;
 
 
@@ -2667,8 +2681,10 @@ namespace Terminal.Gui {
 				need = true;
 				need = true;
 			} else if ((wordWrap && leftColumn > 0) || (dSize.size + RightOffset < Frame.Width + offB.width
 			} else if ((wordWrap && leftColumn > 0) || (dSize.size + RightOffset < Frame.Width + offB.width
 				&& tSize.size + RightOffset < Frame.Width + offB.width)) {
 				&& tSize.size + RightOffset < Frame.Width + offB.width)) {
-				leftColumn = 0;
-				need = true;
+				if (leftColumn > 0) {
+					leftColumn = 0;
+					need = true;
+				}
 			}
 			}
 
 
 			if (currentRow < topRow) {
 			if (currentRow < topRow) {
@@ -4269,6 +4285,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		bool isButtonShift;
 		bool isButtonShift;
+		bool clickWithSelecting;
 
 
 		///<inheritdoc/>
 		///<inheritdoc/>
 		public override bool MouseEvent (MouseEvent ev)
 		public override bool MouseEvent (MouseEvent ev)
@@ -4362,6 +4379,7 @@ namespace Terminal.Gui {
 				columnTrack = currentColumn;
 				columnTrack = currentColumn;
 			} else if (ev.Flags.HasFlag (MouseFlags.Button1Pressed)) {
 			} else if (ev.Flags.HasFlag (MouseFlags.Button1Pressed)) {
 				if (shiftSelecting) {
 				if (shiftSelecting) {
+					clickWithSelecting = true;
 					StopSelecting ();
 					StopSelecting ();
 				}
 				}
 				ProcessMouseClick (ev, out _);
 				ProcessMouseClick (ev, out _);
@@ -4447,16 +4465,6 @@ namespace Terminal.Gui {
 			line = r;
 			line = r;
 		}
 		}
 
 
-		///<inheritdoc/>
-		public override bool OnLeave (View view)
-		{
-			if (Application.MouseGrabView != null && Application.MouseGrabView == this) {
-				Application.UngrabMouse ();
-			}
-
-			return base.OnLeave (view);
-		}
-
 		/// <summary>
 		/// <summary>
 		/// Allows clearing the <see cref="HistoryText.HistoryTextItem"/> items updating the original text.
 		/// Allows clearing the <see cref="HistoryText.HistoryTextItem"/> items updating the original text.
 		/// </summary>
 		/// </summary>
@@ -4475,12 +4483,12 @@ namespace Terminal.Gui {
 	public class TextViewAutocomplete : Autocomplete {
 	public class TextViewAutocomplete : Autocomplete {
 
 
 		///<inheritdoc/>
 		///<inheritdoc/>
-		protected override string GetCurrentWord ()
+		protected override string GetCurrentWord (int columnOffset = 0)
 		{
 		{
 			var host = (TextView)HostControl;
 			var host = (TextView)HostControl;
 			var currentLine = host.GetCurrentLine ();
 			var currentLine = host.GetCurrentLine ();
-			var cursorPosition = Math.Min (host.CurrentColumn, currentLine.Count);
-			return IdxToWord (currentLine, cursorPosition);
+			var cursorPosition = Math.Min (host.CurrentColumn + columnOffset, currentLine.Count);
+			return IdxToWord (currentLine, cursorPosition, columnOffset);
 		}
 		}
 
 
 		/// <inheritdoc/>
 		/// <inheritdoc/>

+ 1 - 1
UICatalog/UICatalog.cs

@@ -163,7 +163,7 @@ namespace UICatalog {
 
 
 			public UICatalogTopLevel ()
 			public UICatalogTopLevel ()
 			{
 			{
-				ColorScheme = _colorScheme;
+				ColorScheme = _colorScheme = Colors.Base;
 				MenuBar = new MenuBar (new MenuBarItem [] {
 				MenuBar = new MenuBar (new MenuBarItem [] {
 					new MenuBarItem ("_File", new MenuItem [] {
 					new MenuBarItem ("_File", new MenuItem [] {
 						new MenuItem ("_Quit", "Quit UI Catalog", () => RequestStop(), null, null, Key.Q | Key.CtrlMask)
 						new MenuItem ("_Quit", "Quit UI Catalog", () => RequestStop(), null, null, Key.Q | Key.CtrlMask)

+ 1 - 1
UICatalog/UICatalog.csproj

@@ -5,7 +5,7 @@
     <LangVersion>8.0</LangVersion>
     <LangVersion>8.0</LangVersion>
     <StartupObject>UICatalog.UICatalogApp</StartupObject>
     <StartupObject>UICatalog.UICatalogApp</StartupObject>
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
-    <!-- In the source tree the version will always be 1.0 for all projects. -->
+    <!-- In the source tree the version will always be 2.0 for all projects. -->
     <!-- Do not modify these. -->
     <!-- Do not modify these. -->
     <AssemblyVersion>1.0</AssemblyVersion>
     <AssemblyVersion>1.0</AssemblyVersion>
     <FileVersion>1.0</FileVersion>
     <FileVersion>1.0</FileVersion>

+ 0 - 1
UnitTests/Application/ApplicationTests.cs

@@ -24,7 +24,6 @@ namespace Terminal.Gui.ApplicationTests {
 			Assert.Null (Application.Driver);
 			Assert.Null (Application.Driver);
 			Assert.Null (Application.Top);
 			Assert.Null (Application.Top);
 			Assert.Null (Application.Current);
 			Assert.Null (Application.Current);
-			Assert.Throws<ArgumentNullException> (() => Application.HeightAsBuffer == true);
 			Assert.Null (Application.MainLoop);
 			Assert.Null (Application.MainLoop);
 			Assert.Null (Application.Iteration);
 			Assert.Null (Application.Iteration);
 			Assert.Null (Application.RootMouseEvent);
 			Assert.Null (Application.RootMouseEvent);

+ 69 - 5
UnitTests/Drivers/AttributeTests.cs

@@ -85,7 +85,34 @@ namespace Terminal.Gui.DriverTests {
 		}
 		}
 
 
 		[Fact]
 		[Fact]
-		public void Make_Asserts_IfNotInit ()
+		public void Implicit_Assign_NoDriver ()
+		{
+
+			var attr = new Attribute ();
+
+			var fg = new Color ();
+			fg = Color.Red;
+
+			var bg = new Color ();
+			bg = Color.Blue;
+
+			// Test conversion to int
+			attr = new Attribute (fg, bg);
+			int value_implicit = (int)attr.Value;
+			Assert.False (attr.Initialized);
+
+			Assert.Equal (-1, value_implicit);
+			Assert.False (attr.Initialized);
+
+			// Test conversion from int
+			attr = -1;
+			Assert.Equal (-1, attr.Value);
+			Assert.False (attr.Initialized);
+
+		}
+
+		[Fact]
+		public void Make_SetsNotInitialized_NoDriver ()
 		{
 		{
 			var fg = new Color ();
 			var fg = new Color ();
 			fg = Color.Red;
 			fg = Color.Red;
@@ -93,7 +120,9 @@ namespace Terminal.Gui.DriverTests {
 			var bg = new Color ();
 			var bg = new Color ();
 			bg = Color.Blue;
 			bg = Color.Blue;
 
 
-			Assert.Throws<InvalidOperationException> (() => Attribute.Make (fg, bg));
+			var a = Attribute.Make (fg, bg);
+
+			Assert.False (a.Initialized);
 		}
 		}
 
 
 		[Fact]
 		[Fact]
@@ -109,8 +138,8 @@ namespace Terminal.Gui.DriverTests {
 			var bg = new Color ();
 			var bg = new Color ();
 			bg = Color.Blue;
 			bg = Color.Blue;
 
 
-			var attr =  Attribute.Make (fg, bg);
-
+			var attr = Attribute.Make (fg, bg);
+			Assert.True (attr.Initialized);
 			Assert.Equal (fg, attr.Foreground);
 			Assert.Equal (fg, attr.Foreground);
 			Assert.Equal (bg, attr.Background);
 			Assert.Equal (bg, attr.Background);
 
 
@@ -119,7 +148,23 @@ namespace Terminal.Gui.DriverTests {
 		}
 		}
 
 
 		[Fact]
 		[Fact]
-		public void Get_Asserts_IfNotInit ()
+		public void Make_Creates_NoDriver ()
+		{
+
+			var fg = new Color ();
+			fg = Color.Red;
+
+			var bg = new Color ();
+			bg = Color.Blue;
+
+			var attr = Attribute.Make (fg, bg);
+			Assert.False (attr.Initialized);
+			Assert.Equal (fg, attr.Foreground);
+			Assert.Equal (bg, attr.Background);
+		}
+
+		[Fact]
+		public void Get_Asserts_NoDriver ()
 		{
 		{
 			Assert.Throws<InvalidOperationException> (() => Attribute.Get ());
 			Assert.Throws<InvalidOperationException> (() => Attribute.Get ());
 		}
 		}
@@ -163,5 +208,24 @@ namespace Terminal.Gui.DriverTests {
 			Assert.Equal (Color.Red, fg);
 			Assert.Equal (Color.Red, fg);
 			Assert.Equal (Color.Green, bg);
 			Assert.Equal (Color.Green, bg);
 		}
 		}
+
+		[Fact]
+		public void IsValid_Tests ()
+		{
+			var attr = new Attribute ();
+			Assert.True (attr.HasValidColors);
+
+			attr = new Attribute (Color.Red, Color.Green);
+			Assert.True (attr.HasValidColors);
+
+			attr = new Attribute (Color.Red, Color.Invalid);
+			Assert.False (attr.HasValidColors);
+
+			attr = new Attribute (Color.Invalid, Color.Green);
+			Assert.False (attr.HasValidColors);
+
+			attr = new Attribute (Color.Invalid, Color.Invalid);
+			Assert.False (attr.HasValidColors);
+		}
 	}
 	}
 }
 }

+ 9 - 0
UnitTests/Drivers/ColorTests.cs

@@ -35,5 +35,14 @@ namespace Terminal.Gui.DriverTests {
 			Application.Shutdown ();
 			Application.Shutdown ();
 		}
 		}
 
 
+		[Fact, AutoInitShutdown]
+		public void ColorScheme_New ()
+		{
+			var scheme = new ColorScheme ();
+			var lbl = new Label ();
+			lbl.ColorScheme = scheme;
+			lbl.Redraw (lbl.Bounds);
+		}
+
 	}
 	}
 }
 }

+ 3 - 2
UnitTests/Drivers/ConsoleDriverTests.cs

@@ -319,7 +319,7 @@ namespace Terminal.Gui.DriverTests {
 
 
 			Application.Shutdown ();
 			Application.Shutdown ();
 		}
 		}
-
+		
 		[Fact, AutoInitShutdown]
 		[Fact, AutoInitShutdown]
 		public void AddRune_On_Clip_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space ()
 		public void AddRune_On_Clip_Left_Or_Right_Replace_Previous_Or_Next_Wide_Rune_With_Space ()
 		{
 		{
@@ -441,7 +441,7 @@ namespace Terminal.Gui.DriverTests {
 		}
 		}
 
 
 		private static object packetLock = new object ();
 		private static object packetLock = new object ();
-
+		
 		/// <summary>
 		/// <summary>
 		/// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'.
 		/// Sometimes when using remote tools EventKeyRecord sends 'virtual keystrokes'.
 		/// These are indicated with the wVirtualKeyCode of 231. When we see this code
 		/// These are indicated with the wVirtualKeyCode of 231. When we see this code
@@ -487,6 +487,7 @@ namespace Terminal.Gui.DriverTests {
 				if (iterations == 0) Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control);
 				if (iterations == 0) Application.Driver.SendKeys ((char)mappedConsoleKey, ConsoleKey.Packet, shift, alt, control);
 			};
 			};
 
 
+
 			lock (packetLock) {
 			lock (packetLock) {
 				Application.Run ();
 				Application.Run ();
 				Application.Shutdown ();
 				Application.Shutdown ();

+ 1 - 0
UnitTests/Drivers/KeyTests.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using Terminal.Gui;
 using Xunit;
 using Xunit;
 
 
 namespace Terminal.Gui.DriverTests {
 namespace Terminal.Gui.DriverTests {

+ 42 - 5
UnitTests/TopLevels/ToplevelTests.cs

@@ -696,7 +696,7 @@ namespace Terminal.Gui.TopLevelTests {
 					((FakeDriver)Application.Driver).SetBufferSize (40, 15);
 					((FakeDriver)Application.Driver).SetBufferSize (40, 15);
 					MessageBox.Query ("About", "Hello Word", "Ok");
 					MessageBox.Query ("About", "Hello Word", "Ok");
 
 
-				} else if (iterations == 1) 					TestHelpers.AssertDriverContentsWithFrameAre (@"
+				} else if (iterations == 1) TestHelpers.AssertDriverContentsWithFrameAre (@"
  File                                   
  File                                   
 ┌ Window ──────────────────────────────┐
 ┌ Window ──────────────────────────────┐
 │                                      │
 │                                      │
@@ -712,7 +712,7 @@ namespace Terminal.Gui.TopLevelTests {
 │                                      │
 │                                      │
 └──────────────────────────────────────┘
 └──────────────────────────────────────┘
  CTRL-N New                             ", output);
  CTRL-N New                             ", output);
-else if (iterations == 2) {
+				else if (iterations == 2) {
 					Assert.Null (Application.MouseGrabView);
 					Assert.Null (Application.MouseGrabView);
 					// Grab the mouse
 					// Grab the mouse
 					ReflectionTools.InvokePrivate (
 					ReflectionTools.InvokePrivate (
@@ -815,8 +815,8 @@ else if (iterations == 2) {
 
 
 					Assert.Null (Application.MouseGrabView);
 					Assert.Null (Application.MouseGrabView);
 
 
-				} else if (iterations == 8) 					Application.RequestStop ();
-else if (iterations == 9) 					Application.RequestStop ();
+				} else if (iterations == 8) Application.RequestStop ();
+				else if (iterations == 9) Application.RequestStop ();
 			};
 			};
 
 
 			Application.Run ();
 			Application.Run ();
@@ -956,7 +956,7 @@ else if (iterations == 9) 					Application.RequestStop ();
 
 
 					Assert.Null (Application.MouseGrabView);
 					Assert.Null (Application.MouseGrabView);
 
 
-				} else if (iterations == 8) 					Application.RequestStop ();
+				} else if (iterations == 8) Application.RequestStop ();
 			};
 			};
 
 
 			Application.Run ();
 			Application.Run ();
@@ -974,5 +974,42 @@ else if (iterations == 9) 					Application.RequestStop ();
 			exception = Record.Exception (() => ((FakeDriver)Application.Driver).SetBufferSize (10, 0));
 			exception = Record.Exception (() => ((FakeDriver)Application.Driver).SetBufferSize (10, 0));
 			Assert.Null (exception);
 			Assert.Null (exception);
 		}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void OnEnter_OnLeave_Triggered_On_Application_Begin_End ()
+		{
+			var isEnter = false;
+			var isLeave = false;
+			var v = new View ();
+			v.Enter += (_) => isEnter = true;
+			v.Leave += (_) => isLeave = true;
+			var top = Application.Top;
+			top.Add (v);
+
+			Assert.False (v.CanFocus);
+			var exception = Record.Exception (() => top.OnEnter (top));
+			Assert.Null (exception);
+			exception = Record.Exception (() => top.OnLeave (top));
+			Assert.Null (exception);
+
+			v.CanFocus = true;
+			Application.Begin (top);
+
+			Assert.True (isEnter);
+			Assert.False (isLeave);
+
+			isEnter = false;
+			var d = new Dialog ();
+			var rs = Application.Begin (d);
+
+			Assert.False (isEnter);
+			Assert.True (isLeave);
+
+			isLeave = false;
+			Application.End (rs);
+
+			Assert.True (isEnter);
+			Assert.False (isLeave);
+		}
 	}
 	}
 }
 }

+ 5 - 5
UnitTests/UnitTests.csproj

@@ -7,12 +7,12 @@
     <IsPackable>false</IsPackable>
     <IsPackable>false</IsPackable>
     <UseDataCollector />
     <UseDataCollector />
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
-    <!-- In the source tree the version will always be 1.0 for all projects. -->
+    <!-- In the source tree the version will always be 2.0 for all projects. -->
     <!-- Do not modify these. -->
     <!-- Do not modify these. -->
-    <AssemblyVersion>1.0</AssemblyVersion>
-    <FileVersion>1.0</FileVersion>
-    <Version>1.0</Version>
-    <InformationalVersion>1.0</InformationalVersion>
+    <AssemblyVersion>2.0</AssemblyVersion>
+    <FileVersion>2.0</FileVersion>
+    <Version>2.0</Version>
+    <InformationalVersion>2.0</InformationalVersion>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
     <DefineConstants>TRACE</DefineConstants>
     <DefineConstants>TRACE</DefineConstants>

+ 86 - 0
UnitTests/Views/AutocompleteTests.cs

@@ -6,9 +6,16 @@ using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Terminal.Gui;
 using Terminal.Gui;
 using Xunit;
 using Xunit;
+using Xunit.Abstractions;
 
 
 namespace Terminal.Gui.ViewTests {
 namespace Terminal.Gui.ViewTests {
 	public class AutocompleteTests {
 	public class AutocompleteTests {
+		readonly ITestOutputHelper output;
+
+		public AutocompleteTests (ITestOutputHelper output)
+		{
+			this.output = output;
+		}
 
 
 		[Fact]
 		[Fact]
 		public void Test_GenerateSuggestions_Simple ()
 		public void Test_GenerateSuggestions_Simple ()
@@ -151,5 +158,84 @@ namespace Terminal.Gui.ViewTests {
 			Assert.Empty (tv.Autocomplete.Suggestions);
 			Assert.Empty (tv.Autocomplete.Suggestions);
 			Assert.Equal (3, tv.Autocomplete.AllSuggestions.Count);
 			Assert.Equal (3, tv.Autocomplete.AllSuggestions.Count);
 		}
 		}
+
+		[Fact, AutoInitShutdown]
+		public void CursorLeft_CursorRight_Mouse_Button_Pressed_Does_Not_Show_Popup ()
+		{
+			var tv = new TextView () {
+				Width = 50,
+				Height = 5,
+				Text = "This a long line and against TextView."
+			};
+			tv.Autocomplete.AllSuggestions = Regex.Matches (tv.Text.ToString (), "\\w+")
+					.Select (s => s.Value)
+					.Distinct ().ToList ();
+			var top = Application.Top;
+			top.Add (tv);
+			Application.Begin (top);
+
+
+			for (int i = 0; i < 7; i++) {
+				Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
+				Application.Refresh ();
+				TestHelpers.AssertDriverContentsWithFrameAre (@"
+This a long line and against TextView.", output);
+			}
+
+			Assert.True (tv.MouseEvent (new MouseEvent () {
+				X = 6,
+				Y = 0,
+				Flags = MouseFlags.Button1Pressed
+			}));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This a long line and against TextView.", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.g, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This ag long line and against TextView.
+       against                         ", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This ag long line and against TextView.
+      against                          ", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This ag long line and against TextView.
+     against                           ", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorLeft, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This ag long line and against TextView.", output);
+
+			for (int i = 0; i < 3; i++) {
+				Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
+				Application.Refresh ();
+				TestHelpers.AssertDriverContentsWithFrameAre (@"
+This ag long line and against TextView.", output);
+			}
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This a long line and against TextView.", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.n, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This an long line and against TextView.
+       and                             ", output);
+
+			Assert.True (tv.ProcessKey (new KeyEvent (Key.CursorRight, new KeyModifiers ())));
+			Application.Refresh ();
+			TestHelpers.AssertDriverContentsWithFrameAre (@"
+This an long line and against TextView.", output);
+		}
 	}
 	}
 }
 }

+ 2 - 2
UnitTests/Views/ViewTests.cs

@@ -1602,8 +1602,8 @@ Y
 					// Calling the Text constructor.
 					// Calling the Text constructor.
 					lbl = new Label (text);
 					lbl = new Label (text);
 				}
 				}
-				lbl.ColorScheme = new ColorScheme ();
-				lbl.Redraw (lbl.Bounds);
+				Application.Top.Add (lbl);
+				Application.Top.Redraw (Application.Top.Bounds);
 
 
 				// should have the initial text
 				// should have the initial text
 				Assert.Equal ('t', driver.Contents [0, 0, 0]);
 				Assert.Equal ('t', driver.Contents [0, 0, 0]);