mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Introduce TTYConsole for UNIX
This commit is contained in:
@@ -317,7 +317,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
public CHAR_INFO(char c, ConsoleColor foreground, ConsoleColor background)
|
||||
{
|
||||
UnicodeChar = c;
|
||||
Attributes = (ushort)(((int)background << 4) | (int)foreground);
|
||||
Attributes = (ushort)((((int)background << 4) & 0xf) | ((int)foreground & 0xf));
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
@@ -330,7 +330,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
[ExcludeFromCodeCoverage]
|
||||
public ConsoleColor BackgroundColor
|
||||
{
|
||||
get { return (ConsoleColor)((Attributes & 0xf0) >> 4); }
|
||||
get { return (ConsoleColor)((Attributes & 0x00f0) >> 4); }
|
||||
set { Attributes = (ushort)((Attributes & 0xff0f) | (((int)value & 0xf) << 4)); }
|
||||
}
|
||||
|
||||
@@ -426,6 +426,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
}
|
||||
}
|
||||
|
||||
#if !LINUX
|
||||
internal class ConhostConsole : IConsole
|
||||
{
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
|
||||
@@ -482,18 +483,42 @@ namespace Microsoft.PowerShell.Internal
|
||||
return new SafeFileHandle(handle, true);
|
||||
});
|
||||
|
||||
public uint GetConsoleInputMode()
|
||||
public object GetConsoleInputMode()
|
||||
{
|
||||
uint mode;
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
uint result;
|
||||
NativeMethods.GetConsoleMode(handle, out result);
|
||||
return result;
|
||||
NativeMethods.GetConsoleMode(handle, out mode);
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void SetConsoleInputMode(uint mode)
|
||||
public void SetConsoleInputMode(object modeObj)
|
||||
{
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, mode);
|
||||
if (modeObj is uint)
|
||||
{
|
||||
// Clear a couple flags so we can actually receive certain keys:
|
||||
// ENABLE_PROCESSED_INPUT - enables Ctrl+C
|
||||
// ENABLE_LINE_INPUT - enables Ctrl+S
|
||||
// Also clear a couple flags so we don't mask the input that we ignore:
|
||||
// ENABLE_MOUSE_INPUT - mouse events
|
||||
// ENABLE_WINDOW_INPUT - window resize events
|
||||
var mode = (uint)modeObj &
|
||||
~(NativeMethods.ENABLE_PROCESSED_INPUT |
|
||||
NativeMethods.ENABLE_LINE_INPUT |
|
||||
NativeMethods.ENABLE_WINDOW_INPUT |
|
||||
NativeMethods.ENABLE_MOUSE_INPUT);
|
||||
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreConsoleInputMode(object modeObj)
|
||||
{
|
||||
if (modeObj is uint)
|
||||
{
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, (uint)modeObj);
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleKeyInfo ReadKey()
|
||||
@@ -601,24 +626,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
ScrollBuffer(scrollCount);
|
||||
top -= scrollCount;
|
||||
}
|
||||
#if LINUX
|
||||
ConsoleColor foregroundColor = Console.ForegroundColor;
|
||||
ConsoleColor backgroundColor = Console.BackgroundColor;
|
||||
|
||||
Console.SetCursorPosition(0, (top>=0) ? top : 0);
|
||||
|
||||
for (int i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
// TODO: use escape sequences for better perf
|
||||
Console.ForegroundColor = buffer[i].ForegroundColor;
|
||||
Console.BackgroundColor = buffer[i].BackgroundColor;
|
||||
|
||||
Console.Write((char)buffer[i].UnicodeChar);
|
||||
}
|
||||
|
||||
Console.BackgroundColor = backgroundColor;
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
var bufferSize = new COORD
|
||||
{
|
||||
@@ -643,18 +651,10 @@ namespace Microsoft.PowerShell.Internal
|
||||
{
|
||||
Console.CursorTop = bottom;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ScrollBuffer(int lines)
|
||||
{
|
||||
#if LINUX
|
||||
for (int i=0; i<lines; ++i)
|
||||
{
|
||||
Console.SetCursorPosition(Console.BufferWidth, Console.BufferHeight - 1);
|
||||
Console.WriteLine();
|
||||
}
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
|
||||
var scrollRectangle = new SMALL_RECT
|
||||
@@ -667,20 +667,11 @@ namespace Microsoft.PowerShell.Internal
|
||||
var destinationOrigin = new COORD {X = 0, Y = 0};
|
||||
var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
|
||||
NativeMethods.ScrollConsoleScreenBuffer(handle, ref scrollRectangle, IntPtr.Zero, destinationOrigin, ref fillChar);
|
||||
#endif
|
||||
}
|
||||
|
||||
public CHAR_INFO[] ReadBufferLines(int top, int count)
|
||||
{
|
||||
var result = new CHAR_INFO[BufferWidth * count];
|
||||
#if LINUX
|
||||
for (int i=0; i<BufferWidth*count; ++i)
|
||||
{
|
||||
result[i].UnicodeChar = ' ';
|
||||
result[i].ForegroundColor = Console.ForegroundColor;
|
||||
result[i].BackgroundColor = Console.BackgroundColor;
|
||||
}
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
|
||||
var readBufferSize = new COORD {
|
||||
@@ -696,7 +687,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
};
|
||||
NativeMethods.ReadConsoleOutput(handle, result,
|
||||
readBufferSize, readBufferCoord, ref readRegion);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -891,14 +882,196 @@ namespace Microsoft.PowerShell.Internal
|
||||
NativeMethods.ReleaseDC(_hwnd, _hDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX // TODO: this is not correct, PSReadline never clears the screen, it should only scroll
|
||||
#else
|
||||
|
||||
internal class TTYConsole : IConsole
|
||||
{
|
||||
public object GetConsoleInputMode()
|
||||
{
|
||||
return Console.TreatControlCAsInput;
|
||||
}
|
||||
|
||||
public void SetConsoleInputMode(object modeObj)
|
||||
{
|
||||
Console.TreatControlCAsInput = true;
|
||||
}
|
||||
|
||||
public void RestoreConsoleInputMode(object modeObj)
|
||||
{
|
||||
if (modeObj is bool)
|
||||
{
|
||||
Console.TreatControlCAsInput = (bool)modeObj;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleKeyInfo ReadKey()
|
||||
{
|
||||
return Console.ReadKey(true);
|
||||
}
|
||||
|
||||
public bool KeyAvailable
|
||||
{
|
||||
get { return Console.KeyAvailable; }
|
||||
}
|
||||
|
||||
public int CursorLeft
|
||||
{
|
||||
get { return Console.CursorLeft; }
|
||||
set { Console.CursorLeft = value; }
|
||||
}
|
||||
|
||||
public int CursorTop
|
||||
{
|
||||
get { return Console.CursorTop; }
|
||||
set { Console.CursorTop = value; }
|
||||
}
|
||||
|
||||
public int CursorSize
|
||||
{
|
||||
get { return Console.CursorSize; }
|
||||
set { Console.CursorSize = value; }
|
||||
}
|
||||
|
||||
public int BufferWidth
|
||||
{
|
||||
get { return Console.BufferWidth; }
|
||||
set { Console.BufferWidth = value; }
|
||||
}
|
||||
|
||||
public int BufferHeight
|
||||
{
|
||||
get { return Console.BufferHeight; }
|
||||
set { Console.BufferHeight = value; }
|
||||
}
|
||||
|
||||
public int WindowWidth
|
||||
{
|
||||
get { return Console.WindowWidth; }
|
||||
set { Console.WindowWidth = value; }
|
||||
}
|
||||
|
||||
public int WindowHeight
|
||||
{
|
||||
get { return Console.WindowHeight; }
|
||||
set { Console.WindowHeight = value; }
|
||||
}
|
||||
|
||||
public int WindowTop
|
||||
{
|
||||
get { return Console.WindowTop; }
|
||||
set { Console.WindowTop = value; }
|
||||
}
|
||||
|
||||
public ConsoleColor BackgroundColor
|
||||
{
|
||||
get { return Console.BackgroundColor; }
|
||||
set { Console.BackgroundColor = value; }
|
||||
}
|
||||
|
||||
public ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return Console.ForegroundColor; }
|
||||
set { Console.ForegroundColor = value; }
|
||||
}
|
||||
|
||||
public void SetWindowPosition(int left, int top)
|
||||
{
|
||||
Console.SetWindowPosition(left, top);
|
||||
}
|
||||
|
||||
public void SetCursorPosition(int left, int top)
|
||||
{
|
||||
Console.SetCursorPosition(left, top);
|
||||
}
|
||||
|
||||
public void Write(string value)
|
||||
{
|
||||
Console.Write(value);
|
||||
}
|
||||
|
||||
public void WriteLine(string value)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(CHAR_INFO[] buffer, ref int top)
|
||||
{
|
||||
WriteBufferLines(buffer, ref top, true);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(CHAR_INFO[] buffer, ref int top, bool ensureBottomLineVisible)
|
||||
{
|
||||
int bufferWidth = Console.BufferWidth;
|
||||
int bufferLineCount = buffer.Length / bufferWidth;
|
||||
if ((top + bufferLineCount) > Console.BufferHeight)
|
||||
{
|
||||
var scrollCount = (top + bufferLineCount) - Console.BufferHeight;
|
||||
ScrollBuffer(scrollCount);
|
||||
top -= scrollCount;
|
||||
}
|
||||
|
||||
ConsoleColor foregroundColor = Console.ForegroundColor;
|
||||
ConsoleColor backgroundColor = Console.BackgroundColor;
|
||||
|
||||
Console.SetCursorPosition(0, (top>=0) ? top : 0);
|
||||
|
||||
for (int i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
// TODO: use escape sequences for better perf
|
||||
Console.ForegroundColor = buffer[i].ForegroundColor;
|
||||
Console.BackgroundColor = buffer[i].BackgroundColor;
|
||||
|
||||
Console.Write((char)buffer[i].UnicodeChar);
|
||||
}
|
||||
|
||||
Console.BackgroundColor = backgroundColor;
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
}
|
||||
|
||||
public void ScrollBuffer(int lines)
|
||||
{
|
||||
for (int i=0; i<lines; ++i)
|
||||
{
|
||||
Console.SetCursorPosition(Console.BufferWidth, Console.BufferHeight - 1);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public CHAR_INFO[] ReadBufferLines(int top, int count)
|
||||
{
|
||||
var result = new CHAR_INFO[BufferWidth * count];
|
||||
for (int i=0; i<BufferWidth*count; ++i)
|
||||
{
|
||||
result[i].UnicodeChar = ' ';
|
||||
result[i].ForegroundColor = Console.ForegroundColor;
|
||||
result[i].BackgroundColor = Console.BackgroundColor;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int LengthInBufferCells(char c)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
public void StartRender()
|
||||
{
|
||||
}
|
||||
|
||||
public void EndRender()
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: this is not correct, PSReadline never clears the screen, it should only scroll
|
||||
public void Clear()
|
||||
{
|
||||
Console.Clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CORECLR // TODO: remove if CORECLR adds this attribute back
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)]
|
||||
|
||||
Reference in New Issue
Block a user