Răsfoiți Sursa

merge fixes

Tig Kindel 2 ani în urmă
părinte
comite
2b26ec7bfb

+ 118 - 33
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -62,40 +62,61 @@ namespace Terminal.Gui {
 					Curses.move (crow, ccol);
 					needMove = false;
 				}
-				if (runeWidth < 2 && ccol > 0
-					&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
-
-					var curAtttib = CurrentAttribute;
-					Curses.attrset (contents [crow, ccol - 1, 1]);
-					Curses.mvaddch (crow, ccol - 1, (int)(uint)' ');
-					contents [crow, ccol - 1, 0] = (int)(uint)' ';
-					Curses.move (crow, ccol);
-					Curses.attrset (curAtttib);
-
-				} else if (runeWidth < 2 && ccol <= Clip.Right - 1
-					&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
-
-					var curAtttib = CurrentAttribute;
-					Curses.attrset (contents [crow, ccol + 1, 1]);
-					Curses.mvaddch (crow, ccol + 1, (int)(uint)' ');
-					contents [crow, ccol + 1, 0] = (int)(uint)' ';
-					Curses.move (crow, ccol);
-					Curses.attrset (curAtttib);
+				if (runeWidth == 0 && ccol > 0) {
+					var r = contents [crow, ccol - 1, 0];
+					var s = new string (new char [] { (char)r, (char)rune });
+					string sn;
+					if (!s.IsNormalized ()) {
+						sn = s.Normalize ();
+					} else {
+						sn = s;
+					}
+					var c = sn [0];
+					Curses.mvaddch (crow, ccol - 1, (int)(uint)c);
+					contents [crow, ccol - 1, 0] = c;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
+					contents [crow, ccol - 1, 2] = 1;
 
-				}
-				if (runeWidth > 1 && ccol == Clip.Right - 1) {
-					Curses.addch ((int)(uint)' ');
-					contents [crow, ccol, 0] = (int)(uint)' ';
 				} else {
-					Curses.addch ((int)(uint)rune);
-					contents [crow, ccol, 0] = (int)(uint)rune;
+					if (runeWidth < 2 && ccol > 0
+						&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
+
+						var curAtttib = CurrentAttribute;
+						Curses.attrset (contents [crow, ccol - 1, 1]);
+						Curses.mvaddch (crow, ccol - 1, (int)(uint)' ');
+						contents [crow, ccol - 1, 0] = (int)(uint)' ';
+						Curses.move (crow, ccol);
+						Curses.attrset (curAtttib);
+
+					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
+						&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
+
+						var curAtttib = CurrentAttribute;
+						Curses.attrset (contents [crow, ccol + 1, 1]);
+						Curses.mvaddch (crow, ccol + 1, (int)(uint)' ');
+						contents [crow, ccol + 1, 0] = (int)(uint)' ';
+						Curses.move (crow, ccol);
+						Curses.attrset (curAtttib);
+
+					}
+					if (runeWidth > 1 && ccol == Clip.Right - 1) {
+						Curses.addch ((int)(uint)' ');
+						contents [crow, ccol, 0] = (int)(uint)' ';
+					} else {
+						Curses.addch ((int)(uint)rune);
+						contents [crow, ccol, 0] = (int)(uint)rune;
+					}
+					contents [crow, ccol, 1] = CurrentAttribute;
+					contents [crow, ccol, 2] = 1;
 				}
-				contents [crow, ccol, 1] = CurrentAttribute;
-				contents [crow, ccol, 2] = 1;
-			} else
+			} else {
 				needMove = true;
+			}
 
-			ccol++;
+			if (runeWidth < 0 || runeWidth > 0) {
+				ccol++;
+			}
+			
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 					contents [crow, ccol, 1] = CurrentAttribute;
@@ -104,8 +125,9 @@ namespace Terminal.Gui {
 				ccol++;
 			}
 
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
+			}
 		}
 
 		public override void AddStr (ustring str)
@@ -143,6 +165,19 @@ namespace Terminal.Gui {
 			SetCursorVisibility (CursorVisibility.Default);
 
 			Curses.endwin ();
+
+			// I'm commenting this because was used in a trying to fix the Linux hanging and forgot to exclude it.
+			// Clear and reset entire screen.
+			//Console.Out.Write ("\x1b[2J");
+			//Console.Out.Flush ();
+
+			// Set top and bottom lines of a window.
+			//Console.Out.Write ("\x1b[1;25r");
+			//Console.Out.Flush ();
+
+			//Set cursor key to cursor.
+			//Console.Out.Write ("\x1b[?1l");
+			//Console.Out.Flush ();
 		}
 
 		public override void UpdateScreen () => window.redrawwin ();
