using XFESystem.Console; using XfeConsoleApi = XFEExtension.NetCore.XFEConsole.XFEConsole; namespace XFESystem.ManagedRuntime; /// Console API calls are bound to one guest terminal, never to host stdout or files. public sealed class TerminalManagedConsole(TerminalTextWriter writer) : IManagedConsole { private ConsoleColor _foreground = ConsoleColor.Cyan, _background = ConsoleColor.Black; private int _written; public ConsoleColor ForegroundColor { get => _foreground; set { var color = TerminalColor.FromConsoleColor(value); _foreground = value; Control($"\u001b[38;2;{color.Red};{color.Green};{color.Blue}m"); } } public ConsoleColor BackgroundColor { get => _background; set { var color = TerminalColor.FromConsoleColor(value); _background = value; Control($"\u001b[48;2;{color.Red};{color.Green};{color.Blue}m"); } } public void ResetColor() { _foreground = ConsoleColor.Cyan; _background = ConsoleColor.Black; Control("\u001b[0m"); } public void Write(string value) { Limit(value.Length); writer.Write(value); } public void WriteLine(string value) { Limit(value.Length + 2); writer.Write(value); writer.Write("\r\n"); } public void XfeWriteLine(string value) { Limit(value.Length + 2); var oldWriter = XfeConsoleApi.CurrentConsoleTextWriter; bool oldDebug = XfeConsoleApi.ShowInDebug, oldLocal = XfeConsoleApi.ShowInLocalConsole, oldLog = XfeConsoleApi.EnableLog; try { XfeConsoleApi.CurrentConsoleTextWriter = new(writer); XfeConsoleApi.ShowInDebug = false; XfeConsoleApi.ShowInLocalConsole = true; XfeConsoleApi.EnableLog = false; XfeConsoleApi.WriteLine(value); } catch { Restore(); throw; } Restore(); // The current native exception unwinder does not execute finally clauses. void Restore() { XfeConsoleApi.CurrentConsoleTextWriter = oldWriter; XfeConsoleApi.ShowInDebug = oldDebug; XfeConsoleApi.ShowInLocalConsole = oldLocal; XfeConsoleApi.EnableLog = oldLog; } } private void Control(string sequence) { Limit(sequence.Length); writer.Write(sequence); } private void Limit(int count) { if (count > ManagedRuntimeCapabilities.MaxOutputCharacters - _written) throw new InvalidOperationException("Managed console output limit exceeded."); _written += count; } }