namespace Terminal.Gui.Drivers;
///
/// Implementation of that uses native dotnet
/// methods e.g.
///
public class NetOutput : OutputBase, IOutput
{
private readonly bool _isWinPlatform;
///
/// Creates a new instance of the class.
///
public NetOutput ()
{
Logging.Information ($"Creating {nameof (NetOutput)}");
try
{
Console.OutputEncoding = Encoding.UTF8;
}
catch
{
// ignore for unit tests
}
PlatformID p = Environment.OSVersion.Platform;
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
{
_isWinPlatform = true;
}
}
///
public void Write (ReadOnlySpan text)
{
try
{
Console.Out.Write (text);
}
catch (IOException)
{
// Not connected to a terminal; do nothing
}
}
///
public Size GetSize ()
{
try
{
Size size = new (Console.WindowWidth, Console.WindowHeight);
return size.IsEmpty ? new (80, 25) : size;
}
catch (IOException)
{
// Not connected to a terminal; return a default size
return new (80, 25);
}
}
///
public Point GetCursorPosition ()
{
return _lastCursorPosition ?? Point.Empty;
}
///
public void SetCursorPosition (int col, int row) { SetCursorPositionImpl (col, row); }
///
public void SetSize (int width, int height)
{
// Do Nothing.
}
private Point? _lastCursorPosition;
///
protected override void AppendOrWriteAttribute (StringBuilder output, Attribute attr, TextStyle redrawTextStyle)
{
if (Force16Colors)
{
output.Append (EscSeqUtils.CSI_SetForegroundColor (attr.Foreground.GetAnsiColorCode ()));
output.Append (EscSeqUtils.CSI_SetBackgroundColor (attr.Background.GetAnsiColorCode ()));
}
else
{
EscSeqUtils.CSI_AppendForegroundColorRGB (
output,
attr.Foreground.R,
attr.Foreground.G,
attr.Foreground.B
);
EscSeqUtils.CSI_AppendBackgroundColorRGB (
output,
attr.Background.R,
attr.Background.G,
attr.Background.B
);
}
EscSeqUtils.CSI_AppendTextStyleChange (output, redrawTextStyle, attr.Style);
}
///
protected override void Write (StringBuilder output)
{
base.Write (output);
try
{
Console.Out.Write (output);
}
catch (IOException)
{
// Not connected to a terminal; do nothing
}
}
///
protected override bool SetCursorPositionImpl (int col, int row)
{
if (_lastCursorPosition is { } && _lastCursorPosition.Value.X == col && _lastCursorPosition.Value.Y == row)
{
return true;
}
_lastCursorPosition = new (col, row);
if (_isWinPlatform)
{
// Could happen that the windows is still resizing and the col is bigger than Console.WindowWidth.
try
{
Console.SetCursorPosition (col, row);
return true;
}
catch (Exception)
{
return true;
}
}
// + 1 is needed because non-Windows is based on 1 instead of 0 and
// Console.CursorTop/CursorLeft isn't reliable.
EscSeqUtils.CSI_WriteCursorPosition (Console.Out, row + 1, col + 1);
return true;
}
///
public void Dispose ()
{
}
private EscSeqUtils.DECSCUSR_Style? _currentDecscusrStyle;
///
public override void SetCursorVisibility (CursorVisibility visibility)
{
try
{
if (visibility != CursorVisibility.Invisible)
{
if (_currentDecscusrStyle is null || _currentDecscusrStyle != (EscSeqUtils.DECSCUSR_Style)(((int)visibility >> 24) & 0xFF))
{
_currentDecscusrStyle = (EscSeqUtils.DECSCUSR_Style)(((int)visibility >> 24) & 0xFF);
Write (EscSeqUtils.CSI_SetCursorStyle ((EscSeqUtils.DECSCUSR_Style)_currentDecscusrStyle));
}
Write (EscSeqUtils.CSI_ShowCursor);
}
else
{
Write (EscSeqUtils.CSI_HideCursor);
}
}
catch
{
// Ignore any exceptions
}
}
}