@@ -155,6 +190,8 @@ namespace Terminal.Gui {
 
 		public Curses.Window window;
 
+		//static short last_color_pair = 16;
+
 		/// <summary>
 		/// Creates a curses color from the provided foreground and background colors
 		/// </summary>
@@ -180,6 +217,37 @@ namespace Terminal.Gui {
 			return MakeColor ((short)MapColor (fore), (short)MapColor (back));
 		}
 
+		int [,] colorPairs = new int [16, 16];
+
+		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
+		{
+			// BUGBUG: This code is never called ?? See Issue #2300
+			int f = (short)foreground;
+			int b = (short)background;
+			var v = colorPairs [f, b];
+			if ((v & 0x10000) == 0) {
+				b &= 0x7;
+				bool bold = (f & 0x8) != 0;
+				f &= 0x7;
+
+				v = MakeColor ((short)f, (short)b) | (bold ? Curses.A_BOLD : 0);
+				colorPairs [(int)foreground, (int)background] = v | 0x1000;
+			}
+			SetAttribute (v & 0xffff);
+		}
+
+		Dictionary<int, int> rawPairs = new Dictionary<int, int> ();
+		public override void SetColors (short foreColorId, short backgroundColorId)
+		{
+			// BUGBUG: This code is never called ?? See Issue #2300
+			int key = ((ushort)foreColorId << 16) | (ushort)backgroundColorId;
+			if (!rawPairs.TryGetValue (key, out var v)) {
+				v = MakeColor (foreColorId, backgroundColorId);
+				rawPairs [key] = v;
+			}
+			SetAttribute (v);
+		}
+
 		static Key MapCursesKey (int cursesKey)
 		{
 			switch (cursesKey) {
@@ -767,7 +835,7 @@ namespace Terminal.Gui {
 			};
 		}
 
-		Curses.Event reportableMouseEvents;
+		Curses.Event oldMouseEvents, reportableMouseEvents;
 		public override void Init (Action terminalResized)
 		{
 			if (window != null)
@@ -824,7 +892,7 @@ namespace Terminal.Gui {
 			Curses.noecho ();
 
 			Curses.Window.Standard.keypad (true);
-			reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out _);
+			reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out oldMouseEvents);
 			TerminalResized = terminalResized;
 			if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition))
 				StartReportingMouseMoves ();
@@ -946,7 +1014,7 @@ namespace Terminal.Gui {
 			case Color.White:
 				return Curses.COLOR_WHITE | Curses.A_BOLD | Curses.COLOR_GRAY;
 			case Color.Invalid:
-				return Curses.COLOR_BLACK;
+				return Curses.COLOR_BLACK; 
 			}
 			throw new ArgumentException ("Invalid color code");
 		}
@@ -1020,6 +1088,23 @@ namespace Terminal.Gui {
 			Console.Out.Flush ();
 		}
 
