Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 59 additions & 37 deletions TrueColorConsole/VTConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,37 @@ public static partial class VTConsole
{
#region Interop

private const uint StdOutputHandle = unchecked((uint) -11);
private const uint StdInputHandle = unchecked((uint) -10);
private static readonly IntPtr InvalidHandleValue = new IntPtr(-1);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(uint nStdHandle);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
private static class NativeMethods
{
public const uint StdOutputHandle = unchecked((uint) -11);
public const uint StdInputHandle = unchecked((uint) -10);
public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(uint nStdHandle);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WriteConsole(
IntPtr hConsoleOutput,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int lpNumberOfCharsToWrite,
out int lpNumberOfCharsToWritten,
IntPtr lpReserved
);
}

private static bool GetConsoleMode(IntPtr hConsoleHandle, out ConsoleModeOutput mode)
{
if (!GetConsoleMode(hConsoleHandle, out uint lpMode))
if (!NativeMethods.GetConsoleMode(hConsoleHandle, out uint lpMode))
{
mode = 0;
return false;
Expand All @@ -39,7 +56,7 @@ private static bool GetConsoleMode(IntPtr hConsoleHandle, out ConsoleModeOutput

private static bool GetConsoleMode(IntPtr hConsoleHandle, out ConsoleModeInput mode)
{
if (!GetConsoleMode(hConsoleHandle, out uint lpMode))
if (!NativeMethods.GetConsoleMode(hConsoleHandle, out uint lpMode))
{
mode = 0;
return false;
Expand All @@ -49,30 +66,16 @@ private static bool GetConsoleMode(IntPtr hConsoleHandle, out ConsoleModeInput m
return true;
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WriteConsole(
IntPtr hConsoleOutput,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,
int lpNumberOfCharsToWrite,
out int lpNumberOfCharsToWritten,
IntPtr lpReserved
);

private static bool GetStdIn(out IntPtr handle)
{
handle = GetStdHandle(StdInputHandle);
return handle != InvalidHandleValue;
handle = NativeMethods.GetStdHandle(NativeMethods.StdInputHandle);
return handle != NativeMethods.InvalidHandleValue;
}

private static bool GetStdOut(out IntPtr handle)
{
handle = GetStdHandle(StdOutputHandle);
return handle != InvalidHandleValue;
handle = NativeMethods.GetStdHandle(NativeMethods.StdOutputHandle);
return handle != NativeMethods.InvalidHandleValue;
}

#endregion
Expand All @@ -91,12 +94,24 @@ private static bool GetStdOut(out IntPtr handle)
private static ConsoleModeInput _inLast;
private static IntPtr _outHandle;
private static ConsoleModeOutput _outLast;
private static bool _isEnabled;

private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

/// <summary>
/// Gets if virtual terminal features are enabled.
/// </summary>
[PublicAPI]
public static bool IsEnabled { get; private set; }
public static bool IsEnabled
{
get
{
if (IsWindows)
return _isEnabled;
return true;
}
private set => _isEnabled = value;
}

/// <summary>
/// Gets if virtual terminal features are supported (see Remarks).
Expand Down Expand Up @@ -147,7 +162,7 @@ bool EnableInput()

var mode = _inLast | ConsoleModeInput.EnableVirtualTerminalInput;

return SetConsoleMode(StdIn, (uint) mode);
return NativeMethods.SetConsoleMode(StdIn, (uint) mode);
}

bool EnableOutput()
Expand All @@ -163,12 +178,12 @@ bool EnableOutput()
if (disableNewLineAutoReturn)
mode |= ConsoleModeOutput.DisableNewlineAutoReturn;

if (SetConsoleMode(StdOut, (uint) mode))
if (NativeMethods.SetConsoleMode(StdOut, (uint) mode))
return true;

mode = _outLast | ConsoleModeOutput.EnableVirtualTerminalProcessing;

return SetConsoleMode(StdOut, (uint) mode);
return NativeMethods.SetConsoleMode(StdOut, (uint) mode);
}

IsEnabled = EnableInput() && EnableOutput();
Expand All @@ -185,17 +200,19 @@ bool EnableOutput()
[PublicAPI]
public static bool Disable()
{
if (!IsWindows)
return true;
if (!IsEnabled)
return false;

bool DisableInput()
{
return GetStdIn(out var handle) && SetConsoleMode(handle, (uint) _inLast);
return GetStdIn(out var handle) && NativeMethods.SetConsoleMode(handle, (uint) _inLast);
}

bool DisableOutput()
{
return GetStdOut(out var handle) && SetConsoleMode(handle, (uint) _outLast);
return GetStdOut(out var handle) && NativeMethods.SetConsoleMode(handle, (uint) _outLast);
}

IsEnabled = !(DisableInput() && DisableOutput());
Expand Down Expand Up @@ -284,7 +301,12 @@ public static void SetFormat(params VTFormat[] formats)
[PublicAPI]
public static int WriteFast(byte[] buffer)
{
WriteConsole(StdOut, buffer, buffer.Length, out var written, IntPtr.Zero);
if (!IsWindows)
{
Console.Write(Console.OutputEncoding.GetString(buffer));
return buffer.Length;
}
NativeMethods.WriteConsole(StdOut, buffer, buffer.Length, out var written, IntPtr.Zero);
return written;
}

Expand Down
25 changes: 17 additions & 8 deletions TrueColorConsoleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using TrueColorConsole;
Expand Down Expand Up @@ -75,23 +76,31 @@ private static void Example2()
private static void Example3()
{
var plasma = new Plasma(256, 256);
var width = 80;
var height = 40;

Console.SetWindowSize(width, height);
Console.SetBufferSize(width, height);
Console.SetWindowSize(width, height); // removes bars
Console.Title = "Plasma !";
Console.CursorVisible = false;

var width = Console.WindowWidth;
var height = Console.WindowHeight;
var builder = new StringBuilder(width * height * 22);
var resetEvent = new AutoResetEvent(true);

using(new Timer(x =>{resetEvent.Set();}, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(1.0/20*1000)))
for (var frame = 0; ; frame++)
{
if (width != Console.WindowWidth || height != Console.WindowHeight)
{
width = Console.WindowWidth;
height = Console.WindowHeight;
Console.WriteLine();
builder = new StringBuilder(width * height * 22);
}
else
{
builder.Clear();
}
plasma.PlasmaFrame(frame);
builder.Clear();

Thread.Sleep((int)(1.0 / 20 * 1000));
resetEvent.WaitOne();

for (var i = 0; i < width * height; i++)
{
Expand Down