NetOutput.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using Microsoft.Extensions.Logging;
  2. namespace Terminal.Gui.Drivers;
  3. /// <summary>
  4. /// Implementation of <see cref="IConsoleOutput"/> that uses native dotnet
  5. /// methods e.g. <see cref="System.Console"/>
  6. /// </summary>
  7. public class NetOutput : OutputBase, IConsoleOutput
  8. {
  9. private readonly bool _isWinPlatform;
  10. /// <summary>
  11. /// Creates a new instance of the <see cref="NetOutput"/> class.
  12. /// </summary>
  13. public NetOutput ()
  14. {
  15. Logging.Logger.LogInformation ($"Creating {nameof (NetOutput)}");
  16. Console.OutputEncoding = Encoding.UTF8;
  17. PlatformID p = Environment.OSVersion.Platform;
  18. if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
  19. {
  20. _isWinPlatform = true;
  21. }
  22. }
  23. /// <inheritdoc/>
  24. public void Write (ReadOnlySpan<char> text) { Console.Out.Write (text); }
  25. /// <inheritdoc/>
  26. public Size GetWindowSize ()
  27. {
  28. if (ConsoleDriver.RunningUnitTests)
  29. {
  30. // For unit tests, we return a default size.
  31. return Size.Empty;
  32. }
  33. return new (Console.WindowWidth, Console.WindowHeight);
  34. }
  35. /// <inheritdoc/>
  36. public void SetCursorPosition (int col, int row) { SetCursorPositionImpl (col, row); }
  37. private Point? _lastCursorPosition;
  38. /// <inheritdoc/>
  39. protected override void AppendOrWriteAttribute (StringBuilder output, Attribute attr, TextStyle redrawTextStyle)
  40. {
  41. EscSeqUtils.CSI_AppendForegroundColorRGB (
  42. output,
  43. attr.Foreground.R,
  44. attr.Foreground.G,
  45. attr.Foreground.B
  46. );
  47. EscSeqUtils.CSI_AppendBackgroundColorRGB (
  48. output,
  49. attr.Background.R,
  50. attr.Background.G,
  51. attr.Background.B
  52. );
  53. EscSeqUtils.CSI_AppendTextStyleChange (output, redrawTextStyle, attr.Style);
  54. }
  55. /// <inheritdoc/>
  56. protected override void Write (StringBuilder output) { Console.Out.Write (output); }
  57. protected override bool SetCursorPositionImpl (int col, int row)
  58. {
  59. if (_lastCursorPosition is { } && _lastCursorPosition.Value.X == col && _lastCursorPosition.Value.Y == row)
  60. {
  61. return true;
  62. }
  63. _lastCursorPosition = new (col, row);
  64. if (_isWinPlatform)
  65. {
  66. // Could happens that the windows is still resizing and the col is bigger than Console.WindowWidth.
  67. try
  68. {
  69. Console.SetCursorPosition (col, row);
  70. return true;
  71. }
  72. catch (Exception)
  73. {
  74. return false;
  75. }
  76. }
  77. // + 1 is needed because non-Windows is based on 1 instead of 0 and
  78. // Console.CursorTop/CursorLeft isn't reliable.
  79. EscSeqUtils.CSI_WriteCursorPosition (Console.Out, row + 1, col + 1);
  80. return true;
  81. }
  82. /// <inheritdoc/>
  83. public void Dispose () { }
  84. /// <inheritdoc/>
  85. public override void SetCursorVisibility (CursorVisibility visibility)
  86. {
  87. Console.Out.Write (visibility == CursorVisibility.Default ? EscSeqUtils.CSI_ShowCursor : EscSeqUtils.CSI_HideCursor);
  88. }
  89. }