+		//int lastMouseInterval;
+		//bool mouseGrabbed;
+
+		public override void UncookMouse ()
+		{
+			//if (mouseGrabbed)
+			//	return;
+			//lastMouseInterval = Curses.mouseinterval (0);
+			//mouseGrabbed = true;
+		}
+
+		public override void CookMouse ()
+		{
+			//mouseGrabbed = false;
+			//Curses.mouseinterval (lastMouseInterval);
+		}
+
 		/// <inheritdoc/>
 		public override bool GetCursorVisibility (out CursorVisibility visibility)
 		{

+ 70 - 23
Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs

@@ -33,7 +33,7 @@ namespace Terminal.Gui {
 				UseFakeClipboard = useFakeClipboard;
 				FakeClipboardAlwaysThrowsNotSupportedException = fakeClipboardAlwaysThrowsNotSupportedException;
 				FakeClipboardIsSupportedAlwaysFalse = fakeClipboardIsSupportedAlwaysTrue;
-				
+
 				// double check usage is correct
 				Debug.Assert (useFakeClipboard == false && fakeClipboardAlwaysThrowsNotSupportedException == false);
 				Debug.Assert (useFakeClipboard == false && fakeClipboardIsSupportedAlwaysTrue == false);
@@ -131,31 +131,51 @@ namespace Terminal.Gui {
 					//MockConsole.CursorTop = crow;
 					needMove = false;
 				}
-				if (runeWidth < 2 && ccol > 0
+				if (runeWidth == 0 && ccol > 0) {
+					var r = contents [crow, ccol - 1, 0];
+					var s = new string (new char [] { (char)r, (char)rune });
+					string sn;
+					if (!s.IsNormalized ()) {
+						sn = s.Normalize ();
+					} else {
+						sn = s;
+					}
+					var c = sn [0];
+					contents [crow, ccol - 1, 0] = c;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
+					contents [crow, ccol - 1, 2] = 1;
+
+				} else {
+					if (runeWidth < 2 && ccol > 0
 					&& Rune.ColumnWidth ((Rune)contents [crow, ccol - 1, 0]) > 1) {
 
-					contents [crow, ccol - 1, 0] = (int)(uint)' ';
+						contents [crow, ccol - 1, 0] = (int)(uint)' ';
 
-				} else if (runeWidth < 2 && ccol <= Clip.Right - 1
-					&& Rune.ColumnWidth ((Rune)contents [crow, ccol, 0]) > 1) {
+					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
+						&& Rune.ColumnWidth ((Rune)contents [crow, ccol, 0]) > 1) {
 
-					contents [crow, ccol + 1, 0] = (int)(uint)' ';
-					contents [crow, ccol + 1, 2] = 1;
+						contents [crow, ccol + 1, 0] = (int)(uint)' ';
+						contents [crow, ccol + 1, 2] = 1;
 
-				}
-				if (runeWidth > 1 && ccol == Clip.Right - 1) {
-					contents [crow, ccol, 0] = (int)(uint)' ';
-				} else {
-					contents [crow, ccol, 0] = (int)(uint)rune;
-				}
-				contents [crow, ccol, 1] = CurrentAttribute;
-				contents [crow, ccol, 2] = 1;
+					}
+					if (runeWidth > 1 && ccol == Clip.Right - 1) {
+						contents [crow, ccol, 0] = (int)(uint)' ';
+					} else {
+						contents [crow, ccol, 0] = (int)(uint)rune;
+					}
+					contents [crow, ccol, 1] = CurrentAttribute;
+					contents [crow, ccol, 2] = 1;
 
-				dirtyLine [crow] = true;
-			} else
+					dirtyLine [crow] = true;
+				}
+			} else {
 				needMove = true;
+			}
+
+			if (runeWidth < 0 || runeWidth > 0) {
+				ccol++;
+			}
 
-			ccol++;
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 					contents [crow, ccol, 1] = CurrentAttribute;
@@ -169,8 +189,9 @@ namespace Terminal.Gui {
 			//	if (crow + 1 < Rows)
 			//		crow++;
 			//}
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
+			}
 		}
 
 		public override void AddStr (ustring str)
@@ -621,6 +642,7 @@ namespace Terminal.Gui {
 			return hasColor;
 		}
 
+		#region Unused
 		public override void UpdateCursor ()
 		{
 			if (!EnsureCursorVisibility ())
@@ -636,10 +658,35 @@ namespace Terminal.Gui {
 			}
 		}
 
-		#region Unused
-		public override void StartReportingMouseMoves () {}
-		public override void StopReportingMouseMoves () {}
-		public override void Suspend () {}
+		public override void StartReportingMouseMoves ()
+		{
+		}
+
+		public override void StopReportingMouseMoves ()
+		{
+		}
+
+		public override void Suspend ()
+		{
+		}
+
+		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
+		{
+		}
+
+		public override void SetColors (short foregroundColorId, short backgroundColorId)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void CookMouse ()
+		{
+		}
+
+		public override void UncookMouse ()
+		{
+		}
+
 		#endregion
 
 		public class FakeClipboard : ClipboardBase {

+ 54 - 17
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -1241,30 +1241,49 @@ namespace Terminal.Gui {
 			var validClip = IsValidContent (ccol, crow, Clip);
 
 			if (validClip) {
-				if (runeWidth < 2 && ccol > 0
-					&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
+				if (runeWidth == 0 && ccol > 0) {
+					var r = contents [crow, ccol - 1, 0];
+					var s = new string (new char [] { (char)r, (char)rune });
+					string sn;
+					if (!s.IsNormalized ()) {
+						sn = s.Normalize ();
+					} else {
+						sn = s;
+					}
+					var c = sn [0];
+					contents [crow, ccol - 1, 0] = c;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
+					contents [crow, ccol - 1, 2] = 1;
 
-					contents [crow, ccol - 1, 0] = (int)(uint)' ';
+				} else {
+					if (runeWidth < 2 && ccol > 0
+						&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
 
-				} else if (runeWidth < 2 && ccol <= Clip.Right - 1
-					&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
+						contents [crow, ccol - 1, 0] = (int)(uint)' ';
 
-					contents [crow, ccol + 1, 0] = (int)(uint)' ';
-					contents [crow, ccol + 1, 2] = 1;
+					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
+						&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
 
-				}
-				if (runeWidth > 1 && ccol == Clip.Right - 1) {
-					contents [crow, ccol, 0] = (int)(uint)' ';
-				} else {
-					contents [crow, ccol, 0] = (int)(uint)rune;
-				}
-				contents [crow, ccol, 1] = CurrentAttribute;
-				contents [crow, ccol, 2] = 1;
+						contents [crow, ccol + 1, 0] = (int)(uint)' ';
+						contents [crow, ccol + 1, 2] = 1;
 
+					}
+					if (runeWidth > 1 && ccol == Clip.Right - 1) {
+						contents [crow, ccol, 0] = (int)(uint)' ';
+					} else {
+						contents [crow, ccol, 0] = (int)(uint)rune;
+					}
+					contents [crow, ccol, 1] = CurrentAttribute;
+					contents [crow, ccol, 2] = 1;
+
+				}
 				dirtyLine [crow] = true;
 			}
 
-			ccol++;
+			if (runeWidth < 0 || runeWidth > 0) {
+				ccol++;
+			}
+			
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 					contents [crow, ccol, 1] = CurrentAttribute;
@@ -1487,7 +1506,7 @@ namespace Terminal.Gui {
 						outputWidth++;
 						var rune = contents [row, col, 0];
 						char [] spair;
-						if (Rune.DecodeSurrogatePair((uint) rune, out spair)) {
+						if (Rune.DecodeSurrogatePair ((uint)rune, out spair)) {
 							output.Append (spair);
 						} else {
 							output.Append ((char)rune);
@@ -1995,6 +2014,24 @@ namespace Terminal.Gui {
 			return hasColor;
 		}
 
+		#region Unused
+		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
+		{
+		}
+
+		public override void SetColors (short foregroundColorId, short backgroundColorId)
+		{
+		}
+
+		public override void CookMouse ()
+		{
+		}
+
+		public override void UncookMouse ()
+		{
+		}
+		#endregion
+
 		//
 		// These are for the .NET driver, but running natively on Windows, wont run
 		// on the Mono emulation

+ 73 - 26
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1517,35 +1517,57 @@ namespace Terminal.Gui {
 			var validClip = IsValidContent (ccol, crow, Clip);
 
 			if (validClip) {
-				if (runeWidth < 2 && ccol > 0
-					&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
-
+				if (runeWidth == 0 && ccol > 0) {
+					var r = contents [crow, ccol - 1, 0];
+					var s = new string (new char [] { (char)r, (char)rune });
+					string sn;
+					if (!s.IsNormalized ()) {
+						sn = s.Normalize ();
+					} else {
+						sn = s;
+					}
+					var c = sn [0];
 					var prevPosition = crow * Cols + (ccol - 1);
-					OutputBuffer [prevPosition].Char.UnicodeChar = ' ';
-					contents [crow, ccol - 1, 0] = (int)(uint)' ';
+					OutputBuffer [prevPosition].Char.UnicodeChar = c;
+					contents [crow, ccol - 1, 0] = c;
+					OutputBuffer [prevPosition].Attributes = (ushort)CurrentAttribute;
+					contents [crow, ccol - 1, 1] = CurrentAttribute;
+					contents [crow, ccol - 1, 2] = 1;
+					WindowsConsole.SmallRect.Update (ref damageRegion, (short)(ccol - 1), (short)crow);
+				} else {
+					if (runeWidth < 2 && ccol > 0
+						&& Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) {
 
-				} else if (runeWidth < 2 && ccol <= Clip.Right - 1
-					&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
+						var prevPosition = crow * Cols + (ccol - 1);
+						OutputBuffer [prevPosition].Char.UnicodeChar = ' ';
+						contents [crow, ccol - 1, 0] = (int)(uint)' ';
 
-					var prevPosition = GetOutputBufferPosition () + 1;
-					OutputBuffer [prevPosition].Char.UnicodeChar = (char)' ';
-					contents [crow, ccol + 1, 0] = (int)(uint)' ';
+					} else if (runeWidth < 2 && ccol <= Clip.Right - 1
+						&& Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) {
 
+						var prevPosition = GetOutputBufferPosition () + 1;
+						OutputBuffer [prevPosition].Char.UnicodeChar = (char)' ';
+						contents [crow, ccol + 1, 0] = (int)(uint)' ';
+
+					}
+					if (runeWidth > 1 && ccol == Clip.Right - 1) {
+						OutputBuffer [position].Char.UnicodeChar = (char)' ';
+						contents [crow, ccol, 0] = (int)(uint)' ';
+					} else {
+						OutputBuffer [position].Char.UnicodeChar = (char)rune;
+						contents [crow, ccol, 0] = (int)(uint)rune;
+					}
+					OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
+					contents [crow, ccol, 1] = CurrentAttribute;
+					contents [crow, ccol, 2] = 1;
+					WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow);
 				}
-				if (runeWidth > 1 && ccol == Clip.Right - 1) {
-					OutputBuffer [position].Char.UnicodeChar = (char)' ';
-					contents [crow, ccol, 0] = (int)(uint)' ';
-				} else {
-					OutputBuffer [position].Char.UnicodeChar = (char)rune;
-					contents [crow, ccol, 0] = (int)(uint)rune;
-				}
-				OutputBuffer [position].Attributes = (ushort)CurrentAttribute;
-				contents [crow, ccol, 1] = CurrentAttribute;
-				contents [crow, ccol, 2] = 1;
-				WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow);
 			}
 
-			ccol++;
+			if (runeWidth < 0 || runeWidth > 0) {
+				ccol++;
+			}
+			
 			if (runeWidth > 1) {
 				if (validClip && ccol < Clip.Right) {
 					position = GetOutputBufferPosition ();
@@ -1558,8 +1580,9 @@ namespace Terminal.Gui {
 				ccol++;
 			}
 
-			if (sync)
+			if (sync) {
 				UpdateScreen ();
+			}
 		}
 
 		public override void AddStr (ustring str)
@@ -1764,9 +1787,33 @@ namespace Terminal.Gui {
 		}
 
 		#region Unused
-		public override void StartReportingMouseMoves () { }
-		public override void StopReportingMouseMoves () { }
-		public override void Suspend () { }
+		public override void SetColors (ConsoleColor foreground, ConsoleColor background)
+		{
+		}
+
+		public override void SetColors (short foregroundColorId, short backgroundColorId)
+		{
+		}
+
+		public override void Suspend ()
+		{
+		}
+
+		public override void StartReportingMouseMoves ()
+		{
+		}
+
+		public override void StopReportingMouseMoves ()
+		{
+		}
+
+		public override void UncookMouse ()
+		{
+		}
+
+		public override void CookMouse ()
+		{
+		}
 		#endregion
 	}
 

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

@@ -57,7 +57,7 @@ namespace Terminal.Gui {
 	///   </para>
 	/// </remarks>
 	public static class Application {
-		static Stack<Toplevel> toplevels = new Stack<Toplevel> ();
+		static readonly Stack<Toplevel> toplevels = new Stack<Toplevel> ();
 
 		/// <summary>
 		/// The current <see cref="ConsoleDriver"/> in use.
@@ -111,28 +111,33 @@ namespace Terminal.Gui {
 		/// </summary>
 		public static View WantContinuousButtonPressedView { get; private set; }
 
+		private static bool? _heightAsBuffer;
+
 		/// <summary>
 		/// The current <see cref="ConsoleDriver.HeightAsBuffer"/> used in the terminal.
 		/// </summary>
+		/// 
 		public static bool HeightAsBuffer {
 			get {
 				if (Driver == null) {
-					throw new ArgumentNullException ("The driver must be initialized first.");
+					return _heightAsBuffer.HasValue && _heightAsBuffer.Value;
 				}
 				return Driver.HeightAsBuffer;
 			}
 			set {
+				_heightAsBuffer = value;
 				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;
 
 		/// <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>
 		public static Key AlternateForwardKey {
 			get => alternateForwardKey;
@@ -147,7 +152,7 @@ namespace Terminal.Gui {
 
 		static void OnAlternateForwardKeyChanged (Key oldKey)
 		{
-			foreach (var top in toplevels) {
+			foreach (var top in toplevels.ToArray()) {
 				top.OnAlternateForwardKeyChanged (oldKey);
 			}
 		}
@@ -155,7 +160,7 @@ namespace Terminal.Gui {
 		static Key alternateBackwardKey = Key.PageUp | Key.CtrlMask;
 
 		/// <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>
 		public static Key AlternateBackwardKey {
 			get => alternateBackwardKey;
@@ -170,7 +175,7 @@ namespace Terminal.Gui {
 
 		static void OnAlternateBackwardKeyChanged (Key oldKey)
 		{
-			foreach (var top in toplevels) {
+			foreach (var top in toplevels.ToArray()) {
 				top.OnAlternateBackwardKeyChanged (oldKey);
 			}
 		}
@@ -200,7 +205,8 @@ namespace Terminal.Gui {
 
 		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);
 			}
 		}
@@ -212,7 +218,7 @@ namespace Terminal.Gui {
 		public static MainLoop MainLoop { get; private set; }
 
 		/// <summary>
-		/// Disable or enable the mouse in this <see cref="Application"/>
+		/// Disable or enable the mouse. The mouse is enabled by default.
 		/// </summary>
 		public static bool IsMouseDisabled { get; set; }
 
@@ -266,7 +272,7 @@ namespace Terminal.Gui {
 		// users use async/await on their code
 		//
 		class MainLoopSyncContext : SynchronizationContext {
-			MainLoop mainLoop;
+			readonly MainLoop mainLoop;
 
 			public MainLoopSyncContext (MainLoop mainLoop)
 			{
@@ -305,9 +311,9 @@ namespace Terminal.Gui {
 		}
 
 		/// <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>
-		public static bool UseSystemConsole;
+		public static bool UseSystemConsole { get; set; } = false;
 
 		// For Unit testing - ignores UseSystemConsole
 		internal static bool ForceFakeConsole;
@@ -422,6 +428,7 @@ namespace Terminal.Gui {
 			MainLoop = new MainLoop (mainLoopDriver);
 
 			try {
+				Driver.HeightAsBuffer = HeightAsBuffer;
 				Driver.Init (TerminalResized);
 			} catch (InvalidOperationException ex) {
 				// This is a case where the driver is unable to initialize the console.
@@ -705,6 +712,7 @@ namespace Terminal.Gui {
 				return;
 			OnGrabbedMouse (view);
 			mouseGrabView = view;
+			Driver.UncookMouse ();
 		}
 
 		/// <summary>
@@ -716,6 +724,7 @@ namespace Terminal.Gui {
 				return;
 			OnUnGrabbedMouse (mouseGrabView);
 			mouseGrabView = null;
+			Driver.CookMouse ();
 		}
 
 		static void OnGrabbedMouse (View view)
@@ -984,9 +993,7 @@ namespace Terminal.Gui {
 			toplevel.PositionToplevels ();
 			toplevel.WillPresent ();
 			if (refreshDriver) {
-				if (MdiTop != null) {
-					MdiTop.OnChildLoaded (toplevel);
-				}
+				MdiTop?.OnChildLoaded (toplevel);
 				toplevel.OnLoaded ();
 				Redraw (toplevel);
 				toplevel.PositionCursor ();
@@ -1109,12 +1116,6 @@ namespace Terminal.Gui {
 			Driver.Refresh ();
 		}
 
-		static void Refresh (View view)
-		{
-			view.Redraw (view.Bounds);
-			Driver.Refresh ();
-		}
-
 		/// <summary>
 		/// Triggers a refresh of the entire display.
 		/// </summary>

+ 131 - 21
Terminal.Gui/Core/ConsoleDriver.cs

@@ -170,18 +170,9 @@ namespace Terminal.Gui {
 	/// Attributes are used as elements that contain both a foreground and a background or platform specific features
 	/// </summary>
 	/// <remarks>
-	/// <para>
 	///   <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.
-	/// </para>
-	/// <para>
-	///   <see cref="Attribute"/>s are driver-specific and, as a result, are only valid if initialized by a <see cref="ConsoleDriver"/>.
-	///   If an <see cref="Attribute"/> is created before a driver is initialized <see cref="Initialized"/> will be <see langword="false"/>
-	///   and attempts to use the <see cref="Attribute"/> will result in an exception. To use an <see cref="Attribute"/> that is not
-	///   initilzied, after a driver is initialized, recreate the <see cref="Attribute"/> by calling the <see cref="Attribute"/> constructor
-	///   or <see cref="Make(Color, Color)"/>.
-	///   </para>
 	/// </remarks>
 	public struct Attribute {
 		/// <summary>
@@ -433,11 +424,11 @@ namespace Terminal.Gui {
 		public bool Equals (ColorScheme other)
 		{
 			return other != null &&
-				EqualityComparer<Attribute>.Default.Equals (_normal, other._normal) &&
-				EqualityComparer<Attribute>.Default.Equals (_focus, other._focus) &&
-				EqualityComparer<Attribute>.Default.Equals (_hotNormal, other._hotNormal) &&
-				EqualityComparer<Attribute>.Default.Equals (_hotFocus, other._hotFocus) &&
-				EqualityComparer<Attribute>.Default.Equals (_disabled, other._disabled);
+			       EqualityComparer<Attribute>.Default.Equals (_normal, other._normal) &&
+			       EqualityComparer<Attribute>.Default.Equals (_focus, other._focus) &&
+			       EqualityComparer<Attribute>.Default.Equals (_hotNormal, other._hotNormal) &&
+			       EqualityComparer<Attribute>.Default.Equals (_hotFocus, other._hotFocus) &&
+			       EqualityComparer<Attribute>.Default.Equals (_disabled, other._disabled);
 		}
 
 		/// <summary>
@@ -664,6 +655,71 @@ namespace Terminal.Gui {
 		BoxFix = 0x02020164,
 	}
 
+	///// <summary>
+	///// Special characters that can be drawn with 
+	///// </summary>
+	//public enum SpecialChar {
+	//	/// <summary>
+	//	/// Horizontal line character.
+	//	/// </summary>
+	//	HLine,
+
+	//	/// <summary>
+	//	/// Vertical line character.
+	//	/// </summary>
+	//	VLine,
+
+	//	/// <summary>
+	//	/// Stipple pattern
+	//	/// </summary>
+	//	Stipple,
+
+	//	/// <summary>
+	//	/// Diamond character
+	//	/// </summary>
+	//	Diamond,
+
+	//	/// <summary>
+	//	/// Upper left corner
+	//	/// </summary>
+	//	ULCorner,
+
+	//	/// <summary>
+	//	/// Lower left corner
+	//	/// </summary>
+	//	LLCorner,
+
+	//	/// <summary>
+	//	/// Upper right corner
+	//	/// </summary>
+	//	URCorner,
+
+	//	/// <summary>
+	//	/// Lower right corner
+	//	/// </summary>
+	//	LRCorner,
+
+	//	/// <summary>
+	//	/// Left tee
+	//	/// </summary>
+	//	LeftTee,
+
+	//	/// <summary>
+	//	/// Right tee
+	//	/// </summary>
+	//	RightTee,
+
+	//	/// <summary>
+	//	/// Top tee
+	//	/// </summary>
+	//	TopTee,
+
+	//	/// <summary>
+	//	/// The bottom tee.
+	//	/// </summary>
+	//	BottomTee,
+	//}
+
 	/// <summary>
 	/// ConsoleDriver is an abstract class that defines the requirements for a console driver.  
 	/// There are currently three implementations: <see cref="CursesDriver"/> (for Unix and Mac), <see cref="WindowsDriver"/>, and <see cref="NetDriver"/> that uses the .NET Console API.
@@ -824,8 +880,8 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// The current attribute the driver is using. 
 		/// </summary>
-		internal virtual Attribute CurrentAttribute {
-			get => _currentAttribute; 
+		public virtual Attribute CurrentAttribute {
+			get => currentAttribute; 
 			set {
 				if (!value.Initialized && value.HasValidColors && Application.Driver != null) {
 					CurrentAttribute = Application.Driver.MakeAttribute (value.Foreground, value.Background);
@@ -833,7 +889,7 @@ namespace Terminal.Gui {
 				}
 				if (!value.Initialized) Debug.WriteLine ("ConsoleDriver.CurrentAttribute: Attributes must be initialized before use.");
 
-				_currentAttribute = value;
+				currentAttribute = value;
 			}
 		}
 
@@ -849,6 +905,23 @@ namespace Terminal.Gui {
 			CurrentAttribute = c;
 		}
 
+		/// <summary>
+		/// Set Colors from limit sets of colors. Not implemented by any driver: See Issue #2300.
+		/// </summary>
+		/// <param name="foreground">Foreground.</param>
+		/// <param name="background">Background.</param>
+		public abstract void SetColors (ConsoleColor foreground, ConsoleColor background);
+
+		// Advanced uses - set colors to any pre-set pairs, you would need to init_color
+		// that independently with the R, G, B values.
+		/// <summary>
+		/// Advanced uses - set colors to any pre-set pairs, you would need to init_color
+		/// that independently with the R, G, B values. Not implemented by any driver: See Issue #2300.
+		/// </summary>
+		/// <param name="foregroundColorId">Foreground color identifier.</param>
+		/// <param name="backgroundColorId">Background color identifier.</param>
+		public abstract void SetColors (short foregroundColorId, short backgroundColorId);
+
 		/// <summary>
 		/// Gets the foreground and background colors based on the value.
 		/// </summary>
@@ -1165,6 +1238,17 @@ namespace Terminal.Gui {
 		/// </summary>
 		public abstract void StopReportingMouseMoves ();
 
+		/// <summary>
+		/// 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>
+		public abstract void UncookMouse ();
+
+		/// <summary>
+		/// Enables the cooked event processing from the mouse driver. Not implemented by any driver: See Issue #2300.
+		/// </summary>
+		public abstract void CookMouse ();
+
 		/// <summary>
 		/// Horizontal line character.
 		/// </summary>
@@ -1354,8 +1438,7 @@ namespace Terminal.Gui {
 		/// Lower right rounded corner
 		/// </summary>
 		public Rune LRRCorner = '\u256f';
-		
-		private Attribute _currentAttribute;
+		private Attribute currentAttribute;
 
 		/// <summary>
 		/// Make the attribute for the foreground and background colors.
@@ -1383,8 +1466,6 @@ namespace Terminal.Gui {
 		/// Ensures all <see cref="Attribute"/>s in <see cref="Colors.ColorSchemes"/> are correclty 
 		/// initalized by the driver.
 		/// </summary>
-		/// <remarks>
-		/// </remarks>
 		/// <param name="supportsColors">Flag indicating if colors are supported (not used).</param>
 		public void InitalizeColorSchemes (bool supportsColors = true)
 		{
@@ -1397,6 +1478,35 @@ namespace Terminal.Gui {
 				return;
 			}
 
+			Colors.TopLevel.Normal = MakeColor (Color.BrightGreen, Color.Black);
+			Colors.TopLevel.Focus = MakeColor (Color.White, Color.Cyan);
+			Colors.TopLevel.HotNormal = MakeColor (Color.Brown, Color.Black);
+			Colors.TopLevel.HotFocus = MakeColor (Color.Blue, Color.Cyan);
+			Colors.TopLevel.Disabled = MakeColor (Color.DarkGray, Color.Black);
+
+			Colors.Base.Normal = MakeColor (Color.White, Color.Blue);
+			Colors.Base.Focus = MakeColor (Color.Black, Color.Gray);
+			Colors.Base.HotNormal = MakeColor (Color.BrightCyan, Color.Blue);
+			Colors.Base.HotFocus = MakeColor (Color.BrightBlue, Color.Gray);
+			Colors.Base.Disabled = MakeColor (Color.DarkGray, Color.Blue);
+
+			Colors.Dialog.Normal = MakeColor (Color.Black, Color.Gray);
+			Colors.Dialog.Focus = MakeColor (Color.White, Color.DarkGray);
+			Colors.Dialog.HotNormal = MakeColor (Color.Blue, Color.Gray);
+			Colors.Dialog.HotFocus = MakeColor (Color.BrightYellow, Color.DarkGray);
+			Colors.Dialog.Disabled = MakeColor (Color.Gray, Color.DarkGray);
+
+			Colors.Menu.Normal = MakeColor (Color.White, Color.DarkGray);
+			Colors.Menu.Focus = MakeColor (Color.White, Color.Black);
+			Colors.Menu.HotNormal = MakeColor (Color.BrightYellow, Color.DarkGray);
+			Colors.Menu.HotFocus = MakeColor (Color.BrightYellow, Color.Black);
+			Colors.Menu.Disabled = MakeColor (Color.Gray, Color.DarkGray);
+
+			Colors.Error.Normal = MakeColor (Color.Red, Color.White);
+			Colors.Error.Focus = MakeColor (Color.Black, Color.BrightRed);
+			Colors.Error.HotNormal = MakeColor (Color.Black, Color.White);
+			Colors.Error.HotFocus = MakeColor (Color.White, Color.BrightRed);
+			Colors.Error.Disabled = MakeColor (Color.DarkGray, Color.White);
 		}
 	}
 

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

@@ -769,7 +769,7 @@ namespace Terminal.Gui {
 		void Initialize (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed,
 		    TextDirection direction = TextDirection.LeftRight_TopBottom, Border border = null)
 		{
-			TextFormatter = new TextFormatter ();
+						TextFormatter = new TextFormatter ();
 			TextFormatter.HotKeyChanged += TextFormatter_HotKeyChanged;
 			TextDirection = direction;
 			Border = border;
@@ -1447,8 +1447,9 @@ namespace Terminal.Gui {
 		/// </summary>
 		public virtual ColorScheme ColorScheme {
 			get {
-				if (colorScheme == null)
+				if (colorScheme == null) {
 					return SuperView?.ColorScheme;
+				}
 				return colorScheme;
 			}
 			set {

+ 1 - 1
UICatalog/UICatalog.cs

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

+ 0 - 1
UnitTests/Application/ApplicationTests.cs

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