using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using Cosmos.HAL; namespace Cosmos.System { /// /// Standard output stream. /// public class Console { /// /// Line feed. /// private const byte LineFeed = (byte)'\n'; /// /// Carriage return. /// private const byte CarriageReturn = (byte)'\r'; /// /// Tab. /// private const byte Tab = (byte)'\t'; /// /// Space. /// private const byte Space = (byte)' '; /// /// Cursor location on X axis. /// protected int mX = 0; /// /// Get and set cursor location on X axis. /// public int X { get { return mX; } set { mX = value; UpdateCursor(); } } /// /// Cursor location on Y axis. /// protected int mY = 0; /// /// Get and set cursor location on Y axis. /// public int Y { get { return mY; } set { mY = value; UpdateCursor(); } } /// /// Get window width. /// public int Cols { get { return mText.Cols; } } /// /// Get window height. /// public int Rows { get { return mText.Rows; } } /// /// Text screen. /// protected HAL.TextScreenBase mText; /// /// Console object constructor. /// /// Output device. public Console(TextScreenBase textScreen) { if (textScreen == null) { mText = new TextScreen(); } else { mText = textScreen; } } /// /// Clear console and return cursor to (0,0). /// public void Clear() { mText.Clear(); mX = 0; mY = 0; UpdateCursor(); } //TODO: This is slow, batch it and only do it at end of updates /// /// Update cursor position. /// protected void UpdateCursor() { mText.SetCursorPos(mX, mY); } /// /// Scroll the console up and move crusor to the start of the line. /// private void DoLineFeed() { mY++; mX = 0; if (mY == mText.Rows) { mText.ScrollUp(); mY--; } UpdateCursor(); } /// /// Move cursor to the start of the line. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DoCarriageReturn() { mX = 0; UpdateCursor(); } /// /// Print tab to the console. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DoTab() { Write(Space); Write(Space); Write(Space); Write(Space); } /// /// Write char to the console. /// /// A char to write public void Write(byte aChar) { mText[mX, mY] = aChar; mX++; if (mX == mText.Cols) { DoLineFeed(); } UpdateCursor(); } //TODO: Optimize this /// /// Write byte array to the console. /// /// A byte array to write to the console. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Write(byte[] aText) { if (aText == null) { return; } for (int i = 0; i < aText.Length; i++) { switch (aText[i]) { case LineFeed: DoLineFeed(); break; case CarriageReturn: DoCarriageReturn(); break; case Tab: DoTab(); break; /* Normal characters, simply write them */ default: Write(aText[i]); break; } } } /// /// Get and set console foreground color. /// public ConsoleColor Foreground { get { return (ConsoleColor)(mText.GetColor() ^ (byte)((byte)Background << 4)); } set { mText.SetColors(value, Background); } } /// /// Get and set console background color. /// public ConsoleColor Background { get { return (ConsoleColor)(mText.GetColor() >> 4); } set { mText.SetColors(Foreground, value); } } /// /// Get and set cursor size. /// The value is percentage in the range 1-100. /// /// Thrown when trying to set value out of range. public int CursorSize { get { return mText.GetCursorSize(); } set { // Value should be a percentage from [1, 100]. if (value < 1 || value > 100) throw new ArgumentOutOfRangeException("value", value, "CursorSize value " + value + " out of range (1 - 100)"); mText.SetCursorSize(value); } } /// /// Get and set cursor visiblty. /// public bool CursorVisible { get { return mText.GetCursorVisible(); } set { mText.SetCursorVisible(value); } } } }