NetWinVTConsole.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System.Runtime.InteropServices;
  2. namespace Terminal.Gui;
  3. internal class NetWinVTConsole
  4. {
  5. private const uint DISABLE_NEWLINE_AUTO_RETURN = 8;
  6. private const uint ENABLE_ECHO_INPUT = 4;
  7. private const uint ENABLE_EXTENDED_FLAGS = 128;
  8. private const uint ENABLE_INSERT_MODE = 32;
  9. private const uint ENABLE_LINE_INPUT = 2;
  10. private const uint ENABLE_LVB_GRID_WORLDWIDE = 10;
  11. private const uint ENABLE_MOUSE_INPUT = 16;
  12. // Input modes.
  13. private const uint ENABLE_PROCESSED_INPUT = 1;
  14. // Output modes.
  15. private const uint ENABLE_PROCESSED_OUTPUT = 1;
  16. private const uint ENABLE_QUICK_EDIT_MODE = 64;
  17. private const uint ENABLE_VIRTUAL_TERMINAL_INPUT = 512;
  18. private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
  19. private const uint ENABLE_WINDOW_INPUT = 8;
  20. private const uint ENABLE_WRAP_AT_EOL_OUTPUT = 2;
  21. private const int STD_ERROR_HANDLE = -12;
  22. private const int STD_INPUT_HANDLE = -10;
  23. private const int STD_OUTPUT_HANDLE = -11;
  24. private readonly nint _errorHandle;
  25. private readonly nint _inputHandle;
  26. private readonly uint _originalErrorConsoleMode;
  27. private readonly uint _originalInputConsoleMode;
  28. private readonly uint _originalOutputConsoleMode;
  29. private readonly nint _outputHandle;
  30. public NetWinVTConsole ()
  31. {
  32. _inputHandle = GetStdHandle (STD_INPUT_HANDLE);
  33. if (!GetConsoleMode (_inputHandle, out uint mode))
  34. {
  35. throw new ApplicationException ($"Failed to get input console mode, error code: {GetLastError ()}.");
  36. }
  37. _originalInputConsoleMode = mode;
  38. if ((mode & ENABLE_VIRTUAL_TERMINAL_INPUT) < ENABLE_VIRTUAL_TERMINAL_INPUT)
  39. {
  40. mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
  41. if (!SetConsoleMode (_inputHandle, mode))
  42. {
  43. throw new ApplicationException ($"Failed to set input console mode, error code: {GetLastError ()}.");
  44. }
  45. }
  46. _outputHandle = GetStdHandle (STD_OUTPUT_HANDLE);
  47. if (!GetConsoleMode (_outputHandle, out mode))
  48. {
  49. throw new ApplicationException ($"Failed to get output console mode, error code: {GetLastError ()}.");
  50. }
  51. _originalOutputConsoleMode = mode;
  52. if ((mode & (ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN)) < DISABLE_NEWLINE_AUTO_RETURN)
  53. {
  54. mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
  55. if (!SetConsoleMode (_outputHandle, mode))
  56. {
  57. throw new ApplicationException ($"Failed to set output console mode, error code: {GetLastError ()}.");
  58. }
  59. }
  60. _errorHandle = GetStdHandle (STD_ERROR_HANDLE);
  61. if (!GetConsoleMode (_errorHandle, out mode))
  62. {
  63. throw new ApplicationException ($"Failed to get error console mode, error code: {GetLastError ()}.");
  64. }
  65. _originalErrorConsoleMode = mode;
  66. if ((mode & DISABLE_NEWLINE_AUTO_RETURN) < DISABLE_NEWLINE_AUTO_RETURN)
  67. {
  68. mode |= DISABLE_NEWLINE_AUTO_RETURN;
  69. if (!SetConsoleMode (_errorHandle, mode))
  70. {
  71. throw new ApplicationException ($"Failed to set error console mode, error code: {GetLastError ()}.");
  72. }
  73. }
  74. }
  75. public void Cleanup ()
  76. {
  77. if (!SetConsoleMode (_inputHandle, _originalInputConsoleMode))
  78. {
  79. throw new ApplicationException ($"Failed to restore input console mode, error code: {GetLastError ()}.");
  80. }
  81. if (!SetConsoleMode (_outputHandle, _originalOutputConsoleMode))
  82. {
  83. throw new ApplicationException ($"Failed to restore output console mode, error code: {GetLastError ()}.");
  84. }
  85. if (!SetConsoleMode (_errorHandle, _originalErrorConsoleMode))
  86. {
  87. throw new ApplicationException ($"Failed to restore error console mode, error code: {GetLastError ()}.");
  88. }
  89. }
  90. [DllImport ("kernel32.dll")]
  91. private static extern bool GetConsoleMode (nint hConsoleHandle, out uint lpMode);
  92. [DllImport ("kernel32.dll")]
  93. private static extern uint GetLastError ();
  94. [DllImport ("kernel32.dll", SetLastError = true)]
  95. private static extern nint GetStdHandle (int nStdHandle);
  96. [DllImport ("kernel32.dll")]
  97. private static extern bool SetConsoleMode (nint hConsoleHandle, uint dwMode);
  98. }