using System; using System.Collections.Concurrent; using System.Text; using System.Threading; using Swan.Threading; namespace Swan { /// /// A console terminal helper to create nicer output and receive input from the user. /// This class is thread-safe :). /// public static partial class Terminal { #region Private Declarations // [Obsolete("NEED", false)] private const Int32 OutputFlushInterval = 15; // [Obsolete("NEED", false)] private static readonly ExclusiveTimer DequeueOutputTimer; // [Obsolete("NEED", false)] private static readonly Object SyncLock = new Object(); // [Obsolete("NEED", false)] private static readonly ConcurrentQueue OutputQueue = new ConcurrentQueue(); // [Obsolete("NEED", false)] private static readonly ManualResetEventSlim OutputDone = new ManualResetEventSlim(false); // [Obsolete("NEED", false)] private static readonly ManualResetEventSlim InputDone = new ManualResetEventSlim(true); // [Obsolete("NEED", false)] private static Boolean? _isConsolePresent; #endregion #region Constructors /// /// Initializes static members of the class. /// // [Obsolete("NEED", false)] static Terminal() { lock(SyncLock) { if(DequeueOutputTimer != null) { return; } if(IsConsolePresent) { Console.CursorVisible = false; } // Here we start the output task, fire-and-forget DequeueOutputTimer = new ExclusiveTimer(DequeueOutputCycle); DequeueOutputTimer.Resume(OutputFlushInterval); } } /// /// Gets a value indicating whether the Console is present. /// /// /// true if this instance is console present; otherwise, false. /// // [Obsolete("NEED", false)] public static Boolean IsConsolePresent { get { if(_isConsolePresent == null) { _isConsolePresent = true; try { Int32 windowHeight = Console.WindowHeight; _isConsolePresent = windowHeight >= 0; } catch { _isConsolePresent = false; } } return _isConsolePresent.Value; } } /// /// Gets the available output writers in a bitwise mask. /// /// /// The available writers. /// // [Obsolete("NEED", false)] public static TerminalWriters AvailableWriters => IsConsolePresent ? TerminalWriters.StandardError | TerminalWriters.StandardOutput : TerminalWriters.None; /// /// Gets or sets the output encoding for the current console. /// /// /// The output encoding. /// // [Obsolete("NEED", false)] public static Encoding OutputEncoding { get => Console.OutputEncoding; set => Console.OutputEncoding = value; } #endregion #region Methods /// /// Enqueues the output to be written to the console /// This is the only method that should enqueue to the output /// Please note that if AvailableWriters is None, then no output will be enqueued. /// /// The context. // [Obsolete("NEED", false)] private static void EnqueueOutput(OutputContext context) { lock(SyncLock) { TerminalWriters availableWriters = AvailableWriters; if(availableWriters == TerminalWriters.None || context.OutputWriters == TerminalWriters.None) { OutputDone.Set(); return; } if((context.OutputWriters & availableWriters) == TerminalWriters.None) { return; } OutputDone.Reset(); OutputQueue.Enqueue(context); } } /// /// Runs a Terminal I/O cycle in the thread. /// // [Obsolete("NEED", false)] private static void DequeueOutputCycle() { if(AvailableWriters == TerminalWriters.None) { OutputDone.Set(); return; } InputDone.Wait(); if(OutputQueue.Count <= 0) { OutputDone.Set(); return; } OutputDone.Reset(); while(OutputQueue.Count > 0) { if(!OutputQueue.TryDequeue(out OutputContext context)) { continue; } // Process Console output and Skip over stuff we can't display so we don't stress the output too much. if(!IsConsolePresent) { continue; } Console.ForegroundColor = context.OutputColor; // Output to the standard output if(context.OutputWriters.HasFlag(TerminalWriters.StandardOutput)) { Console.Out.Write(context.OutputText); } // output to the standard error if(context.OutputWriters.HasFlag(TerminalWriters.StandardError)) { Console.Error.Write(context.OutputText); } Console.ResetColor(); Console.ForegroundColor = context.OriginalColor; } } #endregion #region Output Context /// /// Represents an asynchronous output context. /// // [Obsolete("NEED", false)] private sealed class OutputContext { /// /// Initializes a new instance of the class. /// public OutputContext() { this.OriginalColor = Settings.DefaultColor; this.OutputWriters = IsConsolePresent ? TerminalWriters.StandardOutput : TerminalWriters.None; } public ConsoleColor OriginalColor { get; } public ConsoleColor OutputColor { get; set; } public Char[] OutputText { get; set; } public TerminalWriters OutputWriters { get; set; } } #endregion } }