Kon.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Security.Permissions;
  4. namespace BepInEx.ConsoleUtil
  5. {
  6. internal class Kon
  7. {
  8. #region pinvoke
  9. [DllImport("kernel32.dll", SetLastError = true)]
  10. private static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
  11. [DllImport("kernel32.dll", SetLastError = true)]
  12. private static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes);
  13. [DllImport("kernel32.dll", SetLastError = true)]
  14. private static extern IntPtr GetStdHandle(int nStdHandle);
  15. #endregion
  16. #region Types
  17. private struct CONSOLE_SCREEN_BUFFER_INFO
  18. {
  19. internal COORD dwSize;
  20. internal COORD dwCursorPosition;
  21. internal short wAttributes;
  22. internal SMALL_RECT srWindow;
  23. internal COORD dwMaximumWindowSize;
  24. }
  25. private struct COORD
  26. {
  27. internal short X;
  28. internal short Y;
  29. }
  30. private struct SMALL_RECT
  31. {
  32. internal short Left;
  33. internal short Top;
  34. internal short Right;
  35. internal short Bottom;
  36. }
  37. private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
  38. #endregion
  39. #region Private
  40. private static short ConsoleColorToColorAttribute(short color, bool isBackground)
  41. {
  42. if ((color & -16) != 0)
  43. throw new ArgumentException("Arg_InvalidConsoleColor");
  44. if (isBackground)
  45. color <<= 4;
  46. return color;
  47. }
  48. private static CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(bool throwOnNoConsole, out bool succeeded)
  49. {
  50. succeeded = false;
  51. if (!(conOut == INVALID_HANDLE_VALUE))
  52. {
  53. try
  54. {
  55. // FIXME: Windows console shouldn't be used in other OSs in the first place
  56. CONSOLE_SCREEN_BUFFER_INFO console_SCREEN_BUFFER_INFO;
  57. if (!GetConsoleScreenBufferInfo(conOut, out console_SCREEN_BUFFER_INFO))
  58. {
  59. bool consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-12), out console_SCREEN_BUFFER_INFO);
  60. if (!consoleScreenBufferInfo)
  61. consoleScreenBufferInfo = GetConsoleScreenBufferInfo(GetStdHandle(-10), out console_SCREEN_BUFFER_INFO);
  62. if (!consoleScreenBufferInfo)
  63. if (Marshal.GetLastWin32Error() == 6 && !throwOnNoConsole)
  64. return default(CONSOLE_SCREEN_BUFFER_INFO);
  65. }
  66. succeeded = true;
  67. return console_SCREEN_BUFFER_INFO;
  68. }
  69. catch (EntryPointNotFoundException)
  70. {
  71. // Fails under unsupported OSes
  72. }
  73. }
  74. if (!throwOnNoConsole)
  75. return default(CONSOLE_SCREEN_BUFFER_INFO);
  76. throw new Exception("IO.IO_NoConsole");
  77. }
  78. private static void SetConsoleColor(bool isBackground, ConsoleColor c)
  79. {
  80. new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();
  81. var color = ConsoleColorToColorAttribute((short)c, isBackground);
  82. bool flag;
  83. var bufferInfo = GetBufferInfo(false, out flag);
  84. if (!flag)
  85. return;
  86. var num = bufferInfo.wAttributes;
  87. num &= (short)(isBackground ? -241 : -16);
  88. num = (short)((ushort)num | (ushort)color);
  89. SetConsoleTextAttribute(conOut, num);
  90. }
  91. private static ConsoleColor GetConsoleColor(bool isBackground)
  92. {
  93. bool flag;
  94. var bufferInfo = GetBufferInfo(false, out flag);
  95. if (!flag)
  96. return isBackground ? ConsoleColor.Black : ConsoleColor.Gray;
  97. return ColorAttributeToConsoleColor((short)(bufferInfo.wAttributes & 240));
  98. }
  99. private static ConsoleColor ColorAttributeToConsoleColor(short c)
  100. {
  101. if ((short)(c & 255) != 0)
  102. c >>= 4;
  103. return (ConsoleColor)c;
  104. }
  105. internal static IntPtr conOut = IntPtr.Zero;
  106. #endregion
  107. #region Public
  108. public static void ResetConsoleColor()
  109. {
  110. SetConsoleColor(true, ConsoleColor.Black);
  111. SetConsoleColor(false, ConsoleColor.Gray);
  112. }
  113. public static ConsoleColor ForegroundColor
  114. {
  115. get { return GetConsoleColor(false); }
  116. set { SetConsoleColor(false, value); }
  117. }
  118. public static ConsoleColor BackgroundColor
  119. {
  120. get { return GetConsoleColor(true); }
  121. set { SetConsoleColor(true, value); }
  122. }
  123. #endregion
  124. }
  125. }