2019-08-23 11:56:54 -07:00
|
|
|
using System.Text;
|
|
|
|
using System.IO;
|
|
|
|
using System.Threading;
|
2020-05-22 06:05:33 -07:00
|
|
|
using System.Threading.Tasks;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
namespace System
|
|
|
|
{
|
|
|
|
public static class Console
|
|
|
|
{
|
2020-05-05 08:18:32 -07:00
|
|
|
static Encoding InputEncoding = Encoding.ASCII;
|
|
|
|
static Encoding OutputEncoding = Encoding.ASCII;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-05-05 08:18:32 -07:00
|
|
|
static ConsoleColor sForegroundColor = .White;
|
|
|
|
static ConsoleColor sBackgroundColor = .Black;
|
2020-05-05 15:30:43 +02:00
|
|
|
|
2020-05-05 08:18:32 -07:00
|
|
|
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
|
|
|
|
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
|
2020-05-05 15:30:43 +02:00
|
|
|
|
|
|
|
public static ConsoleColor ForegroundColor
|
|
|
|
{
|
2020-05-05 08:18:32 -07:00
|
|
|
get { return sForegroundColor; }
|
|
|
|
set { sForegroundColor = value; SetColors(); }
|
2020-05-05 15:30:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static ConsoleColor BackgroundColor
|
|
|
|
{
|
2020-05-05 08:18:32 -07:00
|
|
|
get { return sBackgroundColor; }
|
|
|
|
set { sBackgroundColor = value; SetColors(); }
|
2020-05-05 15:30:43 +02:00
|
|
|
}
|
|
|
|
|
2020-05-05 08:18:32 -07:00
|
|
|
const uint32 STD_INPUT_HANDLE = (uint32)-10;
|
|
|
|
const uint32 STD_OUTPUT_HANDLE = (uint32)-11;
|
|
|
|
const uint32 STD_ERROR_HANDLE = (uint32)-12;
|
2020-05-05 15:30:43 +02:00
|
|
|
|
2020-05-05 08:18:32 -07:00
|
|
|
[CRepr]
|
|
|
|
struct CONSOLE_SCREEN_BUFFER_INFO
|
|
|
|
{
|
|
|
|
public uint16[2] mSize;
|
|
|
|
public uint16[2] mCursorPosition;
|
|
|
|
public uint16 mAttributes;
|
|
|
|
public uint16[4] mWindow;
|
|
|
|
public uint16[2] mMaximumWindowSize;
|
|
|
|
}
|
|
|
|
|
2020-05-25 20:46:28 +08:00
|
|
|
[CLink, CallingConvention(.Stdcall)]
|
2020-05-05 08:18:32 -07:00
|
|
|
static extern int SetConsoleTextAttribute(void* hConsoleOutput, uint16 wAttributes);
|
|
|
|
|
2020-05-25 20:46:28 +08:00
|
|
|
[CLink, CallingConvention(.Stdcall)]
|
2020-05-05 08:18:32 -07:00
|
|
|
static extern int GetConsoleScreenBufferInfo(void* hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
|
|
|
|
|
2020-05-25 20:46:28 +08:00
|
|
|
[CLink, CallingConvention(.Stdcall)]
|
2020-05-05 08:18:32 -07:00
|
|
|
static extern void* GetStdHandle(uint32 nStdHandle);
|
|
|
|
|
|
|
|
#if BF_PLATFORM_WINDOWS
|
|
|
|
public static this()
|
|
|
|
{
|
|
|
|
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO consoleInfo = .();
|
|
|
|
if (GetConsoleScreenBufferInfo(handle, out consoleInfo) != 0)
|
|
|
|
{
|
|
|
|
sOriginalForegroundColor.ConsoleTextAttribute = (uint8)(consoleInfo.mAttributes & 0xF);
|
|
|
|
sOriginalBackgroundColor.ConsoleTextAttribute = (uint8)(consoleInfo.mAttributes >> 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2020-05-05 15:30:43 +02:00
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
static StreamWriter OpenStreamWriter(Platform.BfpFileStdKind stdKind, ref StreamWriter outStreamWriter)
|
|
|
|
{
|
|
|
|
if (outStreamWriter == null)
|
|
|
|
{
|
|
|
|
FileStream fileStream = new .();
|
|
|
|
Stream stream = fileStream;
|
|
|
|
if (fileStream.OpenStd(stdKind) case .Err)
|
|
|
|
{
|
|
|
|
DeleteAndNullify!(fileStream);
|
|
|
|
stream = new NullStream();
|
|
|
|
}
|
|
|
|
|
|
|
|
StreamWriter newStreamWriter = new StreamWriter(stream, InputEncoding, 4096, true);
|
|
|
|
newStreamWriter.AutoFlush = true;
|
|
|
|
|
|
|
|
let prevValue = Interlocked.CompareExchange(ref outStreamWriter, null, newStreamWriter);
|
|
|
|
if (prevValue != null)
|
|
|
|
{
|
|
|
|
// This was already set - race condition
|
|
|
|
delete newStreamWriter;
|
|
|
|
return prevValue;
|
|
|
|
}
|
|
|
|
return newStreamWriter;
|
|
|
|
}
|
|
|
|
return outStreamWriter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static StreamReader OpenStreamReader(Platform.BfpFileStdKind stdKind, ref StreamReader outStreamReader)
|
|
|
|
{
|
|
|
|
if (outStreamReader == null)
|
|
|
|
{
|
|
|
|
FileStream fileStream = new .();
|
|
|
|
Stream stream = fileStream;
|
|
|
|
if (fileStream.OpenStd(stdKind) case .Err)
|
|
|
|
{
|
|
|
|
DeleteAndNullify!(fileStream);
|
|
|
|
stream = new NullStream();
|
|
|
|
}
|
|
|
|
|
|
|
|
StreamReader newStreamReader = new StreamReader(stream, InputEncoding, false, 4096, true);
|
|
|
|
|
|
|
|
let prevValue = Interlocked.CompareExchange(ref outStreamReader, null, newStreamReader);
|
|
|
|
if (prevValue != null)
|
|
|
|
{
|
|
|
|
// This was already set - race condition
|
|
|
|
delete newStreamReader;
|
|
|
|
return prevValue;
|
|
|
|
}
|
|
|
|
return newStreamReader;
|
|
|
|
}
|
|
|
|
return outStreamReader;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static volatile StreamWriter mOut ~ delete _;
|
|
|
|
public static StreamWriter Out
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return OpenStreamWriter(.Out, ref mOut);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static volatile StreamWriter mError ~ delete _;
|
|
|
|
public static StreamWriter Error
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return OpenStreamWriter(.Error, ref mError);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static volatile StreamReader mIn ~ delete _;
|
|
|
|
public static StreamReader In
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return OpenStreamReader(.In, ref mIn);
|
|
|
|
}
|
|
|
|
}
|
2020-05-22 11:06:20 +02:00
|
|
|
|
|
|
|
public static Result<char8> Read() => In.Read();
|
|
|
|
|
|
|
|
public static Result<void> ReadLine(String strBuffer) => In.ReadLine(strBuffer);
|
|
|
|
|
|
|
|
public static Task<String> ReadLineAsync() => In.ReadLineAsync();
|
|
|
|
|
|
|
|
public static Result<void> ReadToEnd(String outText) => In.ReadToEnd(outText);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
public static void Write(String line)
|
|
|
|
{
|
|
|
|
Out.Write(line).IgnoreError();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void Write(String fmt, params Object[] args)
|
|
|
|
{
|
2020-03-25 09:17:53 -07:00
|
|
|
String str = scope String(256);
|
2019-08-23 11:56:54 -07:00
|
|
|
str.AppendF(fmt, params args);
|
|
|
|
Write(str);
|
|
|
|
}
|
2020-03-25 21:57:49 +08:00
|
|
|
|
|
|
|
public static void Write(Object obj)
|
|
|
|
{
|
2020-03-25 09:17:53 -07:00
|
|
|
String str = scope String(256);
|
2020-03-25 21:57:49 +08:00
|
|
|
obj.ToString(str);
|
|
|
|
Write(str);
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-25 09:17:53 -07:00
|
|
|
public static void WriteLine()
|
|
|
|
{
|
|
|
|
Out.Write("\n").IgnoreError();
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
public static void WriteLine(String line)
|
|
|
|
{
|
|
|
|
Out.WriteLine(line).IgnoreError();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void WriteLine(StringView fmt, params Object[] args)
|
|
|
|
{
|
2020-03-25 09:17:53 -07:00
|
|
|
String str = scope String(256);
|
2019-08-23 11:56:54 -07:00
|
|
|
str.AppendF(fmt, params args);
|
|
|
|
WriteLine(str);
|
|
|
|
}
|
2020-03-25 21:50:34 +08:00
|
|
|
|
|
|
|
public static void WriteLine(Object obj)
|
|
|
|
{
|
2020-03-25 09:17:53 -07:00
|
|
|
String str = scope String(256);
|
2020-03-25 21:50:34 +08:00
|
|
|
obj.ToString(str);
|
|
|
|
WriteLine(str);
|
|
|
|
}
|
2020-05-05 15:30:43 +02:00
|
|
|
|
|
|
|
public static void ResetColor()
|
|
|
|
{
|
2020-05-05 08:18:32 -07:00
|
|
|
sForegroundColor = sOriginalForegroundColor;
|
|
|
|
sBackgroundColor = sOriginalBackgroundColor;
|
2020-05-05 15:30:43 +02:00
|
|
|
|
|
|
|
#if !BF_PLATFORM_WINDOWS
|
|
|
|
Write("\x1B[0m");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-05-05 08:18:32 -07:00
|
|
|
static void SetColors()
|
2020-05-05 15:30:43 +02:00
|
|
|
{
|
|
|
|
#if BF_PLATFORM_WINDOWS
|
|
|
|
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
2020-05-05 08:18:32 -07:00
|
|
|
let fgColor = ForegroundColor.ConsoleTextAttribute;
|
|
|
|
let bgColor = BackgroundColor.ConsoleTextAttribute;
|
2020-05-05 15:30:43 +02:00
|
|
|
SetConsoleTextAttribute(handle, bgColor * 16 + fgColor);
|
|
|
|
#else
|
2020-05-06 17:41:08 -07:00
|
|
|
Write("\x1B[{}m", ForegroundColor.AnsiCode);
|
|
|
|
Write("\x1B[{}m", BackgroundColor.AnsiCode + 10);
|
2020-05-05 15:30:43 +02:00
|
|
|
#endif
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
}
|