diff --git a/Terminal.Gui/ConsoleDrivers/MockDriver/MockConsole.cs b/Terminal.Gui/ConsoleDrivers/MockDriver/MockConsole.cs
new file mode 100644
index 000000000..ffb3b0c32
--- /dev/null
+++ b/Terminal.Gui/ConsoleDrivers/MockDriver/MockConsole.cs
@@ -0,0 +1,1661 @@
+//
+// MockConsole.cs: A mock .NET Windows Console API implementaiton for unit tests.
+//
+// Authors:
+// Charlie Kindel (github.com/tig)
+//
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Terminal.Gui {
+ ///
+ ///
+ ///
+ public static class MockConsole {
+
+ //
+ // Summary:
+ // Gets or sets the width of the console window.
+ //
+ // Returns:
+ // The width of the console window measured in columns.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight
+ // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight
+ // property plus the value of the System.Console.WindowTop property is greater than
+ // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth
+ // property or the value of the System.Console.WindowHeight property is greater
+ // than the largest possible window width or height for the current screen resolution
+ // and console font.
+ //
+ // T:System.IO.IOException:
+ // Error reading or writing information.
+ public static int WindowWidth { get; set; } = 80;
+ //
+ // Summary:
+ // Gets a value that indicates whether output has been redirected from the standard
+ // output stream.
+ //
+ // Returns:
+ // true if output is redirected; otherwise, false.
+ public static bool IsOutputRedirected { get; }
+ //
+ // Summary:
+ // Gets a value that indicates whether the error output stream has been redirected
+ // from the standard error stream.
+ //
+ // Returns:
+ // true if error output is redirected; otherwise, false.
+ public static bool IsErrorRedirected { get; }
+ //
+ // Summary:
+ // Gets the standard input stream.
+ //
+ // Returns:
+ // A System.IO.TextReader that represents the standard input stream.
+ public static TextReader In { get; }
+ //
+ // Summary:
+ // Gets the standard output stream.
+ //
+ // Returns:
+ // A System.IO.TextWriter that represents the standard output stream.
+ public static TextWriter Out { get; }
+ //
+ // Summary:
+ // Gets the standard error output stream.
+ //
+ // Returns:
+ // A System.IO.TextWriter that represents the standard error output stream.
+ public static TextWriter Error { get; }
+ //
+ // Summary:
+ // Gets or sets the encoding the console uses to read input.
+ //
+ // Returns:
+ // The encoding used to read console input.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // The property value in a set operation is null.
+ //
+ // T:System.IO.IOException:
+ // An error occurred during the execution of this operation.
+ //
+ // T:System.Security.SecurityException:
+ // Your application does not have permission to perform this operation.
+ public static Encoding InputEncoding { get; set; }
+ //
+ // Summary:
+ // Gets or sets the encoding the console uses to write output.
+ //
+ // Returns:
+ // The encoding used to write console output.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // The property value in a set operation is null.
+ //
+ // T:System.IO.IOException:
+ // An error occurred during the execution of this operation.
+ //
+ // T:System.Security.SecurityException:
+ // Your application does not have permission to perform this operation.
+ public static Encoding OutputEncoding { get; set; }
+ //
+ // Summary:
+ // Gets or sets the background color of the console.
+ //
+ // Returns:
+ // A value that specifies the background color of the console; that is, the color
+ // that appears behind each character. The default is black.
+ //
+ // Exceptions:
+ // T:System.ArgumentException:
+ // The color specified in a set operation is not a valid member of System.ConsoleColor.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ ///
+ ///
+ ///
+ public static ConsoleColor BackgroundColor { get; set; } = _defaultBackgroundColor;
+ static ConsoleColor _defaultBackgroundColor = ConsoleColor.Black;
+
+ //
+ // Summary:
+ // Gets or sets the foreground color of the console.
+ //
+ // Returns:
+ // A System.ConsoleColor that specifies the foreground color of the console; that
+ // is, the color of each character that is displayed. The default is gray.
+ //
+ // Exceptions:
+ // T:System.ArgumentException:
+ // The color specified in a set operation is not a valid member of System.ConsoleColor.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ ///
+ ///
+ ///
+ public static ConsoleColor ForegroundColor { get; set; } = _defaultForegroundColor;
+ static ConsoleColor _defaultForegroundColor = ConsoleColor.Gray;
+ //
+ // Summary:
+ // Gets or sets the height of the buffer area.
+ //
+ // Returns:
+ // The current height, in rows, of the buffer area.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value in a set operation is less than or equal to zero.-or- The value in
+ // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value
+ // in a set operation is less than System.Console.WindowTop + System.Console.WindowHeight.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int BufferHeight { get; set; } = 25;
+ //
+ // Summary:
+ // Gets or sets the width of the buffer area.
+ //
+ // Returns:
+ // The current width, in columns, of the buffer area.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value in a set operation is less than or equal to zero.-or- The value in
+ // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value
+ // in a set operation is less than System.Console.WindowLeft + System.Console.WindowWidth.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int BufferWidth { get; set; } = 80;
+ //
+ // Summary:
+ // Gets or sets the height of the console window area.
+ //
+ // Returns:
+ // The height of the console window measured in rows.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight
+ // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight
+ // property plus the value of the System.Console.WindowTop property is greater than
+ // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth
+ // property or the value of the System.Console.WindowHeight property is greater
+ // than the largest possible window width or height for the current screen resolution
+ // and console font.
+ //
+ // T:System.IO.IOException:
+ // Error reading or writing information.
+ public static int WindowHeight { get; set; } = 25;
+ //
+ // Summary:
+ // Gets or sets a value indicating whether the combination of the System.ConsoleModifiers.Control
+ // modifier key and System.ConsoleKey.C console key (Ctrl+C) is treated as ordinary
+ // input or as an interruption that is handled by the operating system.
+ //
+ // Returns:
+ // true if Ctrl+C is treated as ordinary input; otherwise, false.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // Unable to get or set the input mode of the console input buffer.
+ public static bool TreatControlCAsInput { get; set; }
+ //
+ // Summary:
+ // Gets the largest possible number of console window columns, based on the current
+ // font and screen resolution.
+ //
+ // Returns:
+ // The width of the largest possible console window measured in columns.
+ public static int LargestWindowWidth { get; }
+ //
+ // Summary:
+ // Gets the largest possible number of console window rows, based on the current
+ // font and screen resolution.
+ //
+ // Returns:
+ // The height of the largest possible console window measured in rows.
+ public static int LargestWindowHeight { get; }
+ //
+ // Summary:
+ // Gets or sets the leftmost position of the console window area relative to the
+ // screen buffer.
+ //
+ // Returns:
+ // The leftmost console window position measured in columns.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // In a set operation, the value to be assigned is less than zero.-or-As a result
+ // of the assignment, System.Console.WindowLeft plus System.Console.WindowWidth
+ // would exceed System.Console.BufferWidth.
+ //
+ // T:System.IO.IOException:
+ // Error reading or writing information.
+ public static int WindowLeft { get; set; }
+ //
+ // Summary:
+ // Gets or sets the top position of the console window area relative to the screen
+ // buffer.
+ //
+ // Returns:
+ // The uppermost console window position measured in rows.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // In a set operation, the value to be assigned is less than zero.-or-As a result
+ // of the assignment, System.Console.WindowTop plus System.Console.WindowHeight
+ // would exceed System.Console.BufferHeight.
+ //
+ // T:System.IO.IOException:
+ // Error reading or writing information.
+ public static int WindowTop { get; set; }
+ //
+ // Summary:
+ // Gets or sets the column position of the cursor within the buffer area.
+ //
+ // Returns:
+ // The current position, in columns, of the cursor.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value in a set operation is less than zero.-or- The value in a set operation
+ // is greater than or equal to System.Console.BufferWidth.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int CursorLeft { get; set; }
+ //
+ // Summary:
+ // Gets or sets the row position of the cursor within the buffer area.
+ //
+ // Returns:
+ // The current position, in rows, of the cursor.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value in a set operation is less than zero.-or- The value in a set operation
+ // is greater than or equal to System.Console.BufferHeight.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int CursorTop { get; set; }
+ //
+ // Summary:
+ // Gets or sets the height of the cursor within a character cell.
+ //
+ // Returns:
+ // The size of the cursor expressed as a percentage of the height of a character
+ // cell. The property value ranges from 1 to 100.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // The value specified in a set operation is less than 1 or greater than 100.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int CursorSize { get; set; }
+ //
+ // Summary:
+ // Gets or sets a value indicating whether the cursor is visible.
+ //
+ // Returns:
+ // true if the cursor is visible; otherwise, false.
+ //
+ // Exceptions:
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static bool CursorVisible { get; set; }
+ //
+ // Summary:
+ // Gets or sets the title to display in the console title bar.
+ //
+ // Returns:
+ // The string to be displayed in the title bar of the console. The maximum length
+ // of the title string is 24500 characters.
+ //
+ // Exceptions:
+ // T:System.InvalidOperationException:
+ // In a get operation, the retrieved title is longer than 24500 characters.
+ //
+ // T:System.ArgumentOutOfRangeException:
+ // In a set operation, the specified title is longer than 24500 characters.
+ //
+ // T:System.ArgumentNullException:
+ // In a set operation, the specified title is null.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static string Title { get; set; }
+ //
+ // Summary:
+ // Gets a value indicating whether a key press is available in the input stream.
+ //
+ // Returns:
+ // true if a key press is available; otherwise, false.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.InvalidOperationException:
+ // Standard input is redirected to a file instead of the keyboard.
+ public static bool KeyAvailable { get; }
+ //
+ // Summary:
+ // Gets a value indicating whether the NUM LOCK keyboard toggle is turned on or
+ // turned off.
+ //
+ // Returns:
+ // true if NUM LOCK is turned on; false if NUM LOCK is turned off.
+ public static bool NumberLock { get; }
+ //
+ // Summary:
+ // Gets a value indicating whether the CAPS LOCK keyboard toggle is turned on or
+ // turned off.
+ //
+ // Returns:
+ // true if CAPS LOCK is turned on; false if CAPS LOCK is turned off.
+ public static bool CapsLock { get; }
+ //
+ // Summary:
+ // Gets a value that indicates whether input has been redirected from the standard
+ // input stream.
+ //
+ // Returns:
+ // true if input is redirected; otherwise, false.
+ public static bool IsInputRedirected { get; }
+
+ //
+ // Summary:
+ // Occurs when the System.ConsoleModifiers.Control modifier key (Ctrl) and either
+ // the System.ConsoleKey.C console key (C) or the Break key are pressed simultaneously
+ // (Ctrl+C or Ctrl+Break).
+ //public static event ConsoleCancelEventHandler CancelKeyPress;
+
+ //
+ // Summary:
+ // Plays the sound of a beep through the console speaker.
+ //
+ // Exceptions:
+ // T:System.Security.HostProtectionException:
+ // This method was executed on a server, such as SQL Server, that does not permit
+ // access to a user interface.
+ public static void Beep ()
+ {
+ throw new NotImplementedException ();
+ }
+ //
+ // Summary:
+ // Plays the sound of a beep of a specified frequency and duration through the console
+ // speaker.
+ //
+ // Parameters:
+ // frequency:
+ // The frequency of the beep, ranging from 37 to 32767 hertz.
+ //
+ // duration:
+ // The duration of the beep measured in milliseconds.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // frequency is less than 37 or more than 32767 hertz.-or- duration is less than
+ // or equal to zero.
+ //
+ // T:System.Security.HostProtectionException:
+ // This method was executed on a server, such as SQL Server, that does not permit
+ // access to the console.
+ public static void Beep (int frequency, int duration)
+ {
+ throw new NotImplementedException ();
+ }
+ //
+ // Summary:
+ // Clears the console buffer and corresponding console window of display information.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Clear ()
+ {
+ _buffer = new char [WindowWidth, WindowHeight];
+ SetCursorPosition (0, 0);
+ }
+
+ static char [,] _buffer = new char [WindowWidth, WindowHeight];
+
+ //
+ // Summary:
+ // Copies a specified source area of the screen buffer to a specified destination
+ // area.
+ //
+ // Parameters:
+ // sourceLeft:
+ // The leftmost column of the source area.
+ //
+ // sourceTop:
+ // The topmost row of the source area.
+ //
+ // sourceWidth:
+ // The number of columns in the source area.
+ //
+ // sourceHeight:
+ // The number of rows in the source area.
+ //
+ // targetLeft:
+ // The leftmost column of the destination area.
+ //
+ // targetTop:
+ // The topmost row of the destination area.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft
+ // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop
+ // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight
+ // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth
+ // is greater than or equal to System.Console.BufferWidth.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Copies a specified source area of the screen buffer to a specified destination
+ // area.
+ //
+ // Parameters:
+ // sourceLeft:
+ // The leftmost column of the source area.
+ //
+ // sourceTop:
+ // The topmost row of the source area.
+ //
+ // sourceWidth:
+ // The number of columns in the source area.
+ //
+ // sourceHeight:
+ // The number of rows in the source area.
+ //
+ // targetLeft:
+ // The leftmost column of the destination area.
+ //
+ // targetTop:
+ // The topmost row of the destination area.
+ //
+ // sourceChar:
+ // The character used to fill the source area.
+ //
+ // sourceForeColor:
+ // The foreground color used to fill the source area.
+ //
+ // sourceBackColor:
+ // The background color used to fill the source area.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft
+ // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop
+ // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight
+ // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth
+ // is greater than or equal to System.Console.BufferWidth.
+ //
+ // T:System.ArgumentException:
+ // One or both of the color parameters is not a member of the System.ConsoleColor
+ // enumeration.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void MoveBufferArea (int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, int targetLeft, int targetTop, char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard error stream.
+ //
+ // Returns:
+ // The standard error stream.
+ public static Stream OpenStandardError ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard error stream, which is set to a specified buffer size.
+ //
+ // Parameters:
+ // bufferSize:
+ // The internal stream buffer size.
+ //
+ // Returns:
+ // The standard error stream.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // bufferSize is less than or equal to zero.
+ public static Stream OpenStandardError (int bufferSize)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard input stream, which is set to a specified buffer size.
+ //
+ // Parameters:
+ // bufferSize:
+ // The internal stream buffer size.
+ //
+ // Returns:
+ // The standard input stream.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // bufferSize is less than or equal to zero.
+ public static Stream OpenStandardInput (int bufferSize)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard input stream.
+ //
+ // Returns:
+ // The standard input stream.
+ public static Stream OpenStandardInput ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard output stream, which is set to a specified buffer size.
+ //
+ // Parameters:
+ // bufferSize:
+ // The internal stream buffer size.
+ //
+ // Returns:
+ // The standard output stream.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // bufferSize is less than or equal to zero.
+ public static Stream OpenStandardOutput (int bufferSize)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Acquires the standard output stream.
+ //
+ // Returns:
+ // The standard output stream.
+ public static Stream OpenStandardOutput ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Reads the next character from the standard input stream.
+ //
+ // Returns:
+ // The next character from the input stream, or negative one (-1) if there are currently
+ // no more characters to be read.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static int Read ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Obtains the next character or function key pressed by the user. The pressed key
+ // is optionally displayed in the console window.
+ //
+ // Parameters:
+ // intercept:
+ // Determines whether to display the pressed key in the console window. true to
+ // not display the pressed key; otherwise, false.
+ //
+ // Returns:
+ // An object that describes the System.ConsoleKey constant and Unicode character,
+ // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo
+ // object also describes, in a bitwise combination of System.ConsoleModifiers values,
+ // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously
+ // with the console key.
+ //
+ // Exceptions:
+ // T:System.InvalidOperationException:
+ // The System.Console.In property is redirected from some stream other than the
+ // console.
+ //[SecuritySafeCritical]
+ public static ConsoleKeyInfo ReadKey (bool intercept)
+ {
+ if (MockKeyPresses.Count > 0) {
+ return MockKeyPresses.Pop();
+ } else {
+ return new ConsoleKeyInfo ('~', ConsoleKey.Oem3, false,false,false);
+ }
+ }
+
+ public static Stack MockKeyPresses = new Stack ();
+
+ //
+ // Summary:
+ // Obtains the next character or function key pressed by the user. The pressed key
+ // is displayed in the console window.
+ //
+ // Returns:
+ // An object that describes the System.ConsoleKey constant and Unicode character,
+ // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo
+ // object also describes, in a bitwise combination of System.ConsoleModifiers values,
+ // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously
+ // with the console key.
+ //
+ // Exceptions:
+ // T:System.InvalidOperationException:
+ // The System.Console.In property is redirected from some stream other than the
+ // console.
+ public static ConsoleKeyInfo ReadKey ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Reads the next line of characters from the standard input stream.
+ //
+ // Returns:
+ // The next line of characters from the input stream, or null if no more lines are
+ // available.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.OutOfMemoryException:
+ // There is insufficient memory to allocate a buffer for the returned string.
+ //
+ // T:System.ArgumentOutOfRangeException:
+ // The number of characters in the next line of characters is greater than System.Int32.MaxValue.
+ public static string ReadLine ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the foreground and background console colors to their defaults.
+ //
+ // Exceptions:
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void ResetColor ()
+ {
+ BackgroundColor = _defaultBackgroundColor;
+ ForegroundColor = _defaultForegroundColor;
+ }
+
+ //
+ // Summary:
+ // Sets the height and width of the screen buffer area to the specified values.
+ //
+ // Parameters:
+ // width:
+ // The width of the buffer area measured in columns.
+ //
+ // height:
+ // The height of the buffer area measured in rows.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // height or width is less than or equal to zero.-or- height or width is greater
+ // than or equal to System.Int16.MaxValue.-or- width is less than System.Console.WindowLeft
+ // + System.Console.WindowWidth.-or- height is less than System.Console.WindowTop
+ // + System.Console.WindowHeight.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void SetBufferSize (int width, int height)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the position of the cursor.
+ //
+ // Parameters:
+ // left:
+ // The column position of the cursor. Columns are numbered from left to right starting
+ // at 0.
+ //
+ // top:
+ // The row position of the cursor. Rows are numbered from top to bottom starting
+ // at 0.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // left or top is less than zero.-or- left is greater than or equal to System.Console.BufferWidth.-or-
+ // top is greater than or equal to System.Console.BufferHeight.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void SetCursorPosition (int left, int top)
+ {
+ CursorLeft = left;
+ CursorTop = top;
+ }
+
+ //
+ // Summary:
+ // Sets the System.Console.Error property to the specified System.IO.TextWriter
+ // object.
+ //
+ // Parameters:
+ // newError:
+ // A stream that is the new standard error output.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // newError is null.
+ //
+ // T:System.Security.SecurityException:
+ // The caller does not have the required permission.
+ //[SecuritySafeCritical]
+ public static void SetError (TextWriter newError)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the System.Console.In property to the specified System.IO.TextReader object.
+ //
+ // Parameters:
+ // newIn:
+ // A stream that is the new standard input.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // newIn is null.
+ //
+ // T:System.Security.SecurityException:
+ // The caller does not have the required permission.
+ //[SecuritySafeCritical]
+ public static void SetIn (TextReader newIn)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the System.Console.Out property to the specified System.IO.TextWriter object.
+ //
+ // Parameters:
+ // newOut:
+ // A stream that is the new standard output.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // newOut is null.
+ //
+ // T:System.Security.SecurityException:
+ // The caller does not have the required permission.
+ //[SecuritySafeCritical]
+ public static void SetOut (TextWriter newOut)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the position of the console window relative to the screen buffer.
+ //
+ // Parameters:
+ // left:
+ // The column position of the upper left corner of the console window.
+ //
+ // top:
+ // The row position of the upper left corner of the console window.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // left or top is less than zero.-or- left + System.Console.WindowWidth is greater
+ // than System.Console.BufferWidth.-or- top + System.Console.WindowHeight is greater
+ // than System.Console.BufferHeight.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void SetWindowPosition (int left, int top)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Sets the height and width of the console window to the specified values.
+ //
+ // Parameters:
+ // width:
+ // The width of the console window measured in columns.
+ //
+ // height:
+ // The height of the console window measured in rows.
+ //
+ // Exceptions:
+ // T:System.ArgumentOutOfRangeException:
+ // width or height is less than or equal to zero.-or- width plus System.Console.WindowLeft
+ // or height plus System.Console.WindowTop is greater than or equal to System.Int16.MaxValue.
+ // -or- width or height is greater than the largest possible window width or height
+ // for the current screen resolution and console font.
+ //
+ // T:System.Security.SecurityException:
+ // The user does not have permission to perform this action.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[SecuritySafeCritical]
+ public static void SetWindowSize (int width, int height)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified string value to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (string value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified object to the standard output
+ // stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write, or null.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (object value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 64-bit unsigned integer value
+ // to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[CLSCompliant (false)]
+ public static void Write (ulong value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 64-bit signed integer value to
+ // the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (long value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified objects to the standard output
+ // stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // The first object to write using format.
+ //
+ // arg1:
+ // The second object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void Write (string format, object arg0, object arg1)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 32-bit signed integer value to
+ // the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (int value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified object to the standard output
+ // stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // An object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void Write (string format, object arg0)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 32-bit unsigned integer value
+ // to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[CLSCompliant (false)]
+ public static void Write (uint value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //[CLSCompliant (false)]
+ public static void Write (string format, object arg0, object arg1, object arg2, object arg3)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified array of objects to the standard
+ // output stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg:
+ // An array of objects to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format or arg is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void Write (string format, params object [] arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified Boolean value to the standard
+ // output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (bool value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified Unicode character value to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (char value)
+ {
+ _buffer [CursorLeft, CursorTop] = value;
+ }
+
+ //
+ // Summary:
+ // Writes the specified array of Unicode characters to the standard output stream.
+ //
+ // Parameters:
+ // buffer:
+ // A Unicode character array.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (char [] buffer)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified subarray of Unicode characters to the standard output stream.
+ //
+ // Parameters:
+ // buffer:
+ // An array of Unicode characters.
+ //
+ // index:
+ // The starting position in buffer.
+ //
+ // count:
+ // The number of characters to write.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // buffer is null.
+ //
+ // T:System.ArgumentOutOfRangeException:
+ // index or count is less than zero.
+ //
+ // T:System.ArgumentException:
+ // index plus count specify a position that is not within buffer.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (char [] buffer, int index, int count)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified objects to the standard output
+ // stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // The first object to write using format.
+ //
+ // arg1:
+ // The second object to write using format.
+ //
+ // arg2:
+ // The third object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void Write (string format, object arg0, object arg1, object arg2)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified System.Decimal value to the standard
+ // output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (decimal value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified single-precision floating-point
+ // value to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (float value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified double-precision floating-point
+ // value to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void Write (double value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the current line terminator to the standard output stream.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified single-precision floating-point
+ // value, followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (float value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 32-bit signed integer value,
+ // followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (int value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 32-bit unsigned integer value,
+ // followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[CLSCompliant (false)]
+ public static void WriteLine (uint value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 64-bit signed integer value,
+ // followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (long value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified 64-bit unsigned integer value,
+ // followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //[CLSCompliant (false)]
+ public static void WriteLine (ulong value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified object, followed by the current
+ // line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (object value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified string value, followed by the current line terminator, to
+ // the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (string value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified object, followed by the current
+ // line terminator, to the standard output stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // An object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void WriteLine (string format, object arg0)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified objects, followed by the current
+ // line terminator, to the standard output stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // The first object to write using format.
+ //
+ // arg1:
+ // The second object to write using format.
+ //
+ // arg2:
+ // The third object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void WriteLine (string format, object arg0, object arg1, object arg2)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //[CLSCompliant (false)]
+ public static void WriteLine (string format, object arg0, object arg1, object arg2, object arg3)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified array of objects, followed by
+ // the current line terminator, to the standard output stream using the specified
+ // format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg:
+ // An array of objects to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format or arg is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void WriteLine (string format, params object [] arg)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified subarray of Unicode characters, followed by the current
+ // line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // buffer:
+ // An array of Unicode characters.
+ //
+ // index:
+ // The starting position in buffer.
+ //
+ // count:
+ // The number of characters to write.
+ //
+ // Exceptions:
+ // T:System.ArgumentNullException:
+ // buffer is null.
+ //
+ // T:System.ArgumentOutOfRangeException:
+ // index or count is less than zero.
+ //
+ // T:System.ArgumentException:
+ // index plus count specify a position that is not within buffer.
+ //
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (char [] buffer, int index, int count)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified System.Decimal value, followed
+ // by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (decimal value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified array of Unicode characters, followed by the current line
+ // terminator, to the standard output stream.
+ //
+ // Parameters:
+ // buffer:
+ // A Unicode character array.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (char [] buffer)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the specified Unicode character, followed by the current line terminator,
+ // value to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (char value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified Boolean value, followed by the
+ // current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (bool value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified objects, followed by the current
+ // line terminator, to the standard output stream using the specified format information.
+ //
+ // Parameters:
+ // format:
+ // A composite format string (see Remarks).
+ //
+ // arg0:
+ // The first object to write using format.
+ //
+ // arg1:
+ // The second object to write using format.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ //
+ // T:System.ArgumentNullException:
+ // format is null.
+ //
+ // T:System.FormatException:
+ // The format specification in format is invalid.
+ public static void WriteLine (string format, object arg0, object arg1)
+ {
+ throw new NotImplementedException ();
+ }
+
+ //
+ // Summary:
+ // Writes the text representation of the specified double-precision floating-point
+ // value, followed by the current line terminator, to the standard output stream.
+ //
+ // Parameters:
+ // value:
+ // The value to write.
+ //
+ // Exceptions:
+ // T:System.IO.IOException:
+ // An I/O error occurred.
+ public static void WriteLine (double value)
+ {
+ throw new NotImplementedException ();
+ }
+
+ }
+}
diff --git a/Terminal.Gui/ConsoleDrivers/MockDriver/MockDriver.cs b/Terminal.Gui/ConsoleDrivers/MockDriver/MockDriver.cs
new file mode 100644
index 000000000..c236cd0b9
--- /dev/null
+++ b/Terminal.Gui/ConsoleDrivers/MockDriver/MockDriver.cs
@@ -0,0 +1,440 @@
+//
+// MockDriver.cs: A mock ConsoleDriver for unit tests.
+//
+// Authors:
+// Charlie Kindel (github.com/tig)
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using NStack;
+
+namespace Terminal.Gui {
+ public class MockDriver : ConsoleDriver, IMainLoopDriver {
+ int cols, rows;
+ public override int Cols => cols;
+ public override int Rows => rows;
+
+ // The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag
+ int [,,] contents;
+ bool [] dirtyLine;
+
+ void UpdateOffscreen ()
+ {
+ int cols = Cols;
+ int rows = Rows;
+
+ contents = new int [rows, cols, 3];
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < cols; c++) {
+ contents [r, c, 0] = ' ';
+ contents [r, c, 1] = MakeColor (ConsoleColor.Gray, ConsoleColor.Black);
+ contents [r, c, 2] = 0;
+ }
+ }
+ dirtyLine = new bool [rows];
+ for (int row = 0; row < rows; row++)
+ dirtyLine [row] = true;
+ }
+
+ static bool sync = false;
+
+ public MockDriver ()
+ {
+ cols = MockConsole.WindowWidth;
+ rows = MockConsole.WindowHeight; // - 1;
+ UpdateOffscreen ();
+ }
+
+ bool needMove;
+ // Current row, and current col, tracked by Move/AddCh only
+ int ccol, crow;
+ public override void Move (int col, int row)
+ {
+ ccol = col;
+ crow = row;
+
+ if (Clip.Contains (col, row)) {
+ MockConsole.CursorTop = row;
+ MockConsole.CursorLeft = col;
+ needMove = false;
+ } else {
+ MockConsole.CursorTop = Clip.Y;
+ MockConsole.CursorLeft = Clip.X;
+ needMove = true;
+ }
+
+ }
+
+ public override void AddRune (Rune rune)
+ {
+ if (Clip.Contains (ccol, crow)) {
+ if (needMove) {
+ //MockConsole.CursorLeft = ccol;
+ //MockConsole.CursorTop = crow;
+ needMove = false;
+ }
+ contents [crow, ccol, 0] = (int)(uint)rune;
+ contents [crow, ccol, 1] = currentAttribute;
+ contents [crow, ccol, 2] = 1;
+ dirtyLine [crow] = true;
+ } else
+ needMove = true;
+ ccol++;
+ //if (ccol == Cols) {
+ // ccol = 0;
+ // if (crow + 1 < Rows)
+ // crow++;
+ //}
+ if (sync)
+ UpdateScreen ();
+ }
+
+ public override void AddStr (ustring str)
+ {
+ foreach (var rune in str)
+ AddRune (rune);
+ }
+
+ public override void End ()
+ {
+ MockConsole.ResetColor ();
+ MockConsole.Clear ();
+ }
+
+ static Attribute MakeColor (ConsoleColor f, ConsoleColor b)
+ {
+ // Encode the colors into the int value.
+ return new Attribute () { value = ((((int)f) & 0xffff) << 16) | (((int)b) & 0xffff) };
+ }
+
+
+ public override void Init (Action terminalResized)
+ {
+ Colors.TopLevel = new ColorScheme ();
+ Colors.Base = new ColorScheme ();
+ Colors.Dialog = new ColorScheme ();
+ Colors.Menu = new ColorScheme ();
+ Colors.Error = new ColorScheme ();
+ Clip = new Rect (0, 0, Cols, Rows);
+
+ Colors.TopLevel.Normal = MakeColor (ConsoleColor.Green, ConsoleColor.Black);
+ Colors.TopLevel.Focus = MakeColor (ConsoleColor.White, ConsoleColor.DarkCyan);
+ Colors.TopLevel.HotNormal = MakeColor (ConsoleColor.DarkYellow, ConsoleColor.Black);
+ Colors.TopLevel.HotFocus = MakeColor (ConsoleColor.DarkBlue, ConsoleColor.DarkCyan);
+
+ Colors.Base.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Blue);
+ Colors.Base.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
+ Colors.Base.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Blue);
+ Colors.Base.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
+
+ // Focused,
+ // Selected, Hot: Yellow on Black
+ // Selected, text: white on black
+ // Unselected, hot: yellow on cyan
+ // unselected, text: same as unfocused
+ Colors.Menu.HotFocus = MakeColor (ConsoleColor.Yellow, ConsoleColor.Black);
+ Colors.Menu.Focus = MakeColor (ConsoleColor.White, ConsoleColor.Black);
+ Colors.Menu.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Cyan);
+ Colors.Menu.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Cyan);
+ Colors.Menu.Disabled = MakeColor (ConsoleColor.DarkGray, ConsoleColor.Cyan);
+
+ Colors.Dialog.Normal = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
+ Colors.Dialog.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Cyan);
+ Colors.Dialog.HotNormal = MakeColor (ConsoleColor.Blue, ConsoleColor.Gray);
+ Colors.Dialog.HotFocus = MakeColor (ConsoleColor.Blue, ConsoleColor.Cyan);
+
+ Colors.Error.Normal = MakeColor (ConsoleColor.White, ConsoleColor.Red);
+ Colors.Error.Focus = MakeColor (ConsoleColor.Black, ConsoleColor.Gray);
+ Colors.Error.HotNormal = MakeColor (ConsoleColor.Yellow, ConsoleColor.Red);
+ Colors.Error.HotFocus = Colors.Error.HotNormal;
+
+ HLine = '\u2500';
+ VLine = '\u2502';
+ Stipple = '\u2592';
+ Diamond = '\u25c6';
+ ULCorner = '\u250C';
+ LLCorner = '\u2514';
+ URCorner = '\u2510';
+ LRCorner = '\u2518';
+ LeftTee = '\u251c';
+ RightTee = '\u2524';
+ TopTee = '\u22a4';
+ BottomTee = '\u22a5';
+ Checked = '\u221a';
+ UnChecked = ' ';
+ Selected = '\u25cf';
+ UnSelected = '\u25cc';
+ RightArrow = '\u25ba';
+ LeftArrow = '\u25c4';
+ UpArrow = '\u25b2';
+ DownArrow = '\u25bc';
+ LeftDefaultIndicator = '\u25e6';
+ RightDefaultIndicator = '\u25e6';
+ LeftBracket = '[';
+ RightBracket = ']';
+ OnMeterSegment = '\u258c';
+ OffMeterSegement = ' ';
+
+ //MockConsole.Clear ();
+ }
+
+ public override Attribute MakeAttribute (Color fore, Color back)
+ {
+ return MakeColor ((ConsoleColor)fore, (ConsoleColor)back);
+ }
+
+ int redrawColor = -1;
+ void SetColor (int color)
+ {
+ redrawColor = color;
+ IEnumerable values = Enum.GetValues (typeof (ConsoleColor))
+ .OfType ()
+ .Select (s => (int)s);
+ if (values.Contains (color & 0xffff)) {
+ MockConsole.BackgroundColor = (ConsoleColor)(color & 0xffff);
+ }
+ if (values.Contains ((color >> 16) & 0xffff)) {
+ MockConsole.ForegroundColor = (ConsoleColor)((color >> 16) & 0xffff);
+ }
+ }
+
+ public override void UpdateScreen ()
+ {
+ int rows = Rows;
+ int cols = Cols;
+
+ MockConsole.CursorTop = 0;
+ MockConsole.CursorLeft = 0;
+ for (int row = 0; row < rows; row++) {
+ dirtyLine [row] = false;
+ for (int col = 0; col < cols; col++) {
+ contents [row, col, 2] = 0;
+ var color = contents [row, col, 1];
+ if (color != redrawColor)
+ SetColor (color);
+ MockConsole.Write ((char)contents [row, col, 0]);
+ }
+ }
+ }
+
+ public override void Refresh ()
+ {
+ int rows = Rows;
+ int cols = Cols;
+
+ var savedRow = MockConsole.CursorTop;
+ var savedCol = MockConsole.CursorLeft;
+ for (int row = 0; row < rows; row++) {
+ if (!dirtyLine [row])
+ continue;
+ dirtyLine [row] = false;
+ for (int col = 0; col < cols; col++) {
+ if (contents [row, col, 2] != 1)
+ continue;
+
+ MockConsole.CursorTop = row;
+ MockConsole.CursorLeft = col;
+ for (; col < cols && contents [row, col, 2] == 1; col++) {
+ var color = contents [row, col, 1];
+ if (color != redrawColor)
+ SetColor (color);
+
+ MockConsole.Write ((char)contents [row, col, 0]);
+ contents [row, col, 2] = 0;
+ }
+ }
+ }
+ MockConsole.CursorTop = savedRow;
+ MockConsole.CursorLeft = savedCol;
+ }
+
+ public override void UpdateCursor ()
+ {
+ //
+ }
+
+ public override void StartReportingMouseMoves ()
+ {
+ }
+
+ public override void StopReportingMouseMoves ()
+ {
+ }
+
+ public override void Suspend ()
+ {
+ }
+
+ int currentAttribute;
+ public override void SetAttribute (Attribute c)
+ {
+ currentAttribute = c.value;
+ }
+
+ Key MapKey (ConsoleKeyInfo keyInfo)
+ {
+ switch (keyInfo.Key) {
+ case ConsoleKey.Escape:
+ return Key.Esc;
+ case ConsoleKey.Tab:
+ return keyInfo.Modifiers == ConsoleModifiers.Shift ? Key.BackTab : Key.Tab;
+ case ConsoleKey.Home:
+ return Key.Home;
+ case ConsoleKey.End:
+ return Key.End;
+ case ConsoleKey.LeftArrow:
+ return Key.CursorLeft;
+ case ConsoleKey.RightArrow:
+ return Key.CursorRight;
+ case ConsoleKey.UpArrow:
+ return Key.CursorUp;
+ case ConsoleKey.DownArrow:
+ return Key.CursorDown;
+ case ConsoleKey.PageUp:
+ return Key.PageUp;
+ case ConsoleKey.PageDown:
+ return Key.PageDown;
+ case ConsoleKey.Enter:
+ return Key.Enter;
+ case ConsoleKey.Spacebar:
+ return Key.Space;
+ case ConsoleKey.Backspace:
+ return Key.Backspace;
+ case ConsoleKey.Delete:
+ return Key.Delete;
+
+ case ConsoleKey.Oem1:
+ case ConsoleKey.Oem2:
+ case ConsoleKey.Oem3:
+ case ConsoleKey.Oem4:
+ case ConsoleKey.Oem5:
+ case ConsoleKey.Oem6:
+ case ConsoleKey.Oem7:
+ case ConsoleKey.Oem8:
+ case ConsoleKey.Oem102:
+ case ConsoleKey.OemPeriod:
+ case ConsoleKey.OemComma:
+ case ConsoleKey.OemPlus:
+ case ConsoleKey.OemMinus:
+ return (Key)((uint)keyInfo.KeyChar);
+ }
+
+ var key = keyInfo.Key;
+ if (key >= ConsoleKey.A && key <= ConsoleKey.Z) {
+ var delta = key - ConsoleKey.A;
+ if (keyInfo.Modifiers == ConsoleModifiers.Control)
+ return (Key)((uint)Key.ControlA + delta);
+ if (keyInfo.Modifiers == ConsoleModifiers.Alt)
+ return (Key)(((uint)Key.AltMask) | ((uint)'A' + delta));
+ if (keyInfo.Modifiers == ConsoleModifiers.Shift)
+ return (Key)((uint)'A' + delta);
+ else
+ return (Key)((uint)'a' + delta);
+ }
+ if (key >= ConsoleKey.D0 && key <= ConsoleKey.D9) {
+ var delta = key - ConsoleKey.D0;
+ if (keyInfo.Modifiers == ConsoleModifiers.Alt)
+ return (Key)(((uint)Key.AltMask) | ((uint)'0' + delta));
+ if (keyInfo.Modifiers == ConsoleModifiers.Shift)
+ return (Key)((uint)keyInfo.KeyChar);
+ return (Key)((uint)'0' + delta);
+ }
+ if (key >= ConsoleKey.F1 && key <= ConsoleKey.F10) {
+ var delta = key - ConsoleKey.F1;
+
+ return (Key)((int)Key.F1 + delta);
+ }
+ return (Key)(0xffffffff);
+ }
+
+ KeyModifiers keyModifiers = new KeyModifiers ();
+
+ public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler)
+ {
+ // Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
+ (mainLoop.Driver as MockDriver).WindowsKeyPressed = delegate (ConsoleKeyInfo consoleKey) {
+ var map = MapKey (consoleKey);
+ if (map == (Key)0xffffffff)
+ return;
+ keyHandler (new KeyEvent (map, keyModifiers));
+ keyUpHandler (new KeyEvent (map, keyModifiers));
+ };
+ }
+
+ public override void SetColors (ConsoleColor foreground, ConsoleColor background)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void SetColors (short foregroundColorId, short backgroundColorId)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void CookMouse ()
+ {
+ }
+
+ public override void UncookMouse ()
+ {
+ }
+
+ AutoResetEvent keyReady = new AutoResetEvent (false);
+ AutoResetEvent waitForProbe = new AutoResetEvent (false);
+ ConsoleKeyInfo? windowsKeyResult = null;
+ public Action WindowsKeyPressed;
+ MainLoop mainLoop;
+
+ void WindowsKeyReader ()
+ {
+ while (true) {
+ waitForProbe.WaitOne ();
+ windowsKeyResult = MockConsole.ReadKey (true);
+ keyReady.Set ();
+ }
+ }
+
+ void IMainLoopDriver.Setup (MainLoop mainLoop)
+ {
+ this.mainLoop = mainLoop;
+ Thread readThread = new Thread (WindowsKeyReader);
+ readThread.Start ();
+ }
+
+ void IMainLoopDriver.Wakeup ()
+ {
+ }
+
+ bool IMainLoopDriver.EventsPending (bool wait)
+ {
+ long now = DateTime.UtcNow.Ticks;
+
+ int waitTimeout;
+ if (mainLoop.timeouts.Count > 0) {
+ waitTimeout = (int)((mainLoop.timeouts.Keys [0] - now) / TimeSpan.TicksPerMillisecond);
+ if (waitTimeout < 0)
+ return true;
+ } else
+ waitTimeout = -1;
+
+ if (!wait)
+ waitTimeout = 0;
+
+ windowsKeyResult = null;
+ waitForProbe.Set ();
+ keyReady.WaitOne (waitTimeout);
+ return windowsKeyResult.HasValue;
+ }
+
+ void IMainLoopDriver.MainIteration ()
+ {
+ if (windowsKeyResult.HasValue) {
+ if (WindowsKeyPressed != null)
+ WindowsKeyPressed (windowsKeyResult.Value);
+ windowsKeyResult = null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index 9b728dc7c..53aff5e82 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -157,21 +157,28 @@ namespace Terminal.Gui {
/// Creates a and assigns it to and
///
///
- public static void Init () => Init (() => Toplevel.Create ());
+ public static void Init (ConsoleDriver driver = null) => Init (() => Toplevel.Create (), driver);
internal static bool _initialized = false;
///
/// Initializes the Terminal.Gui application
///
- static void Init (Func topLevelFactory)
+ static void Init (Func topLevelFactory, ConsoleDriver driver = null)
{
if (_initialized) return;
+ // This supports Unit Tests and the passing of a mock driver/loopdriver
+ if (driver != null) {
+ Driver = driver;
+ Driver.Init (TerminalResized);
+ MainLoop = new MainLoop ((IMainLoopDriver)driver);
+ SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop));
+ }
+
if (Driver == null) {
var p = Environment.OSVersion.Platform;
IMainLoopDriver mainLoopDriver;
-
if (UseSystemConsole) {
mainLoopDriver = new NetMainLoop ();
Driver = new NetDriver ();
@@ -199,7 +206,11 @@ namespace Terminal.Gui {
public class RunState : IDisposable {
internal bool closeDriver = true;
- internal RunState (Toplevel view)
+ ///
+ /// Initializes a new class.
+ ///
+ ///
+ public RunState (Toplevel view)
{
Toplevel = view;
}
@@ -476,7 +487,7 @@ namespace Terminal.Gui {
}
///
- /// Shutdown an application initialized with
+ /// Shutdown an application initialized with
///
/// /// trueCloses the application.falseCloses toplevels only.
public static void Shutdown (bool closeDriver = true)
diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index ec041fa62..7c5db8966 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -20,7 +20,7 @@ namespace Terminal.Gui {
/// been called (which sets the property to false).
///
///
- /// A Toplevel is created when an application initialzies Terminal.Gui by callling .
+ /// A Toplevel is created when an application initialzies Terminal.Gui by callling .
/// The application Toplevel can be accessed via . Additional Toplevels can be created
/// and run (e.g. s. To run a Toplevel, create the and
/// call .
diff --git a/Terminal.sln b/Terminal.sln
index c5b9ac6bc..6df6d7c65 100644
--- a/Terminal.sln
+++ b/Terminal.sln
@@ -6,10 +6,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example", "Example\Example.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Terminal.Gui", "Terminal.Gui\Terminal.Gui.csproj", "{00F366F8-DEE4-482C-B9FD-6DB0200B79E5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Designer", "Designer\Designer.csproj", "{1228D992-C801-49BB-839A-7BD28A3FFF0A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UICatalog", "UICatalog\UICatalog.csproj", "{88979F89-9A42-448F-AE3E-3060145F6375}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{8B901EDE-8974-4820-B100-5226917E2990}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +52,14 @@ Global
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|Any CPU.Build.0 = Release|Any CPU
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.ActiveCfg = Release|Any CPU
{88979F89-9A42-448F-AE3E-3060145F6375}.Release|x86.Build.0 = Release|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Debug|x86.Build.0 = Debug|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Release|x86.ActiveCfg = Release|Any CPU
+ {8B901EDE-8974-4820-B100-5226917E2990}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/UnitTests/ApplicationTests.cs b/UnitTests/ApplicationTests.cs
new file mode 100644
index 000000000..1676cdb93
--- /dev/null
+++ b/UnitTests/ApplicationTests.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Terminal.Gui;
+using Xunit;
+
+// Alais Console to MockConsole so we don't accidentally use Console
+using Console = Terminal.Gui.MockConsole;
+
+// Since Application is a singleton we can't run tests in parallel
+[assembly: CollectionBehavior (DisableTestParallelization = true)]
+
+namespace Terminal.Gui {
+ public class ApplicationTests {
+ [Fact]
+ public void TestInitShutdown ()
+ {
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+
+ Application.Init (new MockDriver ());
+ Assert.NotNull (Application.Current);
+ Assert.NotNull (Application.CurrentView);
+ Assert.NotNull (Application.Top);
+ Assert.NotNull (Application.MainLoop);
+ Assert.NotNull (Application.Driver);
+
+ // MockDriver is always 80x25
+ Assert.Equal (80, Application.Driver.Cols);
+ Assert.Equal (25, Application.Driver.Rows);
+
+ Application.Shutdown (true);
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+ }
+
+ [Fact]
+ public void TestNewRunState ()
+ {
+ var rs = new Application.RunState (null);
+ Assert.NotNull (rs);
+
+ // Should not throw because Toplevel was null
+ rs.Dispose ();
+
+ var top = new Toplevel ();
+ rs = new Application.RunState (top);
+ Assert.NotNull (rs);
+
+ // Should throw because there's no stack
+ Assert.Throws (() => rs.Dispose ());
+ }
+
+ [Fact]
+ public void TestBeginEnd ()
+ {
+ // Setup Mock driver
+ Application.Init (new MockDriver ());
+ Assert.NotNull (Application.Driver);
+
+ // Test null Toplevel
+ Assert.Throws (() => Application.Begin (null));
+
+ var top = new Toplevel ();
+ var rs = Application.Begin (top);
+ Assert.NotNull (rs);
+ Assert.Equal (top, Application.Current);
+ Application.End (rs, true);
+
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+
+ Application.Shutdown (true);
+ }
+
+ [Fact]
+ public void TestRequestStop ()
+ {
+ // Setup Mock driver
+ Application.Init (new MockDriver ());
+ Assert.NotNull (Application.Driver);
+
+ var top = new Toplevel ();
+ var rs = Application.Begin (top);
+ Assert.NotNull (rs);
+ Assert.Equal (top, Application.Current);
+
+ Application.Iteration = () => {
+ Application.RequestStop ();
+ };
+
+ Application.Run (top, true);
+
+ Application.Shutdown (true);
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+ }
+
+ [Fact]
+ public void TestRunningFalse ()
+ {
+ // Setup Mock driver
+ Application.Init (new MockDriver ());
+ Assert.NotNull (Application.Driver);
+
+ var top = new Toplevel ();
+ var rs = Application.Begin (top);
+ Assert.NotNull (rs);
+ Assert.Equal (top, Application.Current);
+
+ Application.Iteration = () => {
+ top.Running = false;
+ };
+
+ Application.Run (top, true);
+
+ Application.Shutdown (true);
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+ }
+
+
+ [Fact]
+ public void TestKeyUp ()
+ {
+ // Setup Mock driver
+ Application.Init (new MockDriver ());
+ Assert.NotNull (Application.Driver);
+
+ // Setup some fake kepresses (This)
+ var input = "Tests";
+
+ // Put a control-q in at the end
+ Console.MockKeyPresses.Push (new ConsoleKeyInfo ('q', ConsoleKey.Q, shift: false, alt: false, control: true));
+ foreach (var c in input.Reverse()) {
+ if (char.IsLetter (c)) {
+ Console.MockKeyPresses.Push (new ConsoleKeyInfo (char.ToLower (c), (ConsoleKey)char.ToUpper (c), shift: char.IsUpper (c), alt: false, control: false));
+ }
+ else
+ {
+ Console.MockKeyPresses.Push (new ConsoleKeyInfo (c, (ConsoleKey)c, shift: false, alt: false, control: false));
+ }
+ }
+
+ int stackSize = Console.MockKeyPresses.Count;
+
+ int iterations = 0;
+ Application.Iteration = () => {
+ iterations++;
+ };
+
+ int keyUps = 0;
+ var output = string.Empty;
+ Application.Top.KeyUp += (View.KeyEventEventArgs args) => {
+ if (args.KeyEvent.Key != Key.ControlQ) {
+ output += (char)args.KeyEvent.KeyValue;
+ }
+ keyUps++;
+ };
+
+ Application.Run (Application.Top, true);
+
+ // Input string should match output
+ Assert.Equal (input, output);
+
+ // # of key up events should match stack size
+ Assert.Equal (stackSize, keyUps);
+
+ // # of key up events should match # of iterations
+ Assert.Equal (stackSize, iterations);
+
+ Application.Shutdown (true);
+ Assert.Null (Application.Current);
+ Assert.Null (Application.CurrentView);
+ Assert.Null (Application.Top);
+ Assert.Null (Application.MainLoop);
+ Assert.Null (Application.Driver);
+ }
+ }
+}
diff --git a/UnitTests/ConsoleDriverTests.cs b/UnitTests/ConsoleDriverTests.cs
new file mode 100644
index 000000000..b2b040e70
--- /dev/null
+++ b/UnitTests/ConsoleDriverTests.cs
@@ -0,0 +1,67 @@
+using System;
+using Terminal.Gui;
+using Xunit;
+
+// Alais Console to MockConsole so we don't accidentally use Console
+using Console = Terminal.Gui.MockConsole;
+
+namespace Terminal.Gui {
+ public class ConsoleDriverTests {
+ [Fact]
+ public void TestInit ()
+ {
+ var driver = new MockDriver ();
+ driver.Init (() => { });
+
+ Assert.Equal (80, Console.BufferWidth);
+ Assert.Equal (25, Console.BufferHeight);
+
+ // MockDriver is always 80x25
+ Assert.Equal (Console.BufferWidth, driver.Cols);
+ Assert.Equal (Console.BufferHeight, driver.Rows);
+ driver.End ();
+ }
+
+ [Fact]
+ public void TestEnd ()
+ {
+ var driver = new MockDriver ();
+ driver.Init (() => { });
+
+ MockConsole.ForegroundColor = ConsoleColor.Red;
+ Assert.Equal (ConsoleColor.Red, Console.ForegroundColor);
+
+ MockConsole.BackgroundColor = ConsoleColor.Green;
+ Assert.Equal (ConsoleColor.Green, Console.BackgroundColor);
+ driver.Move (2, 3);
+ Assert.Equal (2, Console.CursorLeft);
+ Assert.Equal (3, Console.CursorTop);
+
+ driver.End ();
+ Assert.Equal (0, Console.CursorLeft);
+ Assert.Equal (0, Console.CursorTop);
+ Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
+ Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
+ }
+
+ [Fact]
+ public void TestSetColors ()
+ {
+ var driver = new MockDriver ();
+ driver.Init (() => { });
+ Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
+ Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
+
+ Console.ForegroundColor = ConsoleColor.Red;
+ Assert.Equal (ConsoleColor.Red, Console.ForegroundColor);
+
+ Console.BackgroundColor = ConsoleColor.Green;
+ Assert.Equal (ConsoleColor.Green, Console.BackgroundColor);
+
+ Console.ResetColor ();
+ Assert.Equal (ConsoleColor.Gray, Console.ForegroundColor);
+ Assert.Equal (ConsoleColor.Black, Console.BackgroundColor);
+ driver.End ();
+ }
+ }
+}
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
new file mode 100644
index 000000000..9b10745f5
--- /dev/null
+++ b/UnitTests/UnitTests.csproj
@@ -0,0 +1,20 @@
+
+
+
+ netcoreapp3.1
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/UnitTests/xunit.runner.json b/UnitTests/xunit.runner.json
new file mode 100644
index 000000000..e810a9725
--- /dev/null
+++ b/UnitTests/xunit.runner.json
@@ -0,0 +1,5 @@
+{
+ "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
+ "parallelizeTestCollections": false,
+ "parallelizeAssembly": false
+}