| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- #nullable enable
- using System.Runtime.InteropServices;
- // ReSharper disable InconsistentNaming
- namespace Terminal.Gui.Drivers;
- #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
- /// <summary>
- /// Definitions for Windows Console API structures and constants.
- /// </summary>
- public class WindowsConsole
- {
- /// <summary>
- /// Standard input handle constant.
- /// </summary>
- public const int STD_INPUT_HANDLE = -10;
- /// <summary>
- /// Windows Console mode flags.
- /// </summary>
- [Flags]
- public enum ConsoleModes : uint
- {
- EnableProcessedInput = 1,
- EnableVirtualTerminalProcessing = 4,
- EnableMouseInput = 16,
- EnableQuickEditMode = 64,
- EnableExtendedFlags = 128
- }
- /// <summary>
- /// Key event record structure.
- /// </summary>
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct KeyEventRecord
- {
- [FieldOffset (0)]
- [MarshalAs (UnmanagedType.Bool)]
- public bool bKeyDown;
- [FieldOffset (4)]
- [MarshalAs (UnmanagedType.U2)]
- public ushort wRepeatCount;
- [FieldOffset (6)]
- [MarshalAs (UnmanagedType.U2)]
- public ConsoleKeyMapping.VK wVirtualKeyCode;
- [FieldOffset (8)]
- [MarshalAs (UnmanagedType.U2)]
- public ushort wVirtualScanCode;
- [FieldOffset (10)]
- public char UnicodeChar;
- [FieldOffset (12)]
- [MarshalAs (UnmanagedType.U4)]
- public ControlKeyState dwControlKeyState;
- public readonly override string ToString ()
- {
- return
- $"[KeyEventRecord({(bKeyDown ? "down" : "up")},{wRepeatCount},{wVirtualKeyCode},{wVirtualScanCode},{new Rune (UnicodeChar).MakePrintable ()},{dwControlKeyState})]";
- }
- }
- [Flags]
- public enum ButtonState
- {
- NoButtonPressed = 0,
- Button1Pressed = 1,
- Button2Pressed = 4,
- Button3Pressed = 8,
- Button4Pressed = 16,
- RightmostButtonPressed = 2
- }
- [Flags]
- public enum ControlKeyState
- {
- NoControlKeyPressed = 0,
- RightAltPressed = 1,
- LeftAltPressed = 2,
- RightControlPressed = 4,
- LeftControlPressed = 8,
- ShiftPressed = 16,
- NumlockOn = 32,
- ScrolllockOn = 64,
- CapslockOn = 128,
- EnhancedKey = 256
- }
- [Flags]
- public enum EventFlags
- {
- NoEvent = 0,
- MouseMoved = 1,
- DoubleClick = 2,
- MouseWheeled = 4,
- MouseHorizontalWheeled = 8
- }
- [StructLayout (LayoutKind.Explicit)]
- public struct MouseEventRecord
- {
- [FieldOffset (0)]
- public Coord MousePosition;
- [FieldOffset (4)]
- public ButtonState ButtonState;
- [FieldOffset (8)]
- public ControlKeyState ControlKeyState;
- [FieldOffset (12)]
- public EventFlags EventFlags;
- public readonly override string ToString () { return $"[Mouse{MousePosition},{ButtonState},{ControlKeyState},{EventFlags}]"; }
- }
- public struct WindowBufferSizeRecord (short x, short y)
- {
- public Coord _size = new (x, y);
- public readonly override string ToString () { return $"[WindowBufferSize{_size}"; }
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct MenuEventRecord
- {
- public uint dwCommandId;
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct FocusEventRecord
- {
- public uint bSetFocus;
- }
- public enum EventType : ushort
- {
- Focus = 0x10,
- Key = 0x1,
- Menu = 0x8,
- Mouse = 2,
- WindowBufferSize = 4
- }
- [StructLayout (LayoutKind.Explicit)]
- public struct InputRecord
- {
- [FieldOffset (0)]
- public EventType EventType;
- [FieldOffset (4)]
- public KeyEventRecord KeyEvent;
- [FieldOffset (4)]
- public MouseEventRecord MouseEvent;
- [FieldOffset (4)]
- public WindowBufferSizeRecord WindowBufferSizeEvent;
- [FieldOffset (4)]
- public MenuEventRecord MenuEvent;
- [FieldOffset (4)]
- public FocusEventRecord FocusEvent;
- public readonly override string ToString ()
- {
- return (EventType switch
- {
- EventType.Focus => FocusEvent.ToString (),
- EventType.Key => KeyEvent.ToString (),
- EventType.Menu => MenuEvent.ToString (),
- EventType.Mouse => MouseEvent.ToString (),
- EventType.WindowBufferSize => WindowBufferSizeEvent.ToString (),
- _ => "Unknown event type: " + EventType
- })!;
- }
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct Coord
- {
- public short X;
- public short Y;
- public Coord (short x, short y)
- {
- X = x;
- Y = y;
- }
- public readonly override string ToString () { return $"({X},{Y})"; }
- }
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct CharUnion
- {
- [FieldOffset (0)]
- public char UnicodeChar;
- [FieldOffset (0)]
- public byte AsciiChar;
- }
- [StructLayout (LayoutKind.Explicit, CharSet = CharSet.Unicode)]
- public struct CharInfo
- {
- [FieldOffset (0)]
- public CharUnion Char;
- [FieldOffset (2)]
- public ushort Attributes;
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct SmallRect
- {
- public short Left;
- public short Top;
- public short Right;
- public short Bottom;
- public SmallRect (short left, short top, short right, short bottom)
- {
- Left = left;
- Top = top;
- Right = right;
- Bottom = bottom;
- }
- public static void MakeEmpty (ref SmallRect rect) { rect.Left = -1; }
- public static void Update (ref SmallRect rect, short col, short row)
- {
- if (rect.Left == -1)
- {
- rect.Left = rect.Right = col;
- rect.Bottom = rect.Top = row;
- return;
- }
- if (col >= rect.Left && col <= rect.Right && row >= rect.Top && row <= rect.Bottom)
- {
- return;
- }
- if (col < rect.Left)
- {
- rect.Left = col;
- }
- if (col > rect.Right)
- {
- rect.Right = col;
- }
- if (row < rect.Top)
- {
- rect.Top = row;
- }
- if (row > rect.Bottom)
- {
- rect.Bottom = row;
- }
- }
- public readonly override string ToString () { return $"Left={Left},Top={Top},Right={Right},Bottom={Bottom}"; }
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct ConsoleKeyInfoEx
- {
- public ConsoleKeyInfo ConsoleKeyInfo;
- public bool CapsLock;
- public bool NumLock;
- public bool ScrollLock;
- public ConsoleKeyInfoEx (ConsoleKeyInfo consoleKeyInfo, bool capslock, bool numlock, bool scrolllock)
- {
- ConsoleKeyInfo = consoleKeyInfo;
- CapsLock = capslock;
- NumLock = numlock;
- ScrollLock = scrolllock;
- }
- /// <summary>
- /// Prints a ConsoleKeyInfoEx structure
- /// </summary>
- /// <param name="ex"></param>
- /// <returns></returns>
- public readonly string ToString (ConsoleKeyInfoEx ex)
- {
- var ke = new Key ((KeyCode)ex.ConsoleKeyInfo.KeyChar);
- var sb = new StringBuilder ();
- sb.Append ($"Key: {(KeyCode)ex.ConsoleKeyInfo.Key} ({ex.ConsoleKeyInfo.Key})");
- sb.Append ((ex.ConsoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0 ? " | Shift" : string.Empty);
- sb.Append ((ex.ConsoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0 ? " | Control" : string.Empty);
- sb.Append ((ex.ConsoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0 ? " | Alt" : string.Empty);
- sb.Append ($", KeyChar: {ke.AsRune.MakePrintable ()} ({(uint)ex.ConsoleKeyInfo.KeyChar}) ");
- sb.Append (ex.CapsLock ? "caps," : string.Empty);
- sb.Append (ex.NumLock ? "num," : string.Empty);
- sb.Append (ex.ScrollLock ? "scroll," : string.Empty);
- string s = sb.ToString ().TrimEnd (',').TrimEnd (' ');
- return $"[ConsoleKeyInfoEx({s})]";
- }
- }
- [StructLayout (LayoutKind.Sequential)]
- public struct ConsoleCursorInfo
- {
- /// <summary>
- /// The percentage of the character cell that is filled by the cursor.This value is between 1 and 100.
- /// The cursor appearance varies, ranging from completely filling the cell to showing up as a horizontal
- /// line at the bottom of the cell.
- /// </summary>
- public uint dwSize;
- public bool bVisible;
- }
- // See: https://github.com/gui-cs/Terminal.Gui/issues/357
- [StructLayout (LayoutKind.Sequential)]
- public struct CONSOLE_SCREEN_BUFFER_INFOEX
- {
- public uint cbSize;
- public Coord dwSize;
- public Coord dwCursorPosition;
- public ushort wAttributes;
- public SmallRect srWindow;
- public Coord dwMaximumWindowSize;
- public ushort wPopupAttributes;
- public bool bFullscreenSupported;
- [MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
- public COLORREF [] ColorTable;
- }
- [StructLayout (LayoutKind.Explicit, Size = 4)]
- public struct COLORREF
- {
- public COLORREF (byte r, byte g, byte b)
- {
- Value = 0;
- R = r;
- G = g;
- B = b;
- }
- public COLORREF (uint value)
- {
- R = 0;
- G = 0;
- B = 0;
- Value = value & 0x00FFFFFF;
- }
- [FieldOffset (0)]
- public byte R;
- [FieldOffset (1)]
- public byte G;
- [FieldOffset (2)]
- public byte B;
- [FieldOffset (0)]
- public uint Value;
- }
- }
|