diff --git a/src/Microsoft.PowerShell.PSReadLine/Completion.cs b/src/Microsoft.PowerShell.PSReadLine/Completion.cs index 4407de00f1..cba45cd01b 100644 --- a/src/Microsoft.PowerShell.PSReadLine/Completion.cs +++ b/src/Microsoft.PowerShell.PSReadLine/Completion.cs @@ -307,9 +307,9 @@ namespace Microsoft.PowerShell { int j = i + start; #if LINUX // TODO: use real inverse - ConsoleColor tempColor = (int)buffer[j].ForegroundColor == -1 + ConsoleColor tempColor = buffer[j].ForegroundColor == UnknownColor ? ConsoleColor.White : buffer[j].ForegroundColor; - buffer[j].ForegroundColor = (int)buffer[j].BackgroundColor == -1 + buffer[j].ForegroundColor = buffer[j].BackgroundColor == UnknownColor ? ConsoleColor.Black : buffer[j].BackgroundColor; buffer[j].BackgroundColor = tempColor; #else diff --git a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs index 76c46d40da..03be91594d 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ConsoleLib.cs @@ -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 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(Func func) { -#if LINUX // TODO: move to IConsole when there is a Linux IConsole implementation - bool psReadlineControlCMode = Console.TreatControlCAsInput; + var currentMode = _console.GetConsoleInputMode(); try { - Console.TreatControlCAsInput = _prePSReadlineControlCMode; + _console.RestoreConsoleInputMode(_savedConsoleInputMode); return func(); } finally { - Console.TreatControlCAsInput = psReadlineControlCMode; + _console.RestoreConsoleInputMode(currentMode); } -#else - uint psReadlineConsoleMode = _console.GetConsoleInputMode(); - try - { - _console.SetConsoleInputMode(_prePSReadlineConsoleMode); - return func(); - } - finally - { - _console.SetConsoleInputMode(psReadlineConsoleMode); - } -#endif } void CalloutUsingDefaultConsoleMode(Action action) @@ -519,7 +479,11 @@ namespace Microsoft.PowerShell private PSConsoleReadLine() { _mockableMethods = this; +#if LINUX + _console = new TTYConsole(); +#else _console = new ConhostConsole(); +#endif SetDefaultWindowsBindings(); @@ -788,13 +752,11 @@ namespace Microsoft.PowerShell return; } - #region VI special case if (_singleton._options.EditMode == EditMode.Vi && key.Value.KeyChar == '0') { BeginningOfLine(); return; } - #endregion VI special case bool sawDigit = false; _singleton._statusLinePrompt = "digit-argument: "; diff --git a/src/Microsoft.PowerShell.PSReadLine/Render.cs b/src/Microsoft.PowerShell.PSReadLine/Render.cs index 876dc3f66b..1d468fa333 100644 --- a/src/Microsoft.PowerShell.PSReadLine/Render.cs +++ b/src/Microsoft.PowerShell.PSReadLine/Render.cs @@ -13,6 +13,7 @@ namespace Microsoft.PowerShell { public partial class PSConsoleReadLine { + private const ConsoleColor UnknownColor = (ConsoleColor) (-1); private CHAR_INFO[] _consoleBuffer; private int _initialX; private int _initialY; @@ -464,8 +465,8 @@ namespace Microsoft.PowerShell // but looks best with the 2 default color schemes - starting PowerShell // from it's shortcut or from a cmd shortcut. #if LINUX // TODO: set Inverse attribute and let render choose what to do. - ConsoleColor tempColor = ((int)foregroundColor == -1) ? ConsoleColor.White : foregroundColor; - foregroundColor = ((int)backgroundColor == -1) ? ConsoleColor.Black : backgroundColor; + ConsoleColor tempColor = (foregroundColor == UnknownColor) ? ConsoleColor.White : foregroundColor; + foregroundColor = (backgroundColor == UnknownColor) ? ConsoleColor.Black : backgroundColor; backgroundColor = tempColor; #else foregroundColor = (ConsoleColor)((int)foregroundColor ^ 7);