From 8d62f3966f5df72f586bc03675004a62b423e782 Mon Sep 17 00:00:00 2001 From: tznind Date: Fri, 3 Mar 2023 01:37:30 +0000 Subject: [PATCH] Fix bad merge changes --- ReactiveExample/ReactiveExample.csproj | 4 +- .../CursesDriver/CursesDriver.cs | 479 +++++- .../CursesDriver/UnixMainLoop.cs | 30 +- .../CursesDriver/UnmanagedLibrary.cs | 35 +- .../ConsoleDrivers/CursesDriver/binding.cs | 5 + .../ConsoleDrivers/CursesDriver/constants.cs | 4 +- .../ConsoleDrivers/FakeDriver/FakeConsole.cs | 1369 ++++++++-------- .../ConsoleDrivers/FakeDriver/FakeDriver.cs | 26 +- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 1453 +++++++++++------ Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 92 +- Terminal.Gui/Core/Application.cs | 31 +- Terminal.Gui/Core/Border.cs | 21 +- Terminal.Gui/Core/ConsoleDriver.cs | 95 +- Terminal.Gui/Core/ConsoleKeyMapping.cs | 19 - Terminal.Gui/Core/Event.cs | 2 +- Terminal.Gui/Core/View.cs | 201 +-- Terminal.Gui/Core/Window.cs | 19 +- Terminal.Gui/Terminal.Gui.csproj | 1 - Terminal.Gui/Views/FrameView.cs | 11 +- Terminal.Gui/Views/TileView.cs | 6 +- UICatalog/Properties/launchSettings.json | 10 +- UICatalog/Scenarios/BordersComparisons.cs | 5 +- UICatalog/Scenarios/TileViewExperiment.cs | 41 +- UICatalog/UICatalog.cs | 9 +- UnitTests/Application/ApplicationTests.cs | 10 +- UnitTests/Core/BorderTests.cs | 14 +- UnitTests/Drivers/ConsoleDriverTests.cs | 30 +- UnitTests/UnitTests.csproj | 4 +- 28 files changed, 2448 insertions(+), 1578 deletions(-) diff --git a/ReactiveExample/ReactiveExample.csproj b/ReactiveExample/ReactiveExample.csproj index 04793513d..c2ce6640c 100644 --- a/ReactiveExample/ReactiveExample.csproj +++ b/ReactiveExample/ReactiveExample.csproj @@ -11,8 +11,8 @@ 1.0 - - + + diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 7e5f4dcfd..ec2220519 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -1,6 +1,9 @@ // // Driver.cs: Curses-based Driver // +// Authors: +// Miguel de Icaza (miguel@gnome.org) +// using System; using System.Collections.Generic; using System.Diagnostics; @@ -20,12 +23,7 @@ namespace Terminal.Gui { public override int Rows => Curses.Lines; public override int Left => 0; public override int Top => 0; - public override bool EnableConsoleScrolling { get; set; } - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] - public override bool HeightAsBuffer { - get => EnableConsoleScrolling; - set => EnableConsoleScrolling = value; - } + public override bool HeightAsBuffer { get; set; } public override IClipboard Clipboard { get => clipboard; } CursorVisibility? initialCursorVisibility = null; @@ -118,7 +116,7 @@ namespace Terminal.Gui { if (runeWidth < 0 || runeWidth > 0) { ccol++; } - + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -160,10 +158,26 @@ namespace Terminal.Gui { public override void End () { - StopReportingMouseMoves (); + if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) { + StopReportingMouseMoves (); + } + SetCursorVisibility (CursorVisibility.Default); Curses.endwin (); + + // I'm commenting this because was used in a trying to fix the Linux hanging and forgot to exclude it. + // Clear and reset entire screen. + //Console.Out.Write ("\x1b[2J"); + //Console.Out.Flush (); + + // Set top and bottom lines of a window. + //Console.Out.Write ("\x1b[1;25r"); + //Console.Out.Flush (); + + //Set cursor key to cursor. + //Console.Out.Write ("\x1b[?1l"); + //Console.Out.Flush (); } public override void UpdateScreen () => window.redrawwin (); @@ -310,6 +324,305 @@ namespace Terminal.Gui { } } + Curses.Event? lastMouseButtonPressed; + bool isButtonPressed; + bool cancelButtonClicked; + bool isReportMousePosition; + Point point; + int buttonPressedCount; + + MouseEvent ToDriverMouse (Curses.MouseEvent cev) + { + MouseFlags mouseFlag = MouseFlags.AllEvents; + + if (lastMouseButtonPressed != null && cev.ButtonState != Curses.Event.ReportMousePosition) { + lastMouseButtonPressed = null; + isButtonPressed = false; + } + + if (cev.ButtonState == Curses.Event.Button1Pressed + || cev.ButtonState == Curses.Event.Button2Pressed + || cev.ButtonState == Curses.Event.Button3Pressed) { + + isButtonPressed = true; + buttonPressedCount++; + } else { + buttonPressedCount = 0; + } + //System.Diagnostics.Debug.WriteLine ($"buttonPressedCount: {buttonPressedCount}"); + + if (buttonPressedCount == 2 + && (cev.ButtonState == Curses.Event.Button1Pressed + || cev.ButtonState == Curses.Event.Button2Pressed + || cev.ButtonState == Curses.Event.Button3Pressed)) { + + switch (cev.ButtonState) { + case Curses.Event.Button1Pressed: + mouseFlag = MouseFlags.Button1DoubleClicked; + break; + + case Curses.Event.Button2Pressed: + mouseFlag = MouseFlags.Button2DoubleClicked; + break; + + case Curses.Event.Button3Pressed: + mouseFlag = MouseFlags.Button3DoubleClicked; + break; + } + cancelButtonClicked = true; + + } else if (buttonPressedCount == 3 + && (cev.ButtonState == Curses.Event.Button1Pressed + || cev.ButtonState == Curses.Event.Button2Pressed + || cev.ButtonState == Curses.Event.Button3Pressed)) { + + switch (cev.ButtonState) { + case Curses.Event.Button1Pressed: + mouseFlag = MouseFlags.Button1TripleClicked; + break; + + case Curses.Event.Button2Pressed: + mouseFlag = MouseFlags.Button2TripleClicked; + break; + + case Curses.Event.Button3Pressed: + mouseFlag = MouseFlags.Button3TripleClicked; + break; + } + buttonPressedCount = 0; + + } else if ((cev.ButtonState == Curses.Event.Button1Clicked || cev.ButtonState == Curses.Event.Button2Clicked || + cev.ButtonState == Curses.Event.Button3Clicked) && + lastMouseButtonPressed == null) { + + isButtonPressed = false; + mouseFlag = ProcessButtonClickedEvent (cev); + + } else if (((cev.ButtonState == Curses.Event.Button1Pressed || cev.ButtonState == Curses.Event.Button2Pressed || + cev.ButtonState == Curses.Event.Button3Pressed) && lastMouseButtonPressed == null) || + isButtonPressed && lastMouseButtonPressed != null && cev.ButtonState == Curses.Event.ReportMousePosition) { + + mouseFlag = MapCursesButton (cev.ButtonState); + if (cev.ButtonState != Curses.Event.ReportMousePosition) + lastMouseButtonPressed = cev.ButtonState; + isButtonPressed = true; + isReportMousePosition = false; + + if (cev.ButtonState == Curses.Event.ReportMousePosition) { + mouseFlag = MapCursesButton ((Curses.Event)lastMouseButtonPressed) | MouseFlags.ReportMousePosition; + cancelButtonClicked = true; + } + point = new Point () { + X = cev.X, + Y = cev.Y + }; + + if ((mouseFlag & MouseFlags.ReportMousePosition) == 0) { + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessContinuousButtonPressedAsync (mouseFlag)); + return false; + }); + } + + + } else if ((cev.ButtonState == Curses.Event.Button1Released || cev.ButtonState == Curses.Event.Button2Released || + cev.ButtonState == Curses.Event.Button3Released)) { + + mouseFlag = ProcessButtonReleasedEvent (cev); + isButtonPressed = false; + + } else if (cev.ButtonState == Curses.Event.ButtonWheeledUp) { + + mouseFlag = MouseFlags.WheeledUp; + + } else if (cev.ButtonState == Curses.Event.ButtonWheeledDown) { + + mouseFlag = MouseFlags.WheeledDown; + + } else if ((cev.ButtonState & (Curses.Event.ButtonWheeledUp & Curses.Event.ButtonShift)) != 0) { + + mouseFlag = MouseFlags.WheeledLeft; + + } else if ((cev.ButtonState & (Curses.Event.ButtonWheeledDown & Curses.Event.ButtonShift)) != 0) { + + mouseFlag = MouseFlags.WheeledRight; + + } else if (cev.ButtonState == Curses.Event.ReportMousePosition) { + if (cev.X != point.X || cev.Y != point.Y) { + mouseFlag = MouseFlags.ReportMousePosition; + isReportMousePosition = true; + point = new Point (); + } else { + mouseFlag = 0; + } + + } else { + mouseFlag = 0; + var eFlags = cev.ButtonState; + foreach (Enum value in Enum.GetValues (eFlags.GetType ())) { + if (eFlags.HasFlag (value)) { + mouseFlag |= MapCursesButton ((Curses.Event)value); + } + } + } + + mouseFlag = SetControlKeyStates (cev, mouseFlag); + + return new MouseEvent () { + X = cev.X, + Y = cev.Y, + //Flags = MapCursesButton (cev.ButtonState) + Flags = mouseFlag + }; + } + + MouseFlags ProcessButtonClickedEvent (Curses.MouseEvent cev) + { + lastMouseButtonPressed = cev.ButtonState; + var mf = GetButtonState (cev, true); + mouseHandler (ProcessButtonState (cev, mf)); + if (lastMouseButtonPressed != null && lastMouseButtonPressed == cev.ButtonState) { + mf = GetButtonState (cev, false); + mouseHandler (ProcessButtonState (cev, mf)); + if (lastMouseButtonPressed != null && lastMouseButtonPressed == cev.ButtonState) { + mf = MapCursesButton (cev.ButtonState); + } + } + lastMouseButtonPressed = null; + isButtonPressed = false; + return mf; + } + + MouseFlags ProcessButtonReleasedEvent (Curses.MouseEvent cev) + { + var mf = MapCursesButton (cev.ButtonState); + if (!cancelButtonClicked && lastMouseButtonPressed == null && !isReportMousePosition) { + mouseHandler (ProcessButtonState (cev, mf)); + mf = GetButtonState (cev); + } else if (isReportMousePosition) { + mf = MouseFlags.ReportMousePosition; + } + cancelButtonClicked = false; + return mf; + } + + async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) + { + while (isButtonPressed) { + await Task.Delay (100); + var me = new MouseEvent () { + X = point.X, + Y = point.Y, + Flags = mouseFlag + }; + + var view = Application.WantContinuousButtonPressedView; + if (view == null) + break; + if (isButtonPressed && lastMouseButtonPressed != null && (mouseFlag & MouseFlags.ReportMousePosition) == 0) { + Application.MainLoop.Invoke (() => mouseHandler (me)); + } + } + } + + MouseFlags GetButtonState (Curses.MouseEvent cev, bool pressed = false) + { + MouseFlags mf = default; + switch (cev.ButtonState) { + case Curses.Event.Button1Clicked: + if (pressed) + mf = MouseFlags.Button1Pressed; + else + mf = MouseFlags.Button1Released; + break; + + case Curses.Event.Button2Clicked: + if (pressed) + mf = MouseFlags.Button2Pressed; + else + mf = MouseFlags.Button2Released; + break; + + case Curses.Event.Button3Clicked: + if (pressed) + mf = MouseFlags.Button3Pressed; + else + mf = MouseFlags.Button3Released; + break; + + case Curses.Event.Button1Released: + mf = MouseFlags.Button1Clicked; + break; + + case Curses.Event.Button2Released: + mf = MouseFlags.Button2Clicked; + break; + + case Curses.Event.Button3Released: + mf = MouseFlags.Button3Clicked; + break; + + } + return mf; + } + + MouseEvent ProcessButtonState (Curses.MouseEvent cev, MouseFlags mf) + { + return new MouseEvent () { + X = cev.X, + Y = cev.Y, + Flags = mf + }; + } + + MouseFlags MapCursesButton (Curses.Event cursesButton) + { + switch (cursesButton) { + case Curses.Event.Button1Pressed: return MouseFlags.Button1Pressed; + case Curses.Event.Button1Released: return MouseFlags.Button1Released; + case Curses.Event.Button1Clicked: return MouseFlags.Button1Clicked; + case Curses.Event.Button1DoubleClicked: return MouseFlags.Button1DoubleClicked; + case Curses.Event.Button1TripleClicked: return MouseFlags.Button1TripleClicked; + case Curses.Event.Button2Pressed: return MouseFlags.Button2Pressed; + case Curses.Event.Button2Released: return MouseFlags.Button2Released; + case Curses.Event.Button2Clicked: return MouseFlags.Button2Clicked; + case Curses.Event.Button2DoubleClicked: return MouseFlags.Button2DoubleClicked; + case Curses.Event.Button2TrippleClicked: return MouseFlags.Button2TripleClicked; + case Curses.Event.Button3Pressed: return MouseFlags.Button3Pressed; + case Curses.Event.Button3Released: return MouseFlags.Button3Released; + case Curses.Event.Button3Clicked: return MouseFlags.Button3Clicked; + case Curses.Event.Button3DoubleClicked: return MouseFlags.Button3DoubleClicked; + case Curses.Event.Button3TripleClicked: return MouseFlags.Button3TripleClicked; + case Curses.Event.ButtonWheeledUp: return MouseFlags.WheeledUp; + case Curses.Event.ButtonWheeledDown: return MouseFlags.WheeledDown; + case Curses.Event.Button4Pressed: return MouseFlags.Button4Pressed; + case Curses.Event.Button4Released: return MouseFlags.Button4Released; + case Curses.Event.Button4Clicked: return MouseFlags.Button4Clicked; + case Curses.Event.Button4DoubleClicked: return MouseFlags.Button4DoubleClicked; + case Curses.Event.Button4TripleClicked: return MouseFlags.Button4TripleClicked; + case Curses.Event.ButtonShift: return MouseFlags.ButtonShift; + case Curses.Event.ButtonCtrl: return MouseFlags.ButtonCtrl; + case Curses.Event.ButtonAlt: return MouseFlags.ButtonAlt; + case Curses.Event.ReportMousePosition: return MouseFlags.ReportMousePosition; + case Curses.Event.AllEvents: return MouseFlags.AllEvents; + default: return 0; + } + } + + static MouseFlags SetControlKeyStates (Curses.MouseEvent cev, MouseFlags mouseFlag) + { + if ((cev.ButtonState & Curses.Event.ButtonCtrl) != 0 && (mouseFlag & MouseFlags.ButtonCtrl) == 0) + mouseFlag |= MouseFlags.ButtonCtrl; + + if ((cev.ButtonState & Curses.Event.ButtonShift) != 0 && (mouseFlag & MouseFlags.ButtonShift) == 0) + mouseFlag |= MouseFlags.ButtonShift; + + if ((cev.ButtonState & Curses.Event.ButtonAlt) != 0 && (mouseFlag & MouseFlags.ButtonAlt) == 0) + mouseFlag |= MouseFlags.ButtonAlt; + return mouseFlag; + } + + KeyModifiers keyModifiers; KeyModifiers MapKeyModifiers (Key key) @@ -343,18 +656,9 @@ namespace Terminal.Gui { ProcessWinChange (); } if (wch == Curses.KeyMouse) { - int wch2 = wch; - - while (wch2 == Curses.KeyMouse) { - KeyEvent key = null; - ConsoleKeyInfo [] cki = new ConsoleKeyInfo [] { - new ConsoleKeyInfo ((char)Key.Esc, 0, false, false, false), - new ConsoleKeyInfo ('[', 0, false, false, false), - new ConsoleKeyInfo ('<', 0, false, false, false) - }; - code = 0; - GetEscSeq (ref code, ref k, ref wch2, ref key, ref cki); - } + Curses.getmouse (out Curses.MouseEvent ev); + //System.Diagnostics.Debug.WriteLine ($"ButtonState: {ev.ButtonState}; ID: {ev.ID}; X: {ev.X}; Y: {ev.Y}; Z: {ev.Z}"); + mouseHandler (ToDriverMouse (ev)); return; } k = MapCursesKey (wch); @@ -390,7 +694,7 @@ namespace Terminal.Gui { k = Key.AltMask | MapCursesKey (wch); } if (code == 0) { - KeyEvent key = null; + KeyEvent key; // The ESC-number handling, debatable. // Simulates the AltMask itself by pressing Alt + Space. @@ -402,13 +706,55 @@ namespace Terminal.Gui { k = (Key)((uint)(Key.AltMask | Key.CtrlMask) + (wch2 + 64)); } else if (wch2 >= (uint)Key.D0 && wch2 <= (uint)Key.D9) { k = (Key)((uint)Key.AltMask + (uint)Key.D0 + (wch2 - (uint)Key.D0)); - } else if (wch2 == Curses.KeyCSI) { - ConsoleKeyInfo [] cki = new ConsoleKeyInfo [] { - new ConsoleKeyInfo ((char)Key.Esc, 0, false, false, false), - new ConsoleKeyInfo ('[', 0, false, false, false) - }; - GetEscSeq (ref code, ref k, ref wch2, ref key, ref cki); - return; + } else if (wch2 == 27) { + k = (Key)wch2; + } else if (wch2 == Curses.KEY_CODE_SEQ) { + int [] c = null; + while (code == 0) { + code = Curses.get_wch (out wch2); + if (wch2 > 0) { + Array.Resize (ref c, c == null ? 1 : c.Length + 1); + c [c.Length - 1] = wch2; + } + } + if (c [0] == 49 && c [1] == 59 && c [2] == 55 && c [3] >= 80 && c [3] <= 83) { // Ctrl+Alt+(F1 - F4) + wch2 = c [3] + 185; + k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 49 && c [2] == 59 && c [3] == 55 && c [4] == 126 && c [1] >= 53 && c [1] <= 57) { // Ctrl+Alt+(F5 - F8) + wch2 = c [1] == 53 ? c [1] + 216 : c [1] + 215; + k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 50 && c [2] == 59 && c [3] == 55 && c [4] == 126 && c [1] >= 48 && c [1] <= 52) { // Ctrl+Alt+(F9 - F12) + wch2 = c [1] < 51 ? c [1] + 225 : c [1] + 224; + k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 49 && c [1] == 59 && c [2] == 56 && c [3] >= 80 && c [3] <= 83) { // Ctrl+Shift+Alt+(F1 - F4) + wch2 = c [3] + 185; + k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 49 && c [2] == 59 && c [3] == 56 && c [4] == 126 && c [1] >= 53 && c [1] <= 57) { // Ctrl+Shift+Alt+(F5 - F8) + wch2 = c [1] == 53 ? c [1] + 216 : c [1] + 215; + k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 50 && c [2] == 59 && c [3] == 56 && c [4] == 126 && c [1] >= 48 && c [1] <= 52) { // Ctrl+Shift+Alt+(F9 - F12) + wch2 = c [1] < 51 ? c [1] + 225 : c [1] + 224; + k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 49 && c [1] == 59 && c [2] == 52 && c [3] == 83) { // Shift+Alt+(F4) + wch2 = 268; + k = Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 49 && c [2] == 59 && c [3] == 52 && c [4] == 126 && c [1] >= 53 && c [1] <= 57) { // Shift+Alt+(F5 - F8) + wch2 = c [1] < 55 ? c [1] + 216 : c [1] + 215; + k = Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 50 && c [2] == 59 && c [3] == 52 && c [4] == 126 && c [1] >= 48 && c [1] <= 52) { // Shift+Alt+(F9 - F12) + wch2 = c [1] < 51 ? c [1] + 225 : c [1] + 224; + k = Key.ShiftMask | Key.AltMask | MapCursesKey (wch2); + } else if (c [0] == 54 && c [1] == 59 && c [2] == 56 && c [3] == 126) { // Shift+Ctrl+Alt+KeyNPage + k = Key.ShiftMask | Key.CtrlMask | Key.AltMask | Key.PageDown; + } else if (c [0] == 53 && c [1] == 59 && c [2] == 56 && c [3] == 126) { // Shift+Ctrl+Alt+KeyPPage + k = Key.ShiftMask | Key.CtrlMask | Key.AltMask | Key.PageUp; + } else if (c [0] == 49 && c [1] == 59 && c [2] == 56 && c [3] == 72) { // Shift+Ctrl+Alt+KeyHome + k = Key.ShiftMask | Key.CtrlMask | Key.AltMask | Key.Home; + } else if (c [0] == 49 && c [1] == 59 && c [2] == 56 && c [3] == 70) { // Shift+Ctrl+Alt+KeyEnd + k = Key.ShiftMask | Key.CtrlMask | Key.AltMask | Key.End; + } else { + k = MapCursesKey (wch2); + } } else { // Unfortunately there are no way to differentiate Ctrl+Alt+alfa and Ctrl+Shift+Alt+alfa. if (((Key)wch2 & Key.CtrlMask) != 0) { @@ -463,52 +809,6 @@ namespace Terminal.Gui { //} } - void GetEscSeq (ref int code, ref Key k, ref int wch2, ref KeyEvent key, ref ConsoleKeyInfo [] cki) - { - ConsoleKey ck = 0; - ConsoleModifiers mod = 0; - while (code == 0) { - code = Curses.get_wch (out wch2); - var consoleKeyInfo = new ConsoleKeyInfo ((char)wch2, 0, false, false, false); - if (wch2 == 0 || wch2 == 27 || wch2 == Curses.KeyMouse) { - EscSeqUtils.DecodeEscSeq (null, ref consoleKeyInfo, ref ck, cki, ref mod, out _, out _, out _, out _, out bool isKeyMouse, out List mouseFlags, out Point pos, out _, ProcessContinuousButtonPressed); - if (isKeyMouse) { - foreach (var mf in mouseFlags) { - ProcessMouseEvent (mf, pos); - } - cki = null; - if (wch2 == 27) { - cki = EscSeqUtils.ResizeArray (new ConsoleKeyInfo ((char)Key.Esc, 0, - false, false, false), cki); - } - } else { - k = ConsoleKeyMapping.MapConsoleKeyToKey (consoleKeyInfo.Key, out _); - k = ConsoleKeyMapping.MapKeyModifiers (consoleKeyInfo, k); - key = new KeyEvent (k, MapKeyModifiers (k)); - keyDownHandler (key); - keyHandler (key); - } - } else { - cki = EscSeqUtils.ResizeArray (consoleKeyInfo, cki); - } - } - } - - void ProcessMouseEvent (MouseFlags mouseFlag, Point pos) - { - var me = new MouseEvent () { - Flags = mouseFlag, - X = pos.X, - Y = pos.Y - }; - mouseHandler (me); - } - - void ProcessContinuousButtonPressed (MouseFlags mouseFlag, Point pos) - { - ProcessMouseEvent (mouseFlag, pos); - } - Action keyHandler; Action keyDownHandler; Action keyUpHandler; @@ -535,12 +835,17 @@ namespace Terminal.Gui { }; } + Curses.Event oldMouseEvents, reportableMouseEvents; public override void Init (Action terminalResized) { if (window != null) return; try { + //Set cursor key to application. + //Console.Out.Write ("\x1b[?1h"); + //Console.Out.Flush (); + window = Curses.initscr (); Curses.set_escdelay (10); } catch (Exception e) { @@ -587,8 +892,10 @@ namespace Terminal.Gui { Curses.noecho (); Curses.Window.Standard.keypad (true); + reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out oldMouseEvents); TerminalResized = terminalResized; - StartReportingMouseMoves (); + if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) + StartReportingMouseMoves (); CurrentAttribute = MakeColor (Color.White, Color.Black); @@ -637,7 +944,8 @@ namespace Terminal.Gui { public override void ResizeScreen () { Clip = new Rect (0, 0, Cols, Rows); - Curses.refresh (); + Console.Out.Write ("\x1b[3J"); + Console.Out.Flush (); } public override void UpdateOffScreen () @@ -757,21 +1065,25 @@ namespace Terminal.Gui { public override void Suspend () { - StopReportingMouseMoves (); + if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) + StopReportingMouseMoves (); Platform.Suspend (); Curses.Window.Standard.redrawwin (); Curses.refresh (); - StartReportingMouseMoves (); + if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) + StartReportingMouseMoves (); } public override void StartReportingMouseMoves () { - Console.Out.Write (EscSeqUtils.EnableMouseEvents); + Console.Out.Write ("\x1b[?1003h"); + Console.Out.Flush (); } public override void StopReportingMouseMoves () { - Console.Out.Write (EscSeqUtils.DisableMouseEvents); + Console.Out.Write ("\x1b[?1003l"); + Console.Out.Flush (); } //int lastMouseInterval; @@ -814,6 +1126,7 @@ namespace Terminal.Gui { if (visibility != CursorVisibility.Invisible) { Console.Out.Write ("\x1b[{0} q", ((int)visibility >> 24) & 0xFF); + Console.Out.Flush (); } currentCursorVisibility = visibility; @@ -878,8 +1191,8 @@ namespace Terminal.Gui { background = default; int back = -1; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains ((value >> 12) & 0xffff)) { hasColor = true; back = (value >> 12) & 0xffff; @@ -972,7 +1285,6 @@ namespace Terminal.Gui { bool CheckSupport () { -#pragma warning disable RCS1075 // Avoid empty catch clause that catches System.Exception. try { var (exitCode, result) = ClipboardProcessRunner.Bash ("which xclip", waitForOutput: true); if (exitCode == 0 && result.FileExists ()) { @@ -982,7 +1294,6 @@ namespace Terminal.Gui { } catch (Exception) { // Permissions issue. } -#pragma warning restore RCS1075 // Avoid empty catch clause that catches System.Exception. return false; } diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs index df5359542..977913fa2 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs @@ -1,6 +1,30 @@ // // mainloop.cs: Simple managed mainloop implementation. // +// Authors: +// Miguel de Icaza (miguel.de.icaza@gmail.com) +// +// Copyright (C) 2011 Novell (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// using System; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -28,7 +52,7 @@ namespace Terminal.Gui { } /// - /// Condition on which to wake up from file descriptor activity. These match the Linux/BSD poll definitions. + /// Condition on which to wake up from file descriptor activity. These match the Linux/BSD poll definitions. /// [Flags] public enum Condition : short { @@ -103,10 +127,10 @@ namespace Terminal.Gui { } /// - /// Removes an active watch from the mainloop. + /// Removes an active watch from the mainloop. /// /// - /// The token parameter is the value returned from AddWatch + /// The token parameter is the value returned from AddWatch /// public void RemoveWatch (object token) { diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs index cde433744..b1b60c3a5 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs @@ -6,7 +6,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -21,6 +21,8 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Threading; + + namespace Unix.Terminal { /// /// Represents a dynamically loaded unmanaged library in a (partially) platform independent manner. @@ -43,7 +45,7 @@ namespace Unix.Terminal { static bool IsNetCore; public static bool IsMacOSPlatform => IsMacOS; - + [DllImport ("libc")] static extern int uname (IntPtr buf); @@ -103,11 +105,11 @@ namespace Unix.Terminal { // public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath) { - if (isFullPath) { + if (isFullPath){ this.libraryPath = FirstValidLibraryPath (libraryPathAlternatives); this.handle = PlatformSpecificLoadLibrary (this.libraryPath); } else { - foreach (var lib in libraryPathAlternatives) { + foreach (var lib in libraryPathAlternatives){ this.handle = PlatformSpecificLoadLibrary (lib); if (this.handle != IntPtr.Zero) break; @@ -162,13 +164,13 @@ namespace Unix.Terminal { } public T GetNativeMethodDelegate (string methodName) - where T : class + where T : class { var ptr = LoadSymbol (methodName); if (ptr == IntPtr.Zero) { throw new MissingMethodException (string.Format ("The native method \"{0}\" does not exist", methodName)); } - return Marshal.GetDelegateForFunctionPointer (ptr); // non-generic version is obsolete + return Marshal.GetDelegateForFunctionPointer(ptr); // non-generic version is obsolete } /// @@ -207,11 +209,12 @@ namespace Unix.Terminal { } } throw new FileNotFoundException ( - String.Format ("Error loading native library. Not found in any of the possible locations: {0}", + String.Format ("Error loading native library. Not found in any of the possible locations: {0}", string.Join (",", libraryPathAlternatives))); } - static class Windows { + static class Windows + { [DllImport ("kernel32.dll")] internal static extern IntPtr LoadLibrary (string filename); @@ -219,7 +222,8 @@ namespace Unix.Terminal { internal static extern IntPtr GetProcAddress (IntPtr hModule, string procName); } - static class Linux { + static class Linux + { [DllImport ("libdl.so")] internal static extern IntPtr dlopen (string filename, int flags); @@ -227,7 +231,8 @@ namespace Unix.Terminal { internal static extern IntPtr dlsym (IntPtr handle, string symbol); } - static class MacOSX { + static class MacOSX + { [DllImport ("libSystem.dylib")] internal static extern IntPtr dlopen (string filename, int flags); @@ -242,7 +247,8 @@ namespace Unix.Terminal { /// dlopen and dlsym from the current process as on Linux /// Mono sure is linked against these symbols. /// - static class Mono { + static class Mono + { [DllImport ("__Internal")] internal static extern IntPtr dlopen (string filename, int flags); @@ -255,12 +261,13 @@ namespace Unix.Terminal { /// dlopen and dlsym from the "libcoreclr.so", /// to avoid the dependency on libc-dev Linux. /// - static class CoreCLR { + static class CoreCLR + { #if NET6_0 // Custom resolver to support true single-file apps // (those which run directly from bundle; in-memory). - // -1 on Unix means self-referencing binary (libcoreclr.so) - // 0 means fallback to CoreCLR's internal resolution + // -1 on Unix means self-referencing binary (libcoreclr.so) + // 0 means fallback to CoreCLR's internal resolution // Note: meaning of -1 stay the same even for non-single-file form factors. static CoreCLR() => NativeLibrary.SetDllImportResolver(typeof(CoreCLR).Assembly, (string libraryName, Assembly assembly, DllImportSearchPath? searchPath) => diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs index 42612b3ae..4195344eb 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs @@ -145,6 +145,11 @@ namespace Unix.Terminal { if (l == 1 || l != lines || c != cols) { lines = l; cols = c; + //if (l <= 0 || c <= 0) { + // Console.Out.Write ($"\x1b[8;50;{c}t"); + // Console.Out.Flush (); + // return false; + //} return true; } return false; diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs index fb9bc326b..b9a63834a 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs @@ -53,6 +53,7 @@ namespace Unix.Terminal { public const int COLOR_WHITE = unchecked((int)0x7); public const int COLOR_GRAY = unchecked((int)0x8); public const int KEY_CODE_YES = unchecked((int)0x100); + public const int KEY_CODE_SEQ = unchecked((int)0x5b); public const int ERR = unchecked((int)0xffffffff); public const int TIOCGWINSZ = unchecked((int)0x5413); public const int TIOCGWINSZ_MAC = unchecked((int)0x40087468); @@ -68,7 +69,7 @@ namespace Unix.Terminal { Button2Released = unchecked((int)0x20), Button2Clicked = unchecked((int)0x80), Button2DoubleClicked = unchecked((int)0x100), - Button2TripleClicked = unchecked((int)0x200), + Button2TrippleClicked = unchecked((int)0x200), Button3Pressed = unchecked((int)0x800), Button3Released = unchecked((int)0x400), Button3Clicked = unchecked((int)0x1000), @@ -105,7 +106,6 @@ namespace Unix.Terminal { public const int KeyPPage = unchecked((int)0x153); public const int KeyHome = unchecked((int)0x106); public const int KeyMouse = unchecked((int)0x199); - public const int KeyCSI = unchecked((int)0x5b); public const int KeyEnd = unchecked((int)0x168); public const int KeyDeleteChar = unchecked((int)0x14a); public const int KeyInsertChar = unchecked((int)0x14b); diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs index 017050ef0..e78baa96a 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs @@ -1,10 +1,15 @@ // // FakeConsole.cs: A fake .NET Windows Console API implementation for unit tests. // +// Authors: +// Charlie Kindel (github.com/tig) +// using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; +using System.Threading.Tasks; namespace Terminal.Gui { @@ -17,23 +22,23 @@ namespace Terminal.Gui { // // Summary: - // Gets or sets the width of the console window. + // Gets or sets the width of the console window. // // Returns: - // The width of the console window measured in columns. + // The width of the console window measured in columns. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight - // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight - // property plus the value of the System.Console.WindowTop property is greater than - // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth - // property or the value of the System.Console.WindowHeight property is greater - // than the largest possible window width or height for the current screen resolution - // and console font. + // T:System.ArgumentOutOfRangeException: + // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight + // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight + // property plus the value of the System.Console.WindowTop property is greater than + // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth + // property or the value of the System.Console.WindowHeight property is greater + // than the largest possible window width or height for the current screen resolution + // and console font. // - // T:System.IO.IOException: - // Error reading or writing information. + // T:System.IO.IOException: + // Error reading or writing information. #pragma warning disable RCS1138 // Add summary to documentation comment. /// @@ -52,113 +57,113 @@ namespace Terminal.Gui { public static int WindowWidth { get; set; } = WIDTH; // // Summary: - // Gets a value that indicates whether output has been redirected from the standard - // output stream. + // Gets a value that indicates whether output has been redirected from the standard + // output stream. // // Returns: - // true if output is redirected; otherwise, false. + // true if output is redirected; otherwise, false. /// /// /// public static bool IsOutputRedirected { get; } // // Summary: - // Gets a value that indicates whether the error output stream has been redirected - // from the standard error stream. + // Gets a value that indicates whether the error output stream has been redirected + // from the standard error stream. // // Returns: - // true if error output is redirected; otherwise, false. + // true if error output is redirected; otherwise, false. /// /// /// public static bool IsErrorRedirected { get; } // // Summary: - // Gets the standard input stream. + // Gets the standard input stream. // // Returns: - // A System.IO.TextReader that represents the standard input stream. + // A System.IO.TextReader that represents the standard input stream. /// /// /// public static TextReader In { get; } // // Summary: - // Gets the standard output stream. + // Gets the standard output stream. // // Returns: - // A System.IO.TextWriter that represents the standard output stream. + // A System.IO.TextWriter that represents the standard output stream. /// /// /// public static TextWriter Out { get; } // // Summary: - // Gets the standard error output stream. + // Gets the standard error output stream. // // Returns: - // A System.IO.TextWriter that represents the standard error output stream. + // A System.IO.TextWriter that represents the standard error output stream. /// /// /// public static TextWriter Error { get; } // // Summary: - // Gets or sets the encoding the console uses to read input. + // Gets or sets the encoding the console uses to read input. // // Returns: - // The encoding used to read console input. + // The encoding used to read console input. // // Exceptions: - // T:System.ArgumentNullException: - // The property value in a set operation is null. + // T:System.ArgumentNullException: + // The property value in a set operation is null. // - // T:System.IO.IOException: - // An error occurred during the execution of this operation. + // T:System.IO.IOException: + // An error occurred during the execution of this operation. // - // T:System.Security.SecurityException: - // Your application does not have permission to perform this operation. + // T:System.Security.SecurityException: + // Your application does not have permission to perform this operation. /// /// /// public static Encoding InputEncoding { get; set; } // // Summary: - // Gets or sets the encoding the console uses to write output. + // Gets or sets the encoding the console uses to write output. // // Returns: - // The encoding used to write console output. + // The encoding used to write console output. // // Exceptions: - // T:System.ArgumentNullException: - // The property value in a set operation is null. + // T:System.ArgumentNullException: + // The property value in a set operation is null. // - // T:System.IO.IOException: - // An error occurred during the execution of this operation. + // T:System.IO.IOException: + // An error occurred during the execution of this operation. // - // T:System.Security.SecurityException: - // Your application does not have permission to perform this operation. + // T:System.Security.SecurityException: + // Your application does not have permission to perform this operation. /// /// /// public static Encoding OutputEncoding { get; set; } // // Summary: - // Gets or sets the background color of the console. + // Gets or sets the background color of the console. // // Returns: - // A value that specifies the background color of the console; that is, the color - // that appears behind each character. The default is black. + // A value that specifies the background color of the console; that is, the color + // that appears behind each character. The default is black. // // Exceptions: - // T:System.ArgumentException: - // The color specified in a set operation is not a valid member of System.ConsoleColor. + // T:System.ArgumentException: + // The color specified in a set operation is not a valid member of System.ConsoleColor. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. static ConsoleColor _defaultBackgroundColor = ConsoleColor.Black; @@ -169,21 +174,21 @@ namespace Terminal.Gui { // // Summary: - // Gets or sets the foreground color of the console. + // Gets or sets the foreground color of the console. // // Returns: - // A System.ConsoleColor that specifies the foreground color of the console; that - // is, the color of each character that is displayed. The default is gray. + // A System.ConsoleColor that specifies the foreground color of the console; that + // is, the color of each character that is displayed. The default is gray. // // Exceptions: - // T:System.ArgumentException: - // The color specified in a set operation is not a valid member of System.ConsoleColor. + // T:System.ArgumentException: + // The color specified in a set operation is not a valid member of System.ConsoleColor. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. static ConsoleColor _defaultForegroundColor = ConsoleColor.Gray; @@ -193,299 +198,299 @@ namespace Terminal.Gui { public static ConsoleColor ForegroundColor { get; set; } = _defaultForegroundColor; // // Summary: - // Gets or sets the height of the buffer area. + // Gets or sets the height of the buffer area. // // Returns: - // The current height, in rows, of the buffer area. + // The current height, in rows, of the buffer area. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value in a set operation is less than or equal to zero.-or- The value in - // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value - // in a set operation is less than System.Console.WindowTop + System.Console.WindowHeight. + // T:System.ArgumentOutOfRangeException: + // The value in a set operation is less than or equal to zero.-or- The value in + // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value + // in a set operation is less than System.Console.WindowTop + System.Console.WindowHeight. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static int BufferHeight { get; set; } = HEIGHT; // // Summary: - // Gets or sets the width of the buffer area. + // Gets or sets the width of the buffer area. // // Returns: - // The current width, in columns, of the buffer area. + // The current width, in columns, of the buffer area. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value in a set operation is less than or equal to zero.-or- The value in - // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value - // in a set operation is less than System.Console.WindowLeft + System.Console.WindowWidth. + // T:System.ArgumentOutOfRangeException: + // The value in a set operation is less than or equal to zero.-or- The value in + // a set operation is greater than or equal to System.Int16.MaxValue.-or- The value + // in a set operation is less than System.Console.WindowLeft + System.Console.WindowWidth. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static int BufferWidth { get; set; } = WIDTH; // // Summary: - // Gets or sets the height of the console window area. + // Gets or sets the height of the console window area. // // Returns: - // The height of the console window measured in rows. + // The height of the console window measured in rows. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight - // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight - // property plus the value of the System.Console.WindowTop property is greater than - // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth - // property or the value of the System.Console.WindowHeight property is greater - // than the largest possible window width or height for the current screen resolution - // and console font. + // T:System.ArgumentOutOfRangeException: + // The value of the System.Console.WindowWidth property or the value of the System.Console.WindowHeight + // property is less than or equal to 0.-or-The value of the System.Console.WindowHeight + // property plus the value of the System.Console.WindowTop property is greater than + // or equal to System.Int16.MaxValue.-or-The value of the System.Console.WindowWidth + // property or the value of the System.Console.WindowHeight property is greater + // than the largest possible window width or height for the current screen resolution + // and console font. // - // T:System.IO.IOException: - // Error reading or writing information. + // T:System.IO.IOException: + // Error reading or writing information. /// /// /// public static int WindowHeight { get; set; } = HEIGHT; // // Summary: - // Gets or sets a value indicating whether the combination of the System.ConsoleModifiers.Control - // modifier key and System.ConsoleKey.C console key (Ctrl+C) is treated as ordinary - // input or as an interruption that is handled by the operating system. + // Gets or sets a value indicating whether the combination of the System.ConsoleModifiers.Control + // modifier key and System.ConsoleKey.C console key (Ctrl+C) is treated as ordinary + // input or as an interruption that is handled by the operating system. // // Returns: - // true if Ctrl+C is treated as ordinary input; otherwise, false. + // true if Ctrl+C is treated as ordinary input; otherwise, false. // // Exceptions: - // T:System.IO.IOException: - // Unable to get or set the input mode of the console input buffer. + // T:System.IO.IOException: + // Unable to get or set the input mode of the console input buffer. /// /// /// public static bool TreatControlCAsInput { get; set; } // // Summary: - // Gets the largest possible number of console window columns, based on the current - // font and screen resolution. + // Gets the largest possible number of console window columns, based on the current + // font and screen resolution. // // Returns: - // The width of the largest possible console window measured in columns. + // The width of the largest possible console window measured in columns. /// /// /// public static int LargestWindowWidth { get; } // // Summary: - // Gets the largest possible number of console window rows, based on the current - // font and screen resolution. + // Gets the largest possible number of console window rows, based on the current + // font and screen resolution. // // Returns: - // The height of the largest possible console window measured in rows. + // The height of the largest possible console window measured in rows. /// /// /// public static int LargestWindowHeight { get; } // // Summary: - // Gets or sets the leftmost position of the console window area relative to the - // screen buffer. + // Gets or sets the leftmost position of the console window area relative to the + // screen buffer. // // Returns: - // The leftmost console window position measured in columns. + // The leftmost console window position measured in columns. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // In a set operation, the value to be assigned is less than zero.-or-As a result - // of the assignment, System.Console.WindowLeft plus System.Console.WindowWidth - // would exceed System.Console.BufferWidth. + // T:System.ArgumentOutOfRangeException: + // In a set operation, the value to be assigned is less than zero.-or-As a result + // of the assignment, System.Console.WindowLeft plus System.Console.WindowWidth + // would exceed System.Console.BufferWidth. // - // T:System.IO.IOException: - // Error reading or writing information. + // T:System.IO.IOException: + // Error reading or writing information. /// /// /// public static int WindowLeft { get; set; } // // Summary: - // Gets or sets the top position of the console window area relative to the screen - // buffer. + // Gets or sets the top position of the console window area relative to the screen + // buffer. // // Returns: - // The uppermost console window position measured in rows. + // The uppermost console window position measured in rows. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // In a set operation, the value to be assigned is less than zero.-or-As a result - // of the assignment, System.Console.WindowTop plus System.Console.WindowHeight - // would exceed System.Console.BufferHeight. + // T:System.ArgumentOutOfRangeException: + // In a set operation, the value to be assigned is less than zero.-or-As a result + // of the assignment, System.Console.WindowTop plus System.Console.WindowHeight + // would exceed System.Console.BufferHeight. // - // T:System.IO.IOException: - // Error reading or writing information. + // T:System.IO.IOException: + // Error reading or writing information. /// /// /// public static int WindowTop { get; set; } // // Summary: - // Gets or sets the column position of the cursor within the buffer area. + // Gets or sets the column position of the cursor within the buffer area. // // Returns: - // The current position, in columns, of the cursor. + // The current position, in columns, of the cursor. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value in a set operation is less than zero.-or- The value in a set operation - // is greater than or equal to System.Console.BufferWidth. + // T:System.ArgumentOutOfRangeException: + // The value in a set operation is less than zero.-or- The value in a set operation + // is greater than or equal to System.Console.BufferWidth. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static int CursorLeft { get; set; } // // Summary: - // Gets or sets the row position of the cursor within the buffer area. + // Gets or sets the row position of the cursor within the buffer area. // // Returns: - // The current position, in rows, of the cursor. + // The current position, in rows, of the cursor. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value in a set operation is less than zero.-or- The value in a set operation - // is greater than or equal to System.Console.BufferHeight. + // T:System.ArgumentOutOfRangeException: + // The value in a set operation is less than zero.-or- The value in a set operation + // is greater than or equal to System.Console.BufferHeight. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static int CursorTop { get; set; } // // Summary: - // Gets or sets the height of the cursor within a character cell. + // Gets or sets the height of the cursor within a character cell. // // Returns: - // The size of the cursor expressed as a percentage of the height of a character - // cell. The property value ranges from 1 to 100. + // The size of the cursor expressed as a percentage of the height of a character + // cell. The property value ranges from 1 to 100. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // The value specified in a set operation is less than 1 or greater than 100. + // T:System.ArgumentOutOfRangeException: + // The value specified in a set operation is less than 1 or greater than 100. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static int CursorSize { get; set; } // // Summary: - // Gets or sets a value indicating whether the cursor is visible. + // Gets or sets a value indicating whether the cursor is visible. // // Returns: - // true if the cursor is visible; otherwise, false. + // true if the cursor is visible; otherwise, false. // // Exceptions: - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static bool CursorVisible { get; set; } // // Summary: - // Gets or sets the title to display in the console title bar. + // Gets or sets the title to display in the console title bar. // // Returns: - // The string to be displayed in the title bar of the console. The maximum length - // of the title string is 24500 characters. + // The string to be displayed in the title bar of the console. The maximum length + // of the title string is 24500 characters. // // Exceptions: - // T:System.InvalidOperationException: - // In a get operation, the retrieved title is longer than 24500 characters. + // T:System.InvalidOperationException: + // In a get operation, the retrieved title is longer than 24500 characters. // - // T:System.ArgumentOutOfRangeException: - // In a set operation, the specified title is longer than 24500 characters. + // T:System.ArgumentOutOfRangeException: + // In a set operation, the specified title is longer than 24500 characters. // - // T:System.ArgumentNullException: - // In a set operation, the specified title is null. + // T:System.ArgumentNullException: + // In a set operation, the specified title is null. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// public static string Title { get; set; } // // Summary: - // Gets a value indicating whether a key press is available in the input stream. + // Gets a value indicating whether a key press is available in the input stream. // // Returns: - // true if a key press is available; otherwise, false. + // true if a key press is available; otherwise, false. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.InvalidOperationException: - // Standard input is redirected to a file instead of the keyboard. + // T:System.InvalidOperationException: + // Standard input is redirected to a file instead of the keyboard. /// /// /// public static bool KeyAvailable { get; } // // Summary: - // Gets a value indicating whether the NUM LOCK keyboard toggle is turned on or - // turned off. + // Gets a value indicating whether the NUM LOCK keyboard toggle is turned on or + // turned off. // // Returns: - // true if NUM LOCK is turned on; false if NUM LOCK is turned off. + // true if NUM LOCK is turned on; false if NUM LOCK is turned off. /// /// /// public static bool NumberLock { get; } // // Summary: - // Gets a value indicating whether the CAPS LOCK keyboard toggle is turned on or - // turned off. + // Gets a value indicating whether the CAPS LOCK keyboard toggle is turned on or + // turned off. // // Returns: - // true if CAPS LOCK is turned on; false if CAPS LOCK is turned off. + // true if CAPS LOCK is turned on; false if CAPS LOCK is turned off. /// /// /// public static bool CapsLock { get; } // // Summary: - // Gets a value that indicates whether input has been redirected from the standard - // input stream. + // Gets a value that indicates whether input has been redirected from the standard + // input stream. // // Returns: - // true if input is redirected; otherwise, false. + // true if input is redirected; otherwise, false. /// /// /// @@ -493,12 +498,12 @@ namespace Terminal.Gui { // // Summary: - // Plays the sound of a beep through the console speaker. + // Plays the sound of a beep through the console speaker. // // Exceptions: - // T:System.Security.HostProtectionException: - // This method was executed on a server, such as SQL Server, that does not permit - // access to a user interface. + // T:System.Security.HostProtectionException: + // This method was executed on a server, such as SQL Server, that does not permit + // access to a user interface. /// /// /// @@ -508,24 +513,24 @@ namespace Terminal.Gui { } // // Summary: - // Plays the sound of a beep of a specified frequency and duration through the console - // speaker. + // Plays the sound of a beep of a specified frequency and duration through the console + // speaker. // // Parameters: - // frequency: - // The frequency of the beep, ranging from 37 to 32767 hertz. + // frequency: + // The frequency of the beep, ranging from 37 to 32767 hertz. // - // duration: - // The duration of the beep measured in milliseconds. + // duration: + // The duration of the beep measured in milliseconds. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // frequency is less than 37 or more than 32767 hertz.-or- duration is less than - // or equal to zero. + // T:System.ArgumentOutOfRangeException: + // frequency is less than 37 or more than 32767 hertz.-or- duration is less than + // or equal to zero. // - // T:System.Security.HostProtectionException: - // This method was executed on a server, such as SQL Server, that does not permit - // access to the console. + // T:System.Security.HostProtectionException: + // This method was executed on a server, such as SQL Server, that does not permit + // access to the console. /// /// /// @@ -535,11 +540,11 @@ namespace Terminal.Gui { } // // Summary: - // Clears the console buffer and corresponding console window of display information. + // Clears the console buffer and corresponding console window of display information. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. static char [,] _buffer = new char [WindowWidth, WindowHeight]; @@ -554,41 +559,41 @@ namespace Terminal.Gui { // // Summary: - // Copies a specified source area of the screen buffer to a specified destination - // area. + // Copies a specified source area of the screen buffer to a specified destination + // area. // // Parameters: - // sourceLeft: - // The leftmost column of the source area. + // sourceLeft: + // The leftmost column of the source area. // - // sourceTop: - // The topmost row of the source area. + // sourceTop: + // The topmost row of the source area. // - // sourceWidth: - // The number of columns in the source area. + // sourceWidth: + // The number of columns in the source area. // - // sourceHeight: - // The number of rows in the source area. + // sourceHeight: + // The number of rows in the source area. // - // targetLeft: - // The leftmost column of the destination area. + // targetLeft: + // The leftmost column of the destination area. // - // targetTop: - // The topmost row of the destination area. + // targetTop: + // The topmost row of the destination area. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft - // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop - // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight - // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth - // is greater than or equal to System.Console.BufferWidth. + // T:System.ArgumentOutOfRangeException: + // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft + // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop + // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight + // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth + // is greater than or equal to System.Console.BufferWidth. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -599,54 +604,54 @@ namespace Terminal.Gui { // // Summary: - // Copies a specified source area of the screen buffer to a specified destination - // area. + // Copies a specified source area of the screen buffer to a specified destination + // area. // // Parameters: - // sourceLeft: - // The leftmost column of the source area. + // sourceLeft: + // The leftmost column of the source area. // - // sourceTop: - // The topmost row of the source area. + // sourceTop: + // The topmost row of the source area. // - // sourceWidth: - // The number of columns in the source area. + // sourceWidth: + // The number of columns in the source area. // - // sourceHeight: - // The number of rows in the source area. + // sourceHeight: + // The number of rows in the source area. // - // targetLeft: - // The leftmost column of the destination area. + // targetLeft: + // The leftmost column of the destination area. // - // targetTop: - // The topmost row of the destination area. + // targetTop: + // The topmost row of the destination area. // - // sourceChar: - // The character used to fill the source area. + // sourceChar: + // The character used to fill the source area. // - // sourceForeColor: - // The foreground color used to fill the source area. + // sourceForeColor: + // The foreground color used to fill the source area. // - // sourceBackColor: - // The background color used to fill the source area. + // sourceBackColor: + // The background color used to fill the source area. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft - // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop - // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight - // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth - // is greater than or equal to System.Console.BufferWidth. + // T:System.ArgumentOutOfRangeException: + // One or more of the parameters is less than zero.-or- sourceLeft or targetLeft + // is greater than or equal to System.Console.BufferWidth.-or- sourceTop or targetTop + // is greater than or equal to System.Console.BufferHeight.-or- sourceTop + sourceHeight + // is greater than or equal to System.Console.BufferHeight.-or- sourceLeft + sourceWidth + // is greater than or equal to System.Console.BufferWidth. // - // T:System.ArgumentException: - // One or both of the color parameters is not a member of the System.ConsoleColor - // enumeration. + // T:System.ArgumentException: + // One or both of the color parameters is not a member of the System.ConsoleColor + // enumeration. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -658,10 +663,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard error stream. + // Acquires the standard error stream. // // Returns: - // The standard error stream. + // The standard error stream. /// /// /// @@ -672,18 +677,18 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard error stream, which is set to a specified buffer size. + // Acquires the standard error stream, which is set to a specified buffer size. // // Parameters: - // bufferSize: - // The internal stream buffer size. + // bufferSize: + // The internal stream buffer size. // // Returns: - // The standard error stream. + // The standard error stream. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // bufferSize is less than or equal to zero. + // T:System.ArgumentOutOfRangeException: + // bufferSize is less than or equal to zero. /// /// /// @@ -694,18 +699,18 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard input stream, which is set to a specified buffer size. + // Acquires the standard input stream, which is set to a specified buffer size. // // Parameters: - // bufferSize: - // The internal stream buffer size. + // bufferSize: + // The internal stream buffer size. // // Returns: - // The standard input stream. + // The standard input stream. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // bufferSize is less than or equal to zero. + // T:System.ArgumentOutOfRangeException: + // bufferSize is less than or equal to zero. /// /// /// @@ -716,10 +721,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard input stream. + // Acquires the standard input stream. // // Returns: - // The standard input stream. + // The standard input stream. /// /// /// @@ -730,18 +735,18 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard output stream, which is set to a specified buffer size. + // Acquires the standard output stream, which is set to a specified buffer size. // // Parameters: - // bufferSize: - // The internal stream buffer size. + // bufferSize: + // The internal stream buffer size. // // Returns: - // The standard output stream. + // The standard output stream. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // bufferSize is less than or equal to zero. + // T:System.ArgumentOutOfRangeException: + // bufferSize is less than or equal to zero. /// /// /// @@ -752,10 +757,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard output stream. + // Acquires the standard output stream. // // Returns: - // The standard output stream. + // The standard output stream. /// /// /// @@ -766,15 +771,15 @@ namespace Terminal.Gui { // // Summary: - // Reads the next character from the standard input stream. + // Reads the next character from the standard input stream. // // Returns: - // The next character from the input stream, or negative one (-1) if there are currently - // no more characters to be read. + // The next character from the input stream, or negative one (-1) if there are currently + // no more characters to be read. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -785,25 +790,25 @@ namespace Terminal.Gui { // // Summary: - // Obtains the next character or function key pressed by the user. The pressed key - // is optionally displayed in the console window. + // Obtains the next character or function key pressed by the user. The pressed key + // is optionally displayed in the console window. // // Parameters: - // intercept: - // Determines whether to display the pressed key in the console window. true to - // not display the pressed key; otherwise, false. + // intercept: + // Determines whether to display the pressed key in the console window. true to + // not display the pressed key; otherwise, false. // // Returns: - // An object that describes the System.ConsoleKey constant and Unicode character, - // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo - // object also describes, in a bitwise combination of System.ConsoleModifiers values, - // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously - // with the console key. + // An object that describes the System.ConsoleKey constant and Unicode character, + // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo + // object also describes, in a bitwise combination of System.ConsoleModifiers values, + // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously + // with the console key. // // Exceptions: - // T:System.InvalidOperationException: - // The System.Console.In property is redirected from some stream other than the - // console. + // T:System.InvalidOperationException: + // The System.Console.In property is redirected from some stream other than the + // console. //[SecuritySafeCritical] /// /// @@ -824,20 +829,20 @@ namespace Terminal.Gui { // // Summary: - // Obtains the next character or function key pressed by the user. The pressed key - // is displayed in the console window. + // Obtains the next character or function key pressed by the user. The pressed key + // is displayed in the console window. // // Returns: - // An object that describes the System.ConsoleKey constant and Unicode character, - // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo - // object also describes, in a bitwise combination of System.ConsoleModifiers values, - // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously - // with the console key. + // An object that describes the System.ConsoleKey constant and Unicode character, + // if any, that correspond to the pressed console key. The System.ConsoleKeyInfo + // object also describes, in a bitwise combination of System.ConsoleModifiers values, + // whether one or more Shift, Alt, or Ctrl modifier keys was pressed simultaneously + // with the console key. // // Exceptions: - // T:System.InvalidOperationException: - // The System.Console.In property is redirected from some stream other than the - // console. + // T:System.InvalidOperationException: + // The System.Console.In property is redirected from some stream other than the + // console. /// /// /// @@ -848,21 +853,21 @@ namespace Terminal.Gui { // // Summary: - // Reads the next line of characters from the standard input stream. + // Reads the next line of characters from the standard input stream. // // Returns: - // The next line of characters from the input stream, or null if no more lines are - // available. + // The next line of characters from the input stream, or null if no more lines are + // available. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.OutOfMemoryException: - // There is insufficient memory to allocate a buffer for the returned string. + // T:System.OutOfMemoryException: + // There is insufficient memory to allocate a buffer for the returned string. // - // T:System.ArgumentOutOfRangeException: - // The number of characters in the next line of characters is greater than System.Int32.MaxValue. + // T:System.ArgumentOutOfRangeException: + // The number of characters in the next line of characters is greater than System.Int32.MaxValue. /// /// /// @@ -873,14 +878,14 @@ namespace Terminal.Gui { // // Summary: - // Sets the foreground and background console colors to their defaults. + // Sets the foreground and background console colors to their defaults. // // Exceptions: - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -893,27 +898,27 @@ namespace Terminal.Gui { // // Summary: - // Sets the height and width of the screen buffer area to the specified values. + // Sets the height and width of the screen buffer area to the specified values. // // Parameters: - // width: - // The width of the buffer area measured in columns. + // width: + // The width of the buffer area measured in columns. // - // height: - // The height of the buffer area measured in rows. + // height: + // The height of the buffer area measured in rows. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // height or width is less than or equal to zero.-or- height or width is greater - // than or equal to System.Int16.MaxValue.-or- width is less than System.Console.WindowLeft - // + System.Console.WindowWidth.-or- height is less than System.Console.WindowTop - // + System.Console.WindowHeight. + // T:System.ArgumentOutOfRangeException: + // height or width is less than or equal to zero.-or- height or width is greater + // than or equal to System.Int16.MaxValue.-or- width is less than System.Console.WindowLeft + // + System.Console.WindowWidth.-or- height is less than System.Console.WindowTop + // + System.Console.WindowHeight. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -927,27 +932,27 @@ namespace Terminal.Gui { // // Summary: - // Sets the position of the cursor. + // Sets the position of the cursor. // // Parameters: - // left: - // The column position of the cursor. Columns are numbered from left to right starting - // at 0. + // left: + // The column position of the cursor. Columns are numbered from left to right starting + // at 0. // - // top: - // The row position of the cursor. Rows are numbered from top to bottom starting - // at 0. + // top: + // The row position of the cursor. Rows are numbered from top to bottom starting + // at 0. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // left or top is less than zero.-or- left is greater than or equal to System.Console.BufferWidth.-or- - // top is greater than or equal to System.Console.BufferHeight. + // T:System.ArgumentOutOfRangeException: + // left or top is less than zero.-or- left is greater than or equal to System.Console.BufferWidth.-or- + // top is greater than or equal to System.Console.BufferHeight. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -962,19 +967,19 @@ namespace Terminal.Gui { // // Summary: - // Sets the System.Console.Error property to the specified System.IO.TextWriter - // object. + // Sets the System.Console.Error property to the specified System.IO.TextWriter + // object. // // Parameters: - // newError: - // A stream that is the new standard error output. + // newError: + // A stream that is the new standard error output. // // Exceptions: - // T:System.ArgumentNullException: - // newError is null. + // T:System.ArgumentNullException: + // newError is null. // - // T:System.Security.SecurityException: - // The caller does not have the required permission. + // T:System.Security.SecurityException: + // The caller does not have the required permission. //[SecuritySafeCritical] /// /// @@ -986,18 +991,18 @@ namespace Terminal.Gui { // // Summary: - // Sets the System.Console.In property to the specified System.IO.TextReader object. + // Sets the System.Console.In property to the specified System.IO.TextReader object. // // Parameters: - // newIn: - // A stream that is the new standard input. + // newIn: + // A stream that is the new standard input. // // Exceptions: - // T:System.ArgumentNullException: - // newIn is null. + // T:System.ArgumentNullException: + // newIn is null. // - // T:System.Security.SecurityException: - // The caller does not have the required permission. + // T:System.Security.SecurityException: + // The caller does not have the required permission. //[SecuritySafeCritical] /// /// @@ -1009,18 +1014,18 @@ namespace Terminal.Gui { // // Summary: - // Sets the System.Console.Out property to the specified System.IO.TextWriter object. + // Sets the System.Console.Out property to the specified System.IO.TextWriter object. // // Parameters: - // newOut: - // A stream that is the new standard output. + // newOut: + // A stream that is the new standard output. // // Exceptions: - // T:System.ArgumentNullException: - // newOut is null. + // T:System.ArgumentNullException: + // newOut is null. // - // T:System.Security.SecurityException: - // The caller does not have the required permission. + // T:System.Security.SecurityException: + // The caller does not have the required permission. //[SecuritySafeCritical] /// /// @@ -1033,26 +1038,26 @@ namespace Terminal.Gui { // // Summary: - // Sets the position of the console window relative to the screen buffer. + // Sets the position of the console window relative to the screen buffer. // // Parameters: - // left: - // The column position of the upper left corner of the console window. + // left: + // The column position of the upper left corner of the console window. // - // top: - // The row position of the upper left corner of the console window. + // top: + // The row position of the upper left corner of the console window. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // left or top is less than zero.-or- left + System.Console.WindowWidth is greater - // than System.Console.BufferWidth.-or- top + System.Console.WindowHeight is greater - // than System.Console.BufferHeight. + // T:System.ArgumentOutOfRangeException: + // left or top is less than zero.-or- left + System.Console.WindowWidth is greater + // than System.Console.BufferWidth.-or- top + System.Console.WindowHeight is greater + // than System.Console.BufferHeight. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -1067,27 +1072,27 @@ namespace Terminal.Gui { // // Summary: - // Sets the height and width of the console window to the specified values. + // Sets the height and width of the console window to the specified values. // // Parameters: - // width: - // The width of the console window measured in columns. + // width: + // The width of the console window measured in columns. // - // height: - // The height of the console window measured in rows. + // height: + // The height of the console window measured in rows. // // Exceptions: - // T:System.ArgumentOutOfRangeException: - // width or height is less than or equal to zero.-or- width plus System.Console.WindowLeft - // or height plus System.Console.WindowTop is greater than or equal to System.Int16.MaxValue. - // -or- width or height is greater than the largest possible window width or height - // for the current screen resolution and console font. + // T:System.ArgumentOutOfRangeException: + // width or height is less than or equal to zero.-or- width plus System.Console.WindowLeft + // or height plus System.Console.WindowTop is greater than or equal to System.Int16.MaxValue. + // -or- width or height is greater than the largest possible window width or height + // for the current screen resolution and console font. // - // T:System.Security.SecurityException: - // The user does not have permission to perform this action. + // T:System.Security.SecurityException: + // The user does not have permission to perform this action. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[SecuritySafeCritical] /// /// @@ -1102,15 +1107,15 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified string value to the standard output stream. + // Writes the specified string value to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1122,16 +1127,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified object to the standard output - // stream. + // Writes the text representation of the specified object to the standard output + // stream. // // Parameters: - // value: - // The value to write, or null. + // value: + // The value to write, or null. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1143,16 +1148,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 64-bit unsigned integer value - // to the standard output stream. + // Writes the text representation of the specified 64-bit unsigned integer value + // to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[CLSCompliant (false)] /// /// @@ -1165,16 +1170,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 64-bit signed integer value to - // the standard output stream. + // Writes the text representation of the specified 64-bit signed integer value to + // the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1186,28 +1191,28 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified objects to the standard output - // stream using the specified format information. + // Writes the text representation of the specified objects to the standard output + // stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // The first object to write using format. + // arg0: + // The first object to write using format. // - // arg1: - // The second object to write using format. + // arg1: + // The second object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1221,16 +1226,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 32-bit signed integer value to - // the standard output stream. + // Writes the text representation of the specified 32-bit signed integer value to + // the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1242,25 +1247,25 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified object to the standard output - // stream using the specified format information. + // Writes the text representation of the specified object to the standard output + // stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // An object to write using format. + // arg0: + // An object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1273,16 +1278,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 32-bit unsigned integer value - // to the standard output stream. + // Writes the text representation of the specified 32-bit unsigned integer value + // to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[CLSCompliant (false)] /// /// @@ -1309,25 +1314,25 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified array of objects to the standard - // output stream using the specified format information. + // Writes the text representation of the specified array of objects to the standard + // output stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg: - // An array of objects to write using format. + // arg: + // An array of objects to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format or arg is null. + // T:System.ArgumentNullException: + // format or arg is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1340,16 +1345,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified Boolean value to the standard - // output stream. + // Writes the text representation of the specified Boolean value to the standard + // output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1361,15 +1366,15 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified Unicode character value to the standard output stream. + // Writes the specified Unicode character value to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1381,15 +1386,15 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified array of Unicode characters to the standard output stream. + // Writes the specified array of Unicode characters to the standard output stream. // // Parameters: - // buffer: - // A Unicode character array. + // buffer: + // A Unicode character array. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1404,30 +1409,30 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified subarray of Unicode characters to the standard output stream. + // Writes the specified subarray of Unicode characters to the standard output stream. // // Parameters: - // buffer: - // An array of Unicode characters. + // buffer: + // An array of Unicode characters. // - // index: - // The starting position in buffer. + // index: + // The starting position in buffer. // - // count: - // The number of characters to write. + // count: + // The number of characters to write. // // Exceptions: - // T:System.ArgumentNullException: - // buffer is null. + // T:System.ArgumentNullException: + // buffer is null. // - // T:System.ArgumentOutOfRangeException: - // index or count is less than zero. + // T:System.ArgumentOutOfRangeException: + // index or count is less than zero. // - // T:System.ArgumentException: - // index plus count specify a position that is not within buffer. + // T:System.ArgumentException: + // index plus count specify a position that is not within buffer. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1441,31 +1446,31 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified objects to the standard output - // stream using the specified format information. + // Writes the text representation of the specified objects to the standard output + // stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // The first object to write using format. + // arg0: + // The first object to write using format. // - // arg1: - // The second object to write using format. + // arg1: + // The second object to write using format. // - // arg2: - // The third object to write using format. + // arg2: + // The third object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1480,16 +1485,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified System.Decimal value to the standard - // output stream. + // Writes the text representation of the specified System.Decimal value to the standard + // output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1501,16 +1506,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified single-precision floating-point - // value to the standard output stream. + // Writes the text representation of the specified single-precision floating-point + // value to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1522,16 +1527,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified double-precision floating-point - // value to the standard output stream. + // Writes the text representation of the specified double-precision floating-point + // value to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1543,11 +1548,11 @@ namespace Terminal.Gui { // // Summary: - // Writes the current line terminator to the standard output stream. + // Writes the current line terminator to the standard output stream. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1558,16 +1563,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified single-precision floating-point - // value, followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified single-precision floating-point + // value, followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1579,16 +1584,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 32-bit signed integer value, - // followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified 32-bit signed integer value, + // followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1600,16 +1605,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 32-bit unsigned integer value, - // followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified 32-bit unsigned integer value, + // followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[CLSCompliant (false)] /// /// @@ -1622,16 +1627,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 64-bit signed integer value, - // followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified 64-bit signed integer value, + // followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1643,16 +1648,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified 64-bit unsigned integer value, - // followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified 64-bit unsigned integer value, + // followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. //[CLSCompliant (false)] /// /// @@ -1665,16 +1670,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified object, followed by the current - // line terminator, to the standard output stream. + // Writes the text representation of the specified object, followed by the current + // line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1686,16 +1691,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified string value, followed by the current line terminator, to - // the standard output stream. + // Writes the specified string value, followed by the current line terminator, to + // the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1707,25 +1712,25 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified object, followed by the current - // line terminator, to the standard output stream using the specified format information. + // Writes the text representation of the specified object, followed by the current + // line terminator, to the standard output stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // An object to write using format. + // arg0: + // An object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1738,31 +1743,31 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified objects, followed by the current - // line terminator, to the standard output stream using the specified format information. + // Writes the text representation of the specified objects, followed by the current + // line terminator, to the standard output stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // The first object to write using format. + // arg0: + // The first object to write using format. // - // arg1: - // The second object to write using format. + // arg1: + // The second object to write using format. // - // arg2: - // The third object to write using format. + // arg2: + // The third object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1791,26 +1796,26 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified array of objects, followed by - // the current line terminator, to the standard output stream using the specified - // format information. + // Writes the text representation of the specified array of objects, followed by + // the current line terminator, to the standard output stream using the specified + // format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg: - // An array of objects to write using format. + // arg: + // An array of objects to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format or arg is null. + // T:System.ArgumentNullException: + // format or arg is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1823,31 +1828,31 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified subarray of Unicode characters, followed by the current - // line terminator, to the standard output stream. + // Writes the specified subarray of Unicode characters, followed by the current + // line terminator, to the standard output stream. // // Parameters: - // buffer: - // An array of Unicode characters. + // buffer: + // An array of Unicode characters. // - // index: - // The starting position in buffer. + // index: + // The starting position in buffer. // - // count: - // The number of characters to write. + // count: + // The number of characters to write. // // Exceptions: - // T:System.ArgumentNullException: - // buffer is null. + // T:System.ArgumentNullException: + // buffer is null. // - // T:System.ArgumentOutOfRangeException: - // index or count is less than zero. + // T:System.ArgumentOutOfRangeException: + // index or count is less than zero. // - // T:System.ArgumentException: - // index plus count specify a position that is not within buffer. + // T:System.ArgumentException: + // index plus count specify a position that is not within buffer. // - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1861,16 +1866,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified System.Decimal value, followed - // by the current line terminator, to the standard output stream. + // Writes the text representation of the specified System.Decimal value, followed + // by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1882,16 +1887,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified array of Unicode characters, followed by the current line - // terminator, to the standard output stream. + // Writes the specified array of Unicode characters, followed by the current line + // terminator, to the standard output stream. // // Parameters: - // buffer: - // A Unicode character array. + // buffer: + // A Unicode character array. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1903,16 +1908,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the specified Unicode character, followed by the current line terminator, - // value to the standard output stream. + // Writes the specified Unicode character, followed by the current line terminator, + // value to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1924,16 +1929,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified Boolean value, followed by the - // current line terminator, to the standard output stream. + // Writes the text representation of the specified Boolean value, followed by the + // current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// @@ -1945,28 +1950,28 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified objects, followed by the current - // line terminator, to the standard output stream using the specified format information. + // Writes the text representation of the specified objects, followed by the current + // line terminator, to the standard output stream using the specified format information. // // Parameters: - // format: - // A composite format string (see Remarks). + // format: + // A composite format string (see Remarks). // - // arg0: - // The first object to write using format. + // arg0: + // The first object to write using format. // - // arg1: - // The second object to write using format. + // arg1: + // The second object to write using format. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. // - // T:System.ArgumentNullException: - // format is null. + // T:System.ArgumentNullException: + // format is null. // - // T:System.FormatException: - // The format specification in format is invalid. + // T:System.FormatException: + // The format specification in format is invalid. /// /// /// @@ -1980,16 +1985,16 @@ namespace Terminal.Gui { // // Summary: - // Writes the text representation of the specified double-precision floating-point - // value, followed by the current line terminator, to the standard output stream. + // Writes the text representation of the specified double-precision floating-point + // value, followed by the current line terminator, to the standard output stream. // // Parameters: - // value: - // The value to write. + // value: + // The value to write. // // Exceptions: - // T:System.IO.IOException: - // An I/O error occurred. + // T:System.IO.IOException: + // An I/O error occurred. /// /// /// diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs index 824a63829..661daaca4 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs @@ -1,6 +1,9 @@ // // FakeDriver.cs: A fake ConsoleDriver for unit tests. // +// Authors: +// Charlie Kindel (github.com/tig) +// using System; using System.Collections.Generic; using System.Diagnostics; @@ -45,12 +48,7 @@ namespace Terminal.Gui { // Only handling left here because not all terminals has a horizontal scroll bar. public override int Left => 0; public override int Top => 0; - public override bool EnableConsoleScrolling { get; set; } - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] - public override bool HeightAsBuffer { - get => EnableConsoleScrolling; - set => EnableConsoleScrolling = value; - } + public override bool HeightAsBuffer { get; set; } private IClipboard clipboard = null; public override IClipboard Clipboard => clipboard; @@ -247,8 +245,8 @@ namespace Terminal.Gui { { redrawColor = color; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains (color & 0xffff)) { FakeConsole.BackgroundColor = (ConsoleColor)(color & 0xffff); } @@ -537,7 +535,7 @@ namespace Terminal.Gui { FakeConsole.SetBufferSize (width, height); cols = width; rows = height; - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { SetWindowSize (width, height); } ProcessResize (); @@ -546,7 +544,7 @@ namespace Terminal.Gui { public void SetWindowSize (int width, int height) { FakeConsole.SetWindowSize (width, height); - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { if (width != cols || height != rows) { SetBufferSize (width, height); cols = width; @@ -558,7 +556,7 @@ namespace Terminal.Gui { public void SetWindowPosition (int left, int top) { - if (EnableConsoleScrolling) { + if (HeightAsBuffer) { this.left = Math.Max (Math.Min (left, Cols - FakeConsole.WindowWidth), 0); this.top = Math.Max (Math.Min (top, Rows - FakeConsole.WindowHeight), 0); } else if (this.left > 0 || this.top > 0) { @@ -577,7 +575,7 @@ namespace Terminal.Gui { public override void ResizeScreen () { - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { if (FakeConsole.WindowHeight > 0) { // Can raise an exception while is still resizing. try { @@ -631,8 +629,8 @@ namespace Terminal.Gui { foreground = default; background = default; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains (value & 0xffff)) { hasColor = true; background = (Color)(ConsoleColor)(value & 0xffff); diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index da969d136..9ae4eb20e 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1,4 +1,5 @@ -// +//#define PROCESS_REQUEST +// // NetDriver.cs: The System.Console-based .NET driver, works on Windows and Unix, but is not particularly efficient. // // Authors: @@ -6,7 +7,6 @@ // using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Threading; @@ -111,37 +111,27 @@ namespace Terminal.Gui { ManualResetEventSlim winChange = new ManualResetEventSlim (false); Queue inputResultQueue = new Queue (); ConsoleDriver consoleDriver; - volatile ConsoleKeyInfo [] cki = null; - static volatile bool isEscSeq; int lastWindowHeight; - bool stopTasks; + int largestWindowHeight; #if PROCESS_REQUEST - bool neededProcessRequest; + bool neededProcessRequest; #endif - public bool IsTerminalWithOptions { get; set; } - public EscSeqReqProc EscSeqReqProc { get; } = new EscSeqReqProc (); + public int NumberOfCSI { get; } - public NetEvents (ConsoleDriver consoleDriver) + public NetEvents (ConsoleDriver consoleDriver, int numberOfCSI = 1) { if (consoleDriver == null) { throw new ArgumentNullException ("Console driver instance must be provided."); } this.consoleDriver = consoleDriver; + NumberOfCSI = numberOfCSI; Task.Run (ProcessInputResultQueue); Task.Run (CheckWinChange); } - internal void StopTasks () - { - stopTasks = true; - } - public InputResult? ReadConsoleInput () { while (true) { - if (stopTasks) { - return null; - } waitForStart.Set (); winChange.Set (); @@ -150,7 +140,7 @@ namespace Terminal.Gui { inputReady.Reset (); } #if PROCESS_REQUEST - neededProcessRequest = false; + neededProcessRequest = false; #endif if (inputResultQueue.Count > 0) { return inputResultQueue.Dequeue (); @@ -165,53 +155,16 @@ namespace Terminal.Gui { waitForStart.Reset (); if (inputResultQueue.Count == 0) { - GetConsoleKey (); + GetConsoleInputType (Console.ReadKey (true)); } inputReady.Set (); } } - void GetConsoleKey () - { - ConsoleKey key = 0; - ConsoleModifiers mod = 0; - ConsoleKeyInfo newConsoleKeyInfo = default; - - while (true) { - ConsoleKeyInfo consoleKeyInfo = Console.ReadKey (true); - if ((consoleKeyInfo.KeyChar == (char)Key.Esc && !isEscSeq) - || (consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq)) { - if (cki == null && consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq) { - cki = EscSeqUtils.ResizeArray (new ConsoleKeyInfo ((char)Key.Esc, 0, - false, false, false), cki); - } - isEscSeq = true; - newConsoleKeyInfo = consoleKeyInfo; - cki = EscSeqUtils.ResizeArray (consoleKeyInfo, cki); - if (!Console.KeyAvailable) { - DecodeEscSeq (ref newConsoleKeyInfo, ref key, cki, ref mod); - cki = null; - isEscSeq = false; - break; - } - } else if (consoleKeyInfo.KeyChar == (char)Key.Esc && isEscSeq) { - DecodeEscSeq (ref newConsoleKeyInfo, ref key, cki, ref mod); - cki = null; - break; - } else { - GetConsoleInputType (consoleKeyInfo); - break; - } - } - } - void CheckWinChange () { while (true) { - if (stopTasks) { - return; - } winChange.Wait (); winChange.Reset (); WaitWinChange (); @@ -224,58 +177,44 @@ namespace Terminal.Gui { while (true) { // HACK: Sleep for 10ms to mitigate high CPU usage (see issue #1502). 10ms was tested to address the problem, but may not be correct. Thread.Sleep (10); - if (stopTasks) { - return; - } - switch (IsTerminalWithOptions) { - case false: - int buffHeight, buffWidth; - if (((NetDriver)consoleDriver).IsWinPlatform) { - buffHeight = Math.Max (Console.BufferHeight, 0); - buffWidth = Math.Max (Console.BufferWidth, 0); - } else { - buffHeight = consoleDriver.Rows; - buffWidth = consoleDriver.Cols; - } - if (IsWinChanged ( - Math.Max (Console.WindowHeight, 0), - Math.Max (Console.WindowWidth, 0), - buffHeight, - buffWidth)) { - + if (!consoleDriver.HeightAsBuffer) { + if (Console.WindowWidth != consoleDriver.Cols || Console.WindowHeight != consoleDriver.Rows) { + var w = Math.Max (Console.WindowWidth, 0); + var h = Math.Max (Console.WindowHeight, 0); + GetWindowSizeEvent (new Size (w, h)); return; } - break; - case true: - //Request the size of the text area in characters. - EscSeqReqProc.Add ("t"); - Console.Out.Write ("\x1b[18t"); - break; + } else { + //largestWindowHeight = Math.Max (Console.BufferHeight, largestWindowHeight); + largestWindowHeight = Console.BufferHeight; + if (Console.BufferWidth != consoleDriver.Cols || largestWindowHeight != consoleDriver.Rows + || Console.WindowHeight != lastWindowHeight) { + lastWindowHeight = Console.WindowHeight; + GetWindowSizeEvent (new Size (Console.BufferWidth, lastWindowHeight)); + return; + } + if (Console.WindowTop != consoleDriver.Top) { + // Top only working on Windows. + var winPositionEv = new WindowPositionEvent () { + Top = Console.WindowTop, + Left = Console.WindowLeft + }; + inputResultQueue.Enqueue (new InputResult () { + EventType = EventType.WindowPosition, + WindowPositionEvent = winPositionEv + }); + return; + } +#if PROCESS_REQUEST + if (!neededProcessRequest) { + Console.Out.Write ("\x1b[6n"); + neededProcessRequest = true; + } +#endif } } } - bool IsWinChanged (int winHeight, int winWidth, int buffHeight, int buffWidth) - { - if (!consoleDriver.EnableConsoleScrolling) { - if (winWidth != consoleDriver.Cols || winHeight != consoleDriver.Rows) { - var w = Math.Max (winWidth, 0); - var h = Math.Max (winHeight, 0); - GetWindowSizeEvent (new Size (w, h)); - return true; - } - } else { - if (winWidth != consoleDriver.Cols || winHeight != lastWindowHeight - || buffWidth != consoleDriver.Cols || buffHeight != consoleDriver.Rows) { - - lastWindowHeight = Math.Max (winHeight, 0); - GetWindowSizeEvent (new Size (winWidth, lastWindowHeight)); - return true; - } - } - return false; - } - void GetWindowSizeEvent (Size size) { WindowSizeEvent windowSizeEvent = new WindowSizeEvent () { @@ -293,8 +232,65 @@ namespace Terminal.Gui { InputResult inputResult = new InputResult { EventType = EventType.Key }; + ConsoleKeyInfo newConsoleKeyInfo = consoleKeyInfo; + ConsoleKey key = 0; MouseEvent mouseEvent = new MouseEvent (); - ConsoleKeyInfo newConsoleKeyInfo = EscSeqUtils.GetConsoleInputKey (consoleKeyInfo); + var keyChar = consoleKeyInfo.KeyChar; + switch ((uint)keyChar) { + case 0: + if (consoleKeyInfo.Key == (ConsoleKey)64) { // Ctrl+Space in Windows. + newConsoleKeyInfo = new ConsoleKeyInfo (' ', ConsoleKey.Spacebar, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0); + } + break; + case uint n when (n >= '\u0001' && n <= '\u001a'): + if (consoleKeyInfo.Key == 0 && consoleKeyInfo.KeyChar == '\r') { + key = ConsoleKey.Enter; + newConsoleKeyInfo = new ConsoleKeyInfo (consoleKeyInfo.KeyChar, + key, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0); + } else if (consoleKeyInfo.Key == 0) { + key = (ConsoleKey)(char)(consoleKeyInfo.KeyChar + (uint)ConsoleKey.A - 1); + newConsoleKeyInfo = new ConsoleKeyInfo ((char)key, + key, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0, + true); + } + break; + case 27: + //case 91: + ConsoleKeyInfo [] cki = new ConsoleKeyInfo [] { consoleKeyInfo }; + ConsoleModifiers mod = consoleKeyInfo.Modifiers; + int delay = 0; + while (delay < 100) { + if (Console.KeyAvailable) { + do { + var result = Console.ReadKey (true); + Array.Resize (ref cki, cki == null ? 1 : cki.Length + 1); + cki [cki.Length - 1] = result; + } while (Console.KeyAvailable); + break; + } + Thread.Sleep (50); + delay += 50; + } + SplitCSI (cki, ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, ref mod); + return; + case 127: + newConsoleKeyInfo = new ConsoleKeyInfo (consoleKeyInfo.KeyChar, ConsoleKey.Backspace, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0, + (consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0); + break; + default: + newConsoleKeyInfo = consoleKeyInfo; + break; + } if (inputResult.EventType == EventType.Key) { inputResult.ConsoleKeyInfo = newConsoleKeyInfo; } else { @@ -304,234 +300,808 @@ namespace Terminal.Gui { inputResultQueue.Enqueue (inputResult); } - void DecodeEscSeq (ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ConsoleKeyInfo [] cki, ref ConsoleModifiers mod) + void SplitCSI (ConsoleKeyInfo [] cki, ref InputResult inputResult, ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ref MouseEvent mouseEvent, ref ConsoleModifiers mod) { - string c1Control, code, terminating; - string [] values; - // isKeyMouse is true if it's CSI<, false otherwise - bool isKeyMouse; - bool isReq; - List mouseFlags; - Point pos; - EscSeqUtils.DecodeEscSeq (EscSeqReqProc, ref newConsoleKeyInfo, ref key, cki, ref mod, out c1Control, out code, out values, out terminating, out isKeyMouse, out mouseFlags, out pos, out isReq, ProcessContinuousButtonPressed); - - if (isKeyMouse) { - foreach (var mf in mouseFlags) { - GetMouseEvent (MapMouseFlags (mf), pos); + ConsoleKeyInfo [] splitedCki = new ConsoleKeyInfo [] { }; + int length = 0; + var kChar = GetKeyCharArray (cki); + var nCSI = GetNumberOfCSI (kChar); + int curCSI = 0; + char previousKChar = '\0'; + if (nCSI > 1) { + for (int i = 0; i < cki.Length; i++) { + var ck = cki [i]; + if (NumberOfCSI > 0 && nCSI - curCSI > NumberOfCSI) { + if (i + 1 < cki.Length && cki [i + 1].KeyChar == '\x1b' && previousKChar != '\0') { + curCSI++; + previousKChar = '\0'; + } else { + previousKChar = ck.KeyChar; + } + continue; + } + if (ck.KeyChar == '\x1b') { + if (ck.KeyChar == 'R') { + ResizeArray (ck); + } + if (splitedCki.Length > 1) { + DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, splitedCki, ref mod); + } + splitedCki = new ConsoleKeyInfo [] { }; + length = 0; + } + ResizeArray (ck); + if (i == cki.Length - 1 && splitedCki.Length > 0) { + DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, splitedCki, ref mod); + } } + } else { + DecodeCSI (ref inputResult, ref newConsoleKeyInfo, ref key, ref mouseEvent, cki, ref mod); + } + + void ResizeArray (ConsoleKeyInfo ck) + { + length++; + Array.Resize (ref splitedCki, length); + splitedCki [length - 1] = ck; + } + } + + char [] GetKeyCharArray (ConsoleKeyInfo [] cki) + { + char [] kChar = new char [] { }; + var length = 0; + foreach (var kc in cki) { + length++; + Array.Resize (ref kChar, length); + kChar [length - 1] = kc.KeyChar; + } + + return kChar; + } + + int GetNumberOfCSI (char [] csi) + { + int nCSI = 0; + for (int i = 0; i < csi.Length; i++) { + if (csi [i] == '\x1b' || (csi [i] == '[' && (i == 0 || (i > 0 && csi [i - 1] != '\x1b')))) { + nCSI++; + } + } + + return nCSI; + } + + void DecodeCSI (ref InputResult inputResult, ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ref MouseEvent mouseEvent, ConsoleKeyInfo [] cki, ref ConsoleModifiers mod) + { + switch (cki.Length) { + case 2: + if ((uint)cki [1].KeyChar >= 1 && (uint)cki [1].KeyChar <= 26) { + key = (ConsoleKey)(char)(cki [1].KeyChar + (uint)ConsoleKey.A - 1); + newConsoleKeyInfo = new ConsoleKeyInfo (cki [1].KeyChar, + key, + false, + true, + true); + } else { + if (cki [1].KeyChar >= 97 && cki [1].KeyChar <= 122) { + key = (ConsoleKey)cki [1].KeyChar.ToString ().ToUpper () [0]; + } else { + key = (ConsoleKey)cki [1].KeyChar; + } + newConsoleKeyInfo = new ConsoleKeyInfo ((char)key, + (ConsoleKey)Math.Min ((uint)key, 255), + false, + true, + false); + } + break; + case 3: + if (cki [1].KeyChar == '[' || cki [1].KeyChar == 79) { + key = GetConsoleKey (cki [2].KeyChar, ref mod, cki.Length); + } + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + break; + case 4: + if (cki [1].KeyChar == '[' && cki [3].KeyChar == 126) { + key = GetConsoleKey (cki [2].KeyChar, ref mod, cki.Length); + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + } + break; + case 5: + if (cki [1].KeyChar == '[' && (cki [2].KeyChar == 49 || cki [2].KeyChar == 50) + && cki [4].KeyChar == 126) { + key = GetConsoleKey (cki [3].KeyChar, ref mod, cki.Length); + } else if (cki [1].KeyChar == 49 && cki [2].KeyChar == ';') { // For WSL + mod |= GetConsoleModifiers (cki [3].KeyChar); + key = ConsoleKey.End; + } + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + break; + case 6: + if (cki [1].KeyChar == '[' && cki [2].KeyChar == 49 && cki [3].KeyChar == ';') { + mod |= GetConsoleModifiers (cki [4].KeyChar); + key = GetConsoleKey (cki [5].KeyChar, ref mod, cki.Length); + } else if (cki [1].KeyChar == '[' && cki [3].KeyChar == ';') { + mod |= GetConsoleModifiers (cki [4].KeyChar); + key = GetConsoleKey (cki [2].KeyChar, ref mod, cki.Length); + } + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + break; + case 7: + GetRequestEvent (GetKeyCharArray (cki)); return; - } else if (isReq) { - GetRequestEvent (c1Control, code, values, terminating); + case int n when n >= 8: + GetMouseEvent (cki); return; } - InputResult inputResult = new InputResult { - EventType = EventType.Key, - ConsoleKeyInfo = newConsoleKeyInfo - }; + if (inputResult.EventType == EventType.Key) { + inputResult.ConsoleKeyInfo = newConsoleKeyInfo; + } else { + inputResult.MouseEvent = mouseEvent; + } inputResultQueue.Enqueue (inputResult); } - void ProcessContinuousButtonPressed (MouseFlags mouseFlag, Point pos) - { - GetMouseEvent (MapMouseFlags (mouseFlag), pos); - } - - MouseButtonState MapMouseFlags (MouseFlags mouseFlags) - { - MouseButtonState mbs = default; - foreach (var flag in Enum.GetValues (mouseFlags.GetType ())) { - if (mouseFlags.HasFlag ((MouseFlags)flag)) { - switch (flag) { - case MouseFlags.Button1Pressed: - mbs |= MouseButtonState.Button1Pressed; - break; - case MouseFlags.Button1Released: - mbs |= MouseButtonState.Button1Released; - break; - case MouseFlags.Button1Clicked: - mbs |= MouseButtonState.Button1Clicked; - break; - case MouseFlags.Button1DoubleClicked: - mbs |= MouseButtonState.Button1DoubleClicked; - break; - case MouseFlags.Button1TripleClicked: - mbs |= MouseButtonState.Button1TripleClicked; - break; - case MouseFlags.Button2Pressed: - mbs |= MouseButtonState.Button2Pressed; - break; - case MouseFlags.Button2Released: - mbs |= MouseButtonState.Button2Released; - break; - case MouseFlags.Button2Clicked: - mbs |= MouseButtonState.Button2Clicked; - break; - case MouseFlags.Button2DoubleClicked: - mbs |= MouseButtonState.Button2DoubleClicked; - break; - case MouseFlags.Button2TripleClicked: - mbs |= MouseButtonState.Button2TripleClicked; - break; - case MouseFlags.Button3Pressed: - mbs |= MouseButtonState.Button3Pressed; - break; - case MouseFlags.Button3Released: - mbs |= MouseButtonState.Button3Released; - break; - case MouseFlags.Button3Clicked: - mbs |= MouseButtonState.Button3Clicked; - break; - case MouseFlags.Button3DoubleClicked: - mbs |= MouseButtonState.Button3DoubleClicked; - break; - case MouseFlags.Button3TripleClicked: - mbs |= MouseButtonState.Button3TripleClicked; - break; - case MouseFlags.WheeledUp: - mbs |= MouseButtonState.ButtonWheeledUp; - break; - case MouseFlags.WheeledDown: - mbs |= MouseButtonState.ButtonWheeledDown; - break; - case MouseFlags.WheeledLeft: - mbs |= MouseButtonState.ButtonWheeledLeft; - break; - case MouseFlags.WheeledRight: - mbs |= MouseButtonState.ButtonWheeledRight; - break; - case MouseFlags.Button4Pressed: - mbs |= MouseButtonState.Button4Pressed; - break; - case MouseFlags.Button4Released: - mbs |= MouseButtonState.Button4Released; - break; - case MouseFlags.Button4Clicked: - mbs |= MouseButtonState.Button4Clicked; - break; - case MouseFlags.Button4DoubleClicked: - mbs |= MouseButtonState.Button4DoubleClicked; - break; - case MouseFlags.Button4TripleClicked: - mbs |= MouseButtonState.Button4TripleClicked; - break; - case MouseFlags.ButtonShift: - mbs |= MouseButtonState.ButtonShift; - break; - case MouseFlags.ButtonCtrl: - mbs |= MouseButtonState.ButtonCtrl; - break; - case MouseFlags.ButtonAlt: - mbs |= MouseButtonState.ButtonAlt; - break; - case MouseFlags.ReportMousePosition: - mbs |= MouseButtonState.ReportMousePosition; - break; - case MouseFlags.AllEvents: - mbs |= MouseButtonState.AllEvents; - break; - } - } - } - return mbs; - } - Point lastCursorPosition; - void GetRequestEvent (string c1Control, string code, string [] values, string terminating) + void GetRequestEvent (char [] kChar) { EventType eventType = new EventType (); - switch (terminating) { - case "R": // Reports cursor position as CSI r ; c R - Point point = new Point { - X = int.Parse (values [1]) - 1, - Y = int.Parse (values [0]) - 1 - }; - if (lastCursorPosition.Y != point.Y) { - lastCursorPosition = point; - eventType = EventType.WindowPosition; - var winPositionEv = new WindowPositionEvent () { - CursorPosition = point - }; - inputResultQueue.Enqueue (new InputResult () { - EventType = eventType, - WindowPositionEvent = winPositionEv - }); - } else { - return; - } - break; - case "c": - try { - var parent = EscSeqUtils.GetParentProcess (Process.GetCurrentProcess ()); - if (parent == null) { Debug.WriteLine ("Not supported!"); } - } catch (Exception ex) { - Debug.WriteLine (ex.Message); - } + Point point = new Point (); + int foundPoint = 0; + string value = ""; + for (int i = 0; i < kChar.Length; i++) { + var c = kChar [i]; + if (c == '\u001b' || c == '[') { + foundPoint++; + } else if (foundPoint == 1 && c != ';' && c != '?') { + value += c.ToString (); + } else if (c == '?') { + foundPoint++; + } else if (c == ';') { + if (foundPoint >= 1) { + point.Y = int.Parse (value) - 1; + } + value = ""; + foundPoint++; + } else if (foundPoint > 0 && i < kChar.Length - 1) { + value += c.ToString (); + } else if (i == kChar.Length - 1) { + point.X = int.Parse (value) + Console.WindowTop - 1; - if (c1Control == "CSI" && values.Length == 2 - && values [0] == "1" && values [1] == "0") { - // Reports CSI?1;0c ("VT101 with No Options") - IsTerminalWithOptions = false; - } else { - IsTerminalWithOptions = true; + switch (c) { + case 'R': + if (lastCursorPosition.Y != point.Y) { + lastCursorPosition = point; + eventType = EventType.WindowPosition; + var winPositionEv = new WindowPositionEvent () { + CursorPosition = point + }; + inputResultQueue.Enqueue (new InputResult () { + EventType = eventType, + WindowPositionEvent = winPositionEv + }); + } else { + return; + } + break; + case 'c': // CSI?1;0c ("VT101 with No Options") + break; + default: + throw new NotImplementedException (); + } } - break; - case "t": - switch (values [0]) { - case "8": - IsWinChanged ( - Math.Max (int.Parse (values [1]), 0), - Math.Max (int.Parse (values [2]), 0), - Math.Max (int.Parse (values [1]), 0), - Math.Max (int.Parse (values [2]), 0)); - break; - default: - SetRequestedEvent (c1Control, code, values, terminating); - break; - } - break; - default: - SetRequestedEvent (c1Control, code, values, terminating); - break; } inputReady.Set (); } - void SetRequestedEvent (string c1Control, string code, string [] values, string terminating) - { - EventType eventType = EventType.RequestResponse; - var requestRespEv = new RequestResponseEvent () { - ResultTuple = (c1Control, code, values, terminating) - }; - inputResultQueue.Enqueue (new InputResult () { - EventType = eventType, - RequestResponseEvent = requestRespEv - }); - } + MouseEvent lastMouseEvent; + bool isButtonPressed; + bool isButtonClicked; + bool isButtonDoubleClicked; + bool isButtonTripleClicked; + bool isProcContBtnPressedRuning; + int buttonPressedCount; + //bool isButtonReleased; - void GetMouseEvent (MouseButtonState buttonState, Point pos) + void GetMouseEvent (ConsoleKeyInfo [] cki) { - MouseEvent mouseEvent = new MouseEvent () { - Position = pos, - ButtonState = buttonState, - }; + MouseEvent mouseEvent = new MouseEvent (); + MouseButtonState buttonState = 0; + Point point = new Point (); + int buttonCode = 0; + bool foundButtonCode = false; + int foundPoint = 0; + string value = ""; + var kChar = GetKeyCharArray (cki); + //System.Diagnostics.Debug.WriteLine ($"kChar: {new string (kChar)}"); + for (int i = 0; i < kChar.Length; i++) { + var c = kChar [i]; + if (c == '<') { + foundButtonCode = true; + } else if (foundButtonCode && c != ';') { + value += c.ToString (); + } else if (c == ';') { + if (foundButtonCode) { + foundButtonCode = false; + buttonCode = int.Parse (value); + } + if (foundPoint == 1) { + point.X = int.Parse (value) - 1; + } + value = ""; + foundPoint++; + } else if (foundPoint > 0 && c != 'm' && c != 'M') { + value += c.ToString (); + } else if (c == 'm' || c == 'M') { + point.Y = int.Parse (value) + Console.WindowTop - 1; + + //if (c == 'M') { + // isButtonPressed = true; + //} else if (c == 'm') { + // isButtonPressed = false; + //} + + //System.Diagnostics.Debug.WriteLine ($"buttonCode: {buttonCode}"); + + switch (buttonCode) { + case 0: + case 8: + case 16: + case 24: + case 32: + case 36: + case 40: + case 48: + case 56: + buttonState = c == 'M' ? MouseButtonState.Button1Pressed + : MouseButtonState.Button1Released; + break; + case 1: + case 9: + case 17: + case 25: + case 33: + case 37: + case 41: + case 45: + case 49: + case 53: + case 57: + case 61: + buttonState = c == 'M' ? MouseButtonState.Button2Pressed + : MouseButtonState.Button2Released; + break; + case 2: + case 10: + case 14: + case 18: + case 22: + case 26: + case 30: + case 34: + case 42: + case 46: + case 50: + case 54: + case 58: + case 62: + buttonState = c == 'M' ? MouseButtonState.Button3Pressed + : MouseButtonState.Button3Released; + break; + case 35: + case 39: + case 43: + case 47: + case 55: + case 59: + case 63: + buttonState = MouseButtonState.ReportMousePosition; + break; + case 64: + buttonState = MouseButtonState.ButtonWheeledUp; + break; + case 65: + buttonState = MouseButtonState.ButtonWheeledDown; + break; + case 68: + case 72: + case 80: + buttonState = MouseButtonState.ButtonWheeledLeft; // Shift/Ctrl+ButtonWheeledUp + break; + case 69: + case 73: + case 81: + buttonState = MouseButtonState.ButtonWheeledRight; // Shift/Ctrl+ButtonWheeledDown + break; + } + // Modifiers. + switch (buttonCode) { + case 8: + case 9: + case 10: + case 43: + buttonState |= MouseButtonState.ButtonAlt; + break; + case 14: + case 47: + buttonState |= MouseButtonState.ButtonAlt | MouseButtonState.ButtonShift; + break; + case 16: + case 17: + case 18: + case 51: + buttonState |= MouseButtonState.ButtonCtrl; + break; + case 22: + case 55: + buttonState |= MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift; + break; + case 24: + case 25: + case 26: + case 59: + buttonState |= MouseButtonState.ButtonAlt | MouseButtonState.ButtonCtrl; + break; + case 30: + case 63: + buttonState |= MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift | MouseButtonState.ButtonAlt; + break; + case 32: + case 33: + case 34: + buttonState |= MouseButtonState.ReportMousePosition; + break; + case 36: + case 37: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonShift; + break; + case 39: + case 68: + case 69: + buttonState |= MouseButtonState.ButtonShift; + break; + case 40: + case 41: + case 42: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonAlt; + break; + case 45: + case 46: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonAlt | MouseButtonState.ButtonShift; + break; + case 48: + case 49: + case 50: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl; + break; + case 53: + case 54: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift; + break; + case 56: + case 57: + case 58: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonAlt; + break; + case 61: + case 62: + buttonState |= MouseButtonState.ReportMousePosition | MouseButtonState.ButtonCtrl | MouseButtonState.ButtonShift | MouseButtonState.ButtonAlt; + break; + } + } + } + mouseEvent.Position.X = point.X; + mouseEvent.Position.Y = point.Y; + mouseEvent.ButtonState = buttonState; + //System.Diagnostics.Debug.WriteLine ($"ButtonState: {mouseEvent.ButtonState} X: {mouseEvent.Position.X} Y: {mouseEvent.Position.Y}"); + + if (isButtonDoubleClicked) { + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessButtonDoubleClickedAsync ()); + return false; + }); + } + + if ((buttonState & MouseButtonState.Button1Pressed) != 0 + || (buttonState & MouseButtonState.Button2Pressed) != 0 + || (buttonState & MouseButtonState.Button3Pressed) != 0) { + + if ((buttonState & MouseButtonState.ReportMousePosition) == 0) { + buttonPressedCount++; + } else { + buttonPressedCount = 0; + } + //System.Diagnostics.Debug.WriteLine ($"buttonPressedCount: {buttonPressedCount}"); + isButtonPressed = true; + } else { + isButtonPressed = false; + buttonPressedCount = 0; + } + + if (buttonPressedCount == 2 && !isButtonDoubleClicked + && (lastMouseEvent.ButtonState == MouseButtonState.Button1Pressed + || lastMouseEvent.ButtonState == MouseButtonState.Button2Pressed + || lastMouseEvent.ButtonState == MouseButtonState.Button3Pressed)) { + + isButtonDoubleClicked = true; + ProcessButtonDoubleClicked (mouseEvent); + inputReady.Set (); + return; + } else if (buttonPressedCount == 3 && isButtonDoubleClicked + && (lastMouseEvent.ButtonState == MouseButtonState.Button1Pressed + || lastMouseEvent.ButtonState == MouseButtonState.Button2Pressed + || lastMouseEvent.ButtonState == MouseButtonState.Button3Pressed)) { + + isButtonDoubleClicked = false; + isButtonTripleClicked = true; + buttonPressedCount = 0; + ProcessButtonTripleClicked (mouseEvent); + lastMouseEvent = mouseEvent; + inputReady.Set (); + return; + } + + //System.Diagnostics.Debug.WriteLine ($"isButtonClicked: {isButtonClicked} isButtonDoubleClicked: {isButtonDoubleClicked} isButtonTripleClicked: {isButtonTripleClicked}"); + if ((isButtonClicked || isButtonDoubleClicked || isButtonTripleClicked) + && ((buttonState & MouseButtonState.Button1Released) != 0 + || (buttonState & MouseButtonState.Button2Released) != 0 + || (buttonState & MouseButtonState.Button3Released) != 0)) { + + //isButtonClicked = false; + //isButtonDoubleClicked = false; + isButtonTripleClicked = false; + buttonPressedCount = 0; + return; + } + + if (isButtonClicked && !isButtonDoubleClicked && lastMouseEvent.Position != default && lastMouseEvent.Position == point + && ((buttonState & MouseButtonState.Button1Pressed) != 0 + || (buttonState & MouseButtonState.Button2Pressed) != 0 + || (buttonState & MouseButtonState.Button3Pressed) != 0 + || (buttonState & MouseButtonState.Button1Released) != 0 + || (buttonState & MouseButtonState.Button2Released) != 0 + || (buttonState & MouseButtonState.Button3Released) != 0)) { + + isButtonClicked = false; + isButtonDoubleClicked = true; + ProcessButtonDoubleClicked (mouseEvent); + Application.MainLoop.AddIdle (() => { + Task.Run (async () => { + await Task.Delay (600); + isButtonDoubleClicked = false; + }); + return false; + }); + inputReady.Set (); + return; + } + if (isButtonDoubleClicked && lastMouseEvent.Position != default && lastMouseEvent.Position == point + && ((buttonState & MouseButtonState.Button1Pressed) != 0 + || (buttonState & MouseButtonState.Button2Pressed) != 0 + || (buttonState & MouseButtonState.Button3Pressed) != 0 + || (buttonState & MouseButtonState.Button1Released) != 0 + || (buttonState & MouseButtonState.Button2Released) != 0 + || (buttonState & MouseButtonState.Button3Released) != 0)) { + + isButtonDoubleClicked = false; + isButtonTripleClicked = true; + ProcessButtonTripleClicked (mouseEvent); + inputReady.Set (); + return; + } + + //if (!isButtonPressed && !isButtonClicked && !isButtonDoubleClicked && !isButtonTripleClicked + // && !isButtonReleased && lastMouseEvent.ButtonState != 0 + // && ((buttonState & MouseButtonState.Button1Released) == 0 + // && (buttonState & MouseButtonState.Button2Released) == 0 + // && (buttonState & MouseButtonState.Button3Released) == 0)) { + // ProcessButtonReleased (lastMouseEvent); + // inputReady.Set (); + // return; + //} inputResultQueue.Enqueue (new InputResult () { EventType = EventType.Mouse, MouseEvent = mouseEvent }); + if (!isButtonClicked && !lastMouseEvent.ButtonState.HasFlag (MouseButtonState.ReportMousePosition) + && lastMouseEvent.Position != default && lastMouseEvent.Position == point + && ((buttonState & MouseButtonState.Button1Released) != 0 + || (buttonState & MouseButtonState.Button2Released) != 0 + || (buttonState & MouseButtonState.Button3Released) != 0)) { + isButtonClicked = true; + ProcessButtonClicked (mouseEvent); + Application.MainLoop.AddIdle (() => { + Task.Run (async () => { + await Task.Delay (300); + isButtonClicked = false; + }); + return false; + }); + inputReady.Set (); + return; + } + + lastMouseEvent = mouseEvent; + if (isButtonPressed && !isButtonClicked && !isButtonDoubleClicked && !isButtonTripleClicked && !isProcContBtnPressedRuning) { + //isButtonReleased = false; + if ((buttonState & MouseButtonState.ReportMousePosition) != 0) { + point = new Point (); + } else { + point = new Point () { + X = mouseEvent.Position.X, + Y = mouseEvent.Position.Y + }; + } + if ((buttonState & MouseButtonState.ReportMousePosition) == 0) { + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessContinuousButtonPressedAsync ()); + return false; + }); + } + } + inputReady.Set (); } + void ProcessButtonClicked (MouseEvent mouseEvent) + { + var me = new MouseEvent () { + Position = mouseEvent.Position, + ButtonState = mouseEvent.ButtonState + }; + if ((mouseEvent.ButtonState & MouseButtonState.Button1Released) != 0) { + me.ButtonState &= ~MouseButtonState.Button1Released; + me.ButtonState |= MouseButtonState.Button1Clicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button2Released) != 0) { + me.ButtonState &= ~MouseButtonState.Button2Released; + me.ButtonState |= MouseButtonState.Button2Clicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button3Released) != 0) { + me.ButtonState &= ~MouseButtonState.Button3Released; + me.ButtonState |= MouseButtonState.Button3Clicked; + } + //isButtonReleased = true; + + inputResultQueue.Enqueue (new InputResult () { + EventType = EventType.Mouse, + MouseEvent = me + }); + } + + async Task ProcessButtonDoubleClickedAsync () + { + await Task.Delay (300); + isButtonDoubleClicked = false; + buttonPressedCount = 0; + } + + void ProcessButtonDoubleClicked (MouseEvent mouseEvent) + { + var me = new MouseEvent () { + Position = mouseEvent.Position, + ButtonState = mouseEvent.ButtonState + }; + if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button1Pressed; + me.ButtonState |= MouseButtonState.Button1DoubleClicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button2Pressed; + me.ButtonState |= MouseButtonState.Button2DoubleClicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button3Pressed; + me.ButtonState |= MouseButtonState.Button3DoubleClicked; + } + //isButtonReleased = true; + + inputResultQueue.Enqueue (new InputResult () { + EventType = EventType.Mouse, + MouseEvent = me + }); + } + + void ProcessButtonTripleClicked (MouseEvent mouseEvent) + { + var me = new MouseEvent () { + Position = mouseEvent.Position, + ButtonState = mouseEvent.ButtonState + }; + if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button1Pressed; + me.ButtonState |= MouseButtonState.Button1TripleClicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button2Pressed; + me.ButtonState |= MouseButtonState.Button2TrippleClicked; + } else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) { + me.ButtonState &= ~MouseButtonState.Button3Pressed; + me.ButtonState |= MouseButtonState.Button3TripleClicked; + } + //isButtonReleased = true; + + inputResultQueue.Enqueue (new InputResult () { + EventType = EventType.Mouse, + MouseEvent = me + }); + } + + async Task ProcessContinuousButtonPressedAsync () + { + isProcContBtnPressedRuning = true; + await Task.Delay (200); + while (isButtonPressed) { + await Task.Delay (100); + var view = Application.WantContinuousButtonPressedView; + if (view == null) { + break; + } + if (isButtonPressed && (lastMouseEvent.ButtonState & MouseButtonState.ReportMousePosition) == 0) { + inputResultQueue.Enqueue (new InputResult () { + EventType = EventType.Mouse, + MouseEvent = lastMouseEvent + }); + inputReady.Set (); + } + } + isProcContBtnPressedRuning = false; + //isButtonPressed = false; + } + + //void ProcessButtonReleased (MouseEvent mouseEvent) + //{ + // var me = new MouseEvent () { + // Position = mouseEvent.Position, + // ButtonState = mouseEvent.ButtonState + // }; + // if ((mouseEvent.ButtonState & MouseButtonState.Button1Pressed) != 0) { + // me.ButtonState &= ~(MouseButtonState.Button1Pressed | MouseButtonState.ReportMousePosition); + // me.ButtonState |= MouseButtonState.Button1Released; + // } else if ((mouseEvent.ButtonState & MouseButtonState.Button2Pressed) != 0) { + // me.ButtonState &= ~(MouseButtonState.Button2Pressed | MouseButtonState.ReportMousePosition); + // me.ButtonState |= MouseButtonState.Button2Released; + // } else if ((mouseEvent.ButtonState & MouseButtonState.Button3Pressed) != 0) { + // me.ButtonState &= ~(MouseButtonState.Button3Pressed | MouseButtonState.ReportMousePosition); + // me.ButtonState |= MouseButtonState.Button3Released; + // } + // isButtonReleased = true; + // lastMouseEvent = me; + + // inputResultQueue.Enqueue (new InputResult () { + // EventType = EventType.Mouse, + // MouseEvent = me + // }); + //} + + ConsoleModifiers GetConsoleModifiers (uint keyChar) + { + switch (keyChar) { + case 50: + return ConsoleModifiers.Shift; + case 51: + return ConsoleModifiers.Alt; + case 52: + return ConsoleModifiers.Shift | ConsoleModifiers.Alt; + case 53: + return ConsoleModifiers.Control; + case 54: + return ConsoleModifiers.Shift | ConsoleModifiers.Control; + case 55: + return ConsoleModifiers.Alt | ConsoleModifiers.Control; + case 56: + return ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control; + default: + return 0; + } + } + + ConsoleKey GetConsoleKey (char keyChar, ref ConsoleModifiers mod, int length) + { + ConsoleKey key; + switch (keyChar) { + case 'A': + key = ConsoleKey.UpArrow; + break; + case 'B': + key = ConsoleKey.DownArrow; + break; + case 'C': + key = ConsoleKey.RightArrow; + break; + case 'D': + key = ConsoleKey.LeftArrow; + break; + case 'F': + key = ConsoleKey.End; + break; + case 'H': + key = ConsoleKey.Home; + break; + case 'P': + key = ConsoleKey.F1; + break; + case 'Q': + key = ConsoleKey.F2; + break; + case 'R': + key = ConsoleKey.F3; + break; + case 'S': + key = ConsoleKey.F4; + break; + case 'Z': + key = ConsoleKey.Tab; + mod |= ConsoleModifiers.Shift; + break; + case '0': + key = ConsoleKey.F9; + break; + case '1': + key = ConsoleKey.F10; + break; + case '2': + key = ConsoleKey.Insert; + break; + case '3': + if (length == 5) { + key = ConsoleKey.F11; + } else { + key = ConsoleKey.Delete; + } + break; + case '4': + key = ConsoleKey.F12; + break; + case '5': + if (length == 5) { + key = ConsoleKey.F5; + } else { + key = ConsoleKey.PageUp; + } + break; + case '6': + key = ConsoleKey.PageDown; + break; + case '7': + key = ConsoleKey.F6; + break; + case '8': + key = ConsoleKey.F7; + break; + case '9': + key = ConsoleKey.F8; + break; + default: + key = 0; + break; + } + + return key; + } + public enum EventType { Key = 1, Mouse = 2, WindowSize = 3, - WindowPosition = 4, - RequestResponse = 5 + WindowPosition = 4 } [Flags] @@ -545,7 +1115,7 @@ namespace Terminal.Gui { Button2Released = 0x40, Button2Clicked = 0x80, Button2DoubleClicked = 0x100, - Button2TripleClicked = 0x200, + Button2TrippleClicked = 0x200, Button3Pressed = 0x400, Button3Released = 0x800, Button3Clicked = 0x1000, @@ -564,7 +1134,7 @@ namespace Terminal.Gui { ButtonCtrl = 0x2000000, ButtonAlt = 0x4000000, ReportMousePosition = 0x8000000, - AllEvents = -1 + AllEvents = Button1Pressed | Button1Released | Button1Clicked | Button1DoubleClicked | Button1TripleClicked | Button2Pressed | Button2Released | Button2Clicked | Button2DoubleClicked | Button2TrippleClicked | Button3Pressed | Button3Released | Button3Clicked | Button3DoubleClicked | Button3TripleClicked | ButtonWheeledUp | ButtonWheeledDown | ButtonWheeledLeft | ButtonWheeledRight | Button4Pressed | Button4Released | Button4Clicked | Button4DoubleClicked | Button4TripleClicked | ReportMousePosition } public struct MouseEvent { @@ -582,17 +1152,12 @@ namespace Terminal.Gui { public Point CursorPosition; } - public struct RequestResponseEvent { - public (string c1Control, string code, string [] values, string terminating) ResultTuple; - } - public struct InputResult { public EventType EventType; public ConsoleKeyInfo ConsoleKeyInfo; public MouseEvent MouseEvent; public WindowSizeEvent WindowSizeEvent; public WindowPositionEvent WindowPositionEvent; - public RequestResponseEvent RequestResponseEvent; } } @@ -620,19 +1185,14 @@ namespace Terminal.Gui { public override int Rows => rows; public override int Left => left; public override int Top => top; - public override bool EnableConsoleScrolling { get; set; } - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] - public override bool HeightAsBuffer { - get => EnableConsoleScrolling; - set => EnableConsoleScrolling = value; - } + public override bool HeightAsBuffer { get; set; } public NetWinVTConsole NetWinConsole { get; } public bool IsWinPlatform { get; } public override IClipboard Clipboard { get; } public override int [,,] Contents => contents; - int largestBufferHeight; + int largestWindowHeight; public NetDriver () { @@ -641,6 +1201,8 @@ namespace Terminal.Gui { IsWinPlatform = true; NetWinConsole = new NetWinVTConsole (); } + //largestWindowHeight = Math.Max (Console.BufferHeight, largestWindowHeight); + largestWindowHeight = Console.BufferHeight; if (IsWinPlatform) { Clipboard = new WindowsClipboard (); } else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) { @@ -721,7 +1283,7 @@ namespace Terminal.Gui { if (runeWidth < 0 || runeWidth > 0) { ccol++; } - + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -730,6 +1292,11 @@ namespace Terminal.Gui { ccol++; } + //if (ccol == Cols) { + // ccol = 0; + // if (crow + 1 < Rows) + // crow++; + //} if (sync) { UpdateScreen (); } @@ -743,22 +1310,25 @@ namespace Terminal.Gui { public override void End () { - mainLoop.netEvents.StopTasks (); - if (IsWinPlatform) { NetWinConsole.Cleanup (); } StopReportingMouseMoves (); Console.ResetColor (); - - //Disable alternative screen buffer. - Console.Out.Write ("\x1b[?1049l"); - + Clear (); //Set cursor key to cursor. Console.Out.Write ("\x1b[?25h"); + Console.Out.Flush (); + } - Console.Out.Close (); + void Clear () + { + if (Rows > 0) { + Console.Clear (); + Console.Out.Write ("\x1b[3J"); + //Console.Out.Write ("\x1b[?25l"); + } } public override Attribute MakeColor (Color foreground, Color background) @@ -780,25 +1350,14 @@ namespace Terminal.Gui { { TerminalResized = terminalResized; - //Enable alternative screen buffer. - Console.Out.Write ("\x1b[?1049h"); - //Set cursor key to application. Console.Out.Write ("\x1b[?25l"); + Console.Out.Flush (); Console.TreatControlCAsInput = true; - if (EnableConsoleScrolling) { - largestBufferHeight = Console.BufferHeight; - } else { - largestBufferHeight = Console.WindowHeight; - } - cols = Console.WindowWidth; - rows = largestBufferHeight; - - CurrentAttribute = MakeColor (Color.White, Color.Black); - InitalizeColorSchemes (); + rows = Console.WindowHeight; CurrentAttribute = MakeColor (Color.White, Color.Black); InitalizeColorSchemes (); @@ -807,64 +1366,55 @@ namespace Terminal.Gui { UpdateOffScreen (); StartReportingMouseMoves (); + + + Clear (); } public override void ResizeScreen () { - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { if (Console.WindowHeight > 0) { - // Not supported on Unix. - if (IsWinPlatform) { - // Can raise an exception while is still resizing. - try { + // Can raise an exception while is still resizing. + try { + // Not supported on Unix. + if (IsWinPlatform) { #pragma warning disable CA1416 Console.CursorTop = 0; Console.CursorLeft = 0; Console.WindowTop = 0; Console.WindowLeft = 0; - if (Console.WindowHeight > Rows) { - Console.SetWindowSize (Cols, Rows); - } Console.SetBufferSize (Cols, Rows); #pragma warning restore CA1416 - } catch (System.IO.IOException) { - setClip (); - } catch (ArgumentOutOfRangeException) { - setClip (); + } else { + //Console.Out.Write ($"\x1b[8;{Console.WindowHeight};{Console.WindowWidth}t"); + Console.Out.Write ($"\x1b[0;0" + + $";{Rows};{Cols}w"); } - } else { - Console.Out.Write ($"\x1b[8;{Rows};{Cols}t"); + } catch (System.IO.IOException) { + return; + } catch (ArgumentOutOfRangeException) { + return; } } } else { - if (IsWinPlatform) { - if (Console.WindowHeight > 0) { - // Can raise an exception while is still resizing. - try { + if (IsWinPlatform && Console.WindowHeight > 0) { + // Can raise an exception while is still resizing. + try { #pragma warning disable CA1416 - Console.CursorTop = 0; - Console.CursorLeft = 0; - if (Console.WindowHeight > Rows) { - Console.SetWindowSize (Cols, Rows); - } - Console.SetBufferSize (Cols, Rows); + Console.WindowTop = Math.Max (Math.Min (top, Rows - Console.WindowHeight), 0); #pragma warning restore CA1416 - } catch (System.IO.IOException) { - setClip (); - } catch (ArgumentOutOfRangeException) { - setClip (); - } + } catch (Exception) { + return; } } else { - Console.Out.Write ($"\x1b[30;{Rows};{Cols}t"); + Console.Out.Write ($"\x1b[{top};{Console.WindowLeft}" + + $";{Rows};{Cols}w"); } } - setClip (); - - void setClip () - { - Clip = new Rect (0, 0, Cols, Rows); - } + Clip = new Rect (0, 0, Cols, Rows); + Console.Out.Write ("\x1b[3J"); + Console.Out.Flush (); } public override void UpdateOffScreen () @@ -898,43 +1448,42 @@ namespace Terminal.Gui { UpdateCursor (); } + int redrawAttr = -1; + public override void UpdateScreen () { - if (winChanging || Console.WindowHeight < 1 || contents.Length != Rows * Cols * 3 - || (!EnableConsoleScrolling && Rows != Console.WindowHeight) - || (EnableConsoleScrolling && Rows != largestBufferHeight)) { + if (Console.WindowHeight == 0 || contents.Length != Rows * Cols * 3 + || (!HeightAsBuffer && Rows != Console.WindowHeight) + || (HeightAsBuffer && Rows != largestWindowHeight)) { return; } - int top = 0; - int left = 0; - int rows = Rows; + int top = Top; + int left = Left; + int rows = Math.Min (Console.WindowHeight + top, Rows); int cols = Cols; System.Text.StringBuilder output = new System.Text.StringBuilder (); - int redrawAttr = -1; var lastCol = -1; Console.CursorVisible = false; - for (int row = top; row < rows; row++) { - if (Console.WindowHeight < 1) { - return; - } if (!dirtyLine [row]) { continue; } - if (!SetCursorPosition (0, row)) { - return; - } dirtyLine [row] = false; output.Clear (); for (int col = left; col < cols; col++) { + if (Console.WindowHeight > 0 && !SetCursorPosition (col, row)) { + return; + } lastCol = -1; var outputWidth = 0; for (; col < cols; col++) { if (contents [row, col, 2] == 0) { if (output.Length > 0) { - SetCursorPosition (lastCol, row); + //Console.CursorLeft = lastCol; + //Console.CursorTop = row; + SetVirtualCursorPosition (lastCol, row); Console.Write (output); output.Clear (); lastCol += outputWidth; @@ -952,7 +1501,6 @@ namespace Terminal.Gui { var attr = contents [row, col, 1]; if (attr != redrawAttr) { - redrawAttr = attr; output.Append (WriteAttributes (attr)); } outputWidth++; @@ -967,16 +1515,18 @@ namespace Terminal.Gui { } } if (output.Length > 0) { - SetCursorPosition (lastCol, row); + //Console.CursorLeft = lastCol; + //Console.CursorTop = row; + SetVirtualCursorPosition (lastCol, row); Console.Write (output); } } - SetCursorPosition (0, 0); } - void SetVirtualCursorPosition (int col, int row) + void SetVirtualCursorPosition (int lastCol, int row) { - Console.Out.Write ($"\x1b[{row + 1};{col + 1}H"); + Console.Out.Write ($"\x1b[{row + 1};{lastCol + 1}H"); + Console.Out.Flush (); } System.Text.StringBuilder WriteAttributes (int attr) @@ -986,9 +1536,10 @@ namespace Terminal.Gui { int fg = 0; System.Text.StringBuilder sb = new System.Text.StringBuilder (); + redrawAttr = attr; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains (attr & 0xffff)) { bg = MapColors ((ConsoleColor)(attr & 0xffff), false); } @@ -1041,80 +1592,42 @@ namespace Terminal.Gui { bool SetCursorPosition (int col, int row) { - if (IsWinPlatform) { - // Could happens that the windows is still resizing and the col is bigger than Console.WindowWidth. - try { - Console.SetCursorPosition (col, row); - return true; - } catch (Exception) { - return false; - } - } else { - SetVirtualCursorPosition (col, row); + // Could happens that the windows is still resizing and the col is bigger than Console.WindowWidth. + try { + Console.SetCursorPosition (col, row); return true; + } catch (Exception) { + return false; } } - private void SetWindowPosition (int col, int row) - { - if (IsWinPlatform && EnableConsoleScrolling) { - var winTop = Math.Max (Rows - Console.WindowHeight - row, 0); - winTop = Math.Min (winTop, Rows - Console.WindowHeight + 1); - winTop = Math.Max (winTop, 0); - if (winTop != Console.WindowTop) { - try { - if (!EnsureBufferSize ()) { - return; - } -#pragma warning disable CA1416 - Console.SetWindowPosition (col, winTop); -#pragma warning restore CA1416 - } catch (System.IO.IOException) { - - } catch (System.ArgumentOutOfRangeException) { } - } - } - top = Console.WindowTop; - left = Console.WindowLeft; - } - - private bool EnsureBufferSize () - { -#pragma warning disable CA1416 - if (IsWinPlatform && Console.BufferHeight < Rows) { - try { - Console.SetBufferSize (Console.WindowWidth, Rows); - } catch (Exception) { - return false; - } - } -#pragma warning restore CA1416 - return true; - } - private CursorVisibility? savedCursorVisibility; public override void UpdateCursor () { - EnsureCursorVisibility (); - //Debug.WriteLine ($"Before - CursorTop: {Console.CursorTop};CursorLeft: {Console.CursorLeft}"); + if (!EnsureCursorVisibility ()) + return; - if (ccol >= 0 && ccol < Cols && crow >= 0 && crow < Rows) { - SetCursorPosition (ccol, crow); - SetWindowPosition (0, crow); + // Prevents the exception of size changing during resizing. + try { + if (ccol >= 0 && ccol < Console.BufferWidth && crow >= 0 && crow < Console.BufferHeight) { + Console.SetCursorPosition (ccol, crow); + } + } catch (System.IO.IOException) { + } catch (ArgumentOutOfRangeException) { } - //Debug.WriteLine ($"WindowTop: {Console.WindowTop};WindowLeft: {Console.WindowLeft}"); - //Debug.WriteLine ($"After - CursorTop: {Console.CursorTop};CursorLeft: {Console.CursorLeft}"); } public override void StartReportingMouseMoves () { - Console.Out.Write (EscSeqUtils.EnableMouseEvents); + Console.Out.Write ("\x1b[?1003h\x1b[?1015h\x1b[?1006h"); + Console.Out.Flush (); } public override void StopReportingMouseMoves () { - Console.Out.Write (EscSeqUtils.DisableMouseEvents); + Console.Out.Write ("\x1b[?1003l\x1b[?1015l\x1b[?1006l"); + Console.Out.Flush (); } public override void Suspend () @@ -1269,7 +1782,6 @@ namespace Terminal.Gui { Action keyDownHandler; Action keyUpHandler; Action mouseHandler; - NetMainLoop mainLoop; public override void PrepareToRun (MainLoop mainLoop, Action keyHandler, Action keyDownHandler, Action keyUpHandler, Action mouseHandler) { @@ -1278,14 +1790,10 @@ namespace Terminal.Gui { this.keyUpHandler = keyUpHandler; this.mouseHandler = mouseHandler; - var mLoop = this.mainLoop = mainLoop.Driver as NetMainLoop; + var mLoop = mainLoop.Driver as NetMainLoop; // Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will be simulated to be called. mLoop.ProcessInput = (e) => ProcessInput (e); - - // Check if terminal supports requests - this.mainLoop.netEvents.EscSeqReqProc.Add ("c"); - Console.Out.Write ("\x1b[0c"); } void ProcessInput (NetEvents.InputResult inputEvent) @@ -1314,31 +1822,38 @@ namespace Terminal.Gui { mouseHandler (ToDriverMouse (inputEvent.MouseEvent)); break; case NetEvents.EventType.WindowSize: - ChangeWin (inputEvent.WindowSizeEvent.Size); + ChangeWin (); break; - case NetEvents.EventType.RequestResponse: - Application.Top.Data = inputEvent.RequestResponseEvent.ResultTuple; + case NetEvents.EventType.WindowPosition: + var newTop = inputEvent.WindowPositionEvent.Top; + var newLeft = inputEvent.WindowPositionEvent.Left; + if (HeightAsBuffer && (top != newTop || left != newLeft)) { + top = newTop; + left = newLeft; + Refresh (); + } break; } } - volatile bool winChanging; - - void ChangeWin (Size size) + void ChangeWin () { - winChanging = true; - if (!EnableConsoleScrolling) { - largestBufferHeight = Math.Max (size.Height, 0); + const int Min_WindowWidth = 14; + Size size = new Size (); + if (!HeightAsBuffer) { + size = new Size (Math.Max (Min_WindowWidth, Console.WindowWidth), + Console.WindowHeight); + top = 0; + left = 0; } else { - largestBufferHeight = Math.Max (size.Height, largestBufferHeight); + //largestWindowHeight = Math.Max (Console.BufferHeight, largestWindowHeight); + largestWindowHeight = Console.BufferHeight; + size = new Size (Console.BufferWidth, largestWindowHeight); } - top = 0; - left = 0; cols = size.Width; - rows = largestBufferHeight; + rows = size.Height; ResizeScreen (); UpdateOffScreen (); - winChanging = false; TerminalResized?.Invoke (); } @@ -1375,7 +1890,7 @@ namespace Terminal.Gui { if ((me.ButtonState & NetEvents.MouseButtonState.Button2DoubleClicked) != 0) { mouseFlag |= MouseFlags.Button2DoubleClicked; } - if ((me.ButtonState & NetEvents.MouseButtonState.Button2TripleClicked) != 0) { + if ((me.ButtonState & NetEvents.MouseButtonState.Button2TrippleClicked) != 0) { mouseFlag |= MouseFlags.Button2TripleClicked; } if ((me.ButtonState & NetEvents.MouseButtonState.Button3Pressed) != 0) { @@ -1486,8 +2001,8 @@ namespace Terminal.Gui { foreground = default; background = default; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains (value & 0xffff)) { hasColor = true; background = (Color)(ConsoleColor)(value & 0xffff); @@ -1538,7 +2053,7 @@ namespace Terminal.Gui { Queue inputResult = new Queue (); MainLoop mainLoop; CancellationTokenSource tokenSource = new CancellationTokenSource (); - internal NetEvents netEvents; + NetEvents netEvents; /// /// Invoked when a Key is pressed. diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index a2f87af0e..d7b72fe37 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1,6 +1,30 @@ // // WindowsDriver.cs: Windows specific driver // +// Authors: +// Miguel de Icaza (miguel@gnome.org) +// Nick Van Dyck (vandyck.nick@outlook.com) +// +// Copyright (c) 2018 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// using NStack; using System; using System.Collections.Generic; @@ -622,7 +646,7 @@ namespace Terminal.Gui { } } -#if false // Not needed on the constructor. Perhaps could be used on resizing. To study. +#if false // Not needed on the constructor. Perhaps could be used on resizing. To study. [DllImport ("kernel32.dll", ExactSpelling = true)] static extern IntPtr GetConsoleWindow (); @@ -715,12 +739,7 @@ namespace Terminal.Gui { public override int Rows => rows; public override int Left => left; public override int Top => top; - public override bool EnableConsoleScrolling { get; set; } - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] - public override bool HeightAsBuffer { - get => EnableConsoleScrolling; - set => EnableConsoleScrolling = value; - } + public override bool HeightAsBuffer { get; set; } public override IClipboard Clipboard => clipboard; public override int [,,] Contents => contents; @@ -755,7 +774,7 @@ namespace Terminal.Gui { private void ChangeWin (Size e) { - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { var w = e.Width; if (w == cols - 3 && e.Height < rows) { w += 3; @@ -896,12 +915,8 @@ namespace Terminal.Gui { left = pos.X; top = pos.Y; cols = inputEvent.WindowBufferSizeEvent.size.X; - if (EnableConsoleScrolling) { - rows = Math.Max (inputEvent.WindowBufferSizeEvent.size.Y, rows); - } else { - rows = inputEvent.WindowBufferSizeEvent.size.Y; - } - //System.Diagnostics.Debug.WriteLine ($"{EnableConsoleScrolling},{cols},{rows}"); + rows = inputEvent.WindowBufferSizeEvent.size.Y; + //System.Diagnostics.Debug.WriteLine ($"{HeightAsBuffer},{cols},{rows}"); ResizeScreen (); UpdateOffScreen (); TerminalResized?.Invoke (); @@ -1444,19 +1459,6 @@ namespace Terminal.Gui { TerminalResized = terminalResized; try { - // Needed for Windows Terminal - // ESC [ ? 1047 h Activate xterm alternative buffer (no backscroll) - // ESC [ ? 1047 l Restore xterm working buffer (with backscroll) - // ESC [ ? 1048 h Save cursor position - // ESC [ ? 1048 l Restore cursor position - // ESC [ ? 1049 h Save cursor position and activate xterm alternative buffer (no backscroll) - // ESC [ ? 1049 l Restore cursor position and restore xterm working buffer (with backscroll) - // Per Issue #2264 using the alterantive screen buffer is required for Windows Terminal to not - // wipe out the backscroll buffer when the application exits. - Console.Out.Write ("\x1b[?1047h"); - - // Console.Out.Flush () is not needed. See https://stackoverflow.com/a/20450486/297526 - var winSize = WinConsole.GetConsoleOutputWindow (out Point pos); cols = winSize.Width; rows = winSize.Height; @@ -1465,9 +1467,6 @@ namespace Terminal.Gui { CurrentAttribute = MakeColor (Color.White, Color.Black); InitalizeColorSchemes (); - CurrentAttribute = MakeColor (Color.White, Color.Black); - InitalizeColorSchemes (); - ResizeScreen (); UpdateOffScreen (); } catch (Win32Exception e) { @@ -1486,15 +1485,8 @@ namespace Terminal.Gui { Right = (short)Cols }; WinConsole.ForceRefreshCursorVisibility (); - if (!EnableConsoleScrolling) { - // ANSI ESC "[xJ" Clears part of the screen. - // If n is 0 (or missing), clear from cursor to end of screen. - // If n is 1, clear from cursor to beginning of the screen. - // If n is 2, clear entire screen (and moves cursor to upper left on DOS ANSI.SYS). - // If n is 3, clear entire screen and delete all lines saved in the scrollback buffer - // DO NOT USE 3J - even with the alternate screen buffer, it clears the entire scrollback buffer - Console.Out.Write ("\x1b[3J"); - } + Console.Out.Write ("\x1b[3J"); + Console.Out.Flush (); } public override void UpdateOffScreen () @@ -1661,7 +1653,7 @@ namespace Terminal.Gui { if (damageRegion.Left == -1) return; - if (!EnableConsoleScrolling) { + if (!HeightAsBuffer) { var windowSize = WinConsole.GetConsoleBufferWindow (out _); if (!windowSize.IsEmpty && (windowSize.Width != Cols || windowSize.Height != Rows)) return; @@ -1708,18 +1700,6 @@ namespace Terminal.Gui { { WinConsole.Cleanup (); WinConsole = null; - - // Needed for Windows Terminal - // Clear the alternative screen buffer from the cursor to the - // end of the screen. - // Note, [3J causes Windows Terminal to wipe out the entire NON ALTERNATIVE - // backbuffer! So we need to use [0J instead. - Console.Out.Write ("\x1b[0J"); - - // Disable alternative screen buffer. - Console.Out.Write ("\x1b[?1047l"); - - // Console.Out.Flush () is not needed. See https://stackoverflow.com/a/20450486/297526 } /// @@ -1800,8 +1780,8 @@ namespace Terminal.Gui { foreground = default; background = default; IEnumerable values = Enum.GetValues (typeof (ConsoleColor)) - .OfType () - .Select (s => (int)s); + .OfType () + .Select (s => (int)s); if (values.Contains ((value >> 4) & 0xffff)) { hasColor = true; background = (Color)(ConsoleColor)((value >> 4) & 0xffff); @@ -1917,9 +1897,9 @@ namespace Terminal.Gui { { while (true) { Thread.Sleep (100); - if (!consoleDriver.EnableConsoleScrolling) { + if (!consoleDriver.HeightAsBuffer) { windowSize = winConsole.GetConsoleBufferWindow (out _); - //System.Diagnostics.Debug.WriteLine ($"{consoleDriver.EnableConsoleScrolling},{windowSize.Width},{windowSize.Height}"); + //System.Diagnostics.Debug.WriteLine ($"{consoleDriver.HeightAsBuffer},{windowSize.Width},{windowSize.Height}"); if (windowSize != Size.Empty && windowSize.Width != consoleDriver.Cols || windowSize.Height != consoleDriver.Rows) { return; diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index e48166a9b..9fb6ecbc9 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -114,36 +114,28 @@ namespace Terminal.Gui { /// public static View WantContinuousButtonPressedView { get; private set; } - private static bool? _enableConsoleScrolling; + private static bool? _heightAsBuffer; /// - /// The current used in the terminal. + /// The current used in the terminal. /// /// [SerializableConfigurationProperty (Scope = typeof(SettingsScope))] public static bool HeightAsBuffer { get { if (Driver == null) { - return _enableConsoleScrolling.HasValue && _enableConsoleScrolling.Value; + return _heightAsBuffer.HasValue && _heightAsBuffer.Value; } - return Driver.EnableConsoleScrolling; + return Driver.HeightAsBuffer; } set { - _enableConsoleScrolling = value; + _heightAsBuffer = value; if (Driver == null) { return; } - Driver.EnableConsoleScrolling = value; - } - } - /// - /// This API is deprecated; use instead. - /// - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] - public static bool HeightAsBuffer { - get => EnableConsoleScrolling; - set => EnableConsoleScrolling = value; + Driver.HeightAsBuffer = _heightAsBuffer.Value; + } } static Key alternateForwardKey = Key.PageDown | Key.CtrlMask; @@ -165,7 +157,7 @@ namespace Terminal.Gui { static void OnAlternateForwardKeyChanged (Key oldKey) { - foreach (var top in toplevels.ToArray ()) { + foreach (var top in toplevels.ToArray()) { top.OnAlternateForwardKeyChanged (oldKey); } } @@ -189,7 +181,7 @@ namespace Terminal.Gui { static void OnAlternateBackwardKeyChanged (Key oldKey) { - foreach (var top in toplevels.ToArray ()) { + foreach (var top in toplevels.ToArray()) { top.OnAlternateBackwardKeyChanged (oldKey); } } @@ -221,7 +213,7 @@ namespace Terminal.Gui { static void OnQuitKeyChanged (Key oldKey) { // Duplicate the list so if it changes during enumeration we're safe - foreach (var top in toplevels.ToArray ()) { + foreach (var top in toplevels.ToArray()) { top.OnQuitKeyChanged (oldKey); } } @@ -453,7 +445,7 @@ namespace Terminal.Gui { MainLoop = new MainLoop (mainLoopDriver); try { - Driver.EnableConsoleScrolling = EnableConsoleScrolling; + Driver.HeightAsBuffer = HeightAsBuffer; Driver.Init (TerminalResized); } catch (InvalidOperationException ex) { // This is a case where the driver is unable to initialize the console. @@ -1129,7 +1121,6 @@ namespace Terminal.Gui { NotifyStopRunState = null; _initialized = false; mouseGrabView = null; - _enableConsoleScrolling = false; // Reset synchronization context to allow the user to run async/await, // as the main loop has been ended, the synchronization context from diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index 9b945bfde..8040afdeb 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -331,7 +331,6 @@ namespace Terminal.Gui { private Point effect3DOffset = new Point (1, 1); private Attribute? effect3DBrush; private ustring title = ustring.Empty; - private View child; /// /// Specifies the for a view. @@ -448,6 +447,7 @@ namespace Terminal.Gui { /// /// Gets or sets the single child element of a . /// + [JsonIgnore] public View Child { get; set; } /// @@ -611,7 +611,7 @@ namespace Terminal.Gui { Child.Clear (borderRect); } - driver.SetAttribute (new Attribute (BorderBrush, Background)); + driver.SetAttribute (savedAttribute); // Draw margin frame if (DrawMarginFrame) { @@ -635,7 +635,6 @@ namespace Terminal.Gui { driver.DrawWindowFrame (borderRect, 1, 1, 1, 1, BorderStyle != BorderStyle.None, fill: true, this); } } - driver.SetAttribute (savedAttribute); } private void DrawChildBorder (Rect frame, bool fill = true) @@ -732,7 +731,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (new Attribute (BorderBrush, Background)); + driver.SetAttribute (savedAttribute); // Draw the MarginFrame if (DrawMarginFrame) { @@ -906,7 +905,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (new Attribute (BorderBrush, Background)); + driver.SetAttribute (savedAttribute); // Draw the MarginFrame if (DrawMarginFrame) { @@ -988,9 +987,9 @@ namespace Terminal.Gui { { var driver = Application.Driver; if (DrawMarginFrame) { - driver.SetAttribute (new Attribute (BorderBrush, Background)); - if (view.HasFocus) - driver.SetAttribute (new Attribute (Child.ColorScheme.HotNormal.Foreground, Background)); + driver.SetAttribute (Child.GetNormalColor ()); + if (Child.HasFocus) + driver.SetAttribute (Child.ColorScheme.HotNormal); var padding = view.Border.GetSumThickness (); Rect scrRect; if (view == Child) { @@ -999,7 +998,7 @@ namespace Terminal.Gui { driver.DrawWindowTitle (scrRect, Title, 0, 0, 0, 0); } else { scrRect = view.ViewToScreen (new Rect (0, 0, view.Frame.Width, view.Frame.Height)); - driver.DrawWindowTitle (scrRect, Parent.Border.Title, + driver.DrawWindowTitle (scrRect, Title, padding.Left, padding.Top, padding.Right, padding.Bottom); } } @@ -1015,9 +1014,9 @@ namespace Terminal.Gui { { var driver = Application.Driver; if (DrawMarginFrame) { - driver.SetAttribute (new Attribute (BorderBrush, Background)); + driver.SetAttribute (view.GetNormalColor ()); if (view.HasFocus) { - driver.SetAttribute (new Attribute (view.ColorScheme.HotNormal.Foreground, Background)); + driver.SetAttribute (view.ColorScheme.HotNormal); } var padding = Parent.Border.GetSumThickness (); var scrRect = Parent.ViewToScreen (new Rect (0, 0, rect.Width, rect.Height)); diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 8b2b535c1..e0527a6ce 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -89,7 +89,7 @@ namespace Terminal.Gui { } /// - /// Indicates the RGB for true colors. + /// /// public class TrueColor { /// @@ -119,7 +119,7 @@ namespace Terminal.Gui { } /// - /// Converts true color to console color. + /// /// /// public Color ToConsoleColor () @@ -504,7 +504,7 @@ namespace Terminal.Gui { public bool Equals (string x, string y) { if (x != null && y != null) { - return string.Equals (x, y, StringComparison.InvariantCultureIgnoreCase); + return x.ToLowerInvariant () == y.ToLowerInvariant (); } return false; } @@ -659,7 +659,72 @@ namespace Terminal.Gui { /// Works under Xterm-like terminal otherwise this is equivalent to BoxFix = 0x02020164, } - + + ///// + ///// Special characters that can be drawn with + ///// + //public enum SpecialChar { + // /// + // /// Horizontal line character. + // /// + // HLine, + + // /// + // /// Vertical line character. + // /// + // VLine, + + // /// + // /// Stipple pattern + // /// + // Stipple, + + // /// + // /// Diamond character + // /// + // Diamond, + + // /// + // /// Upper left corner + // /// + // ULCorner, + + // /// + // /// Lower left corner + // /// + // LLCorner, + + // /// + // /// Upper right corner + // /// + // URCorner, + + // /// + // /// Lower right corner + // /// + // LRCorner, + + // /// + // /// Left tee + // /// + // LeftTee, + + // /// + // /// Right tee + // /// + // RightTee, + + // /// + // /// Top tee + // /// + // TopTee, + + // /// + // /// The bottom tee. + // /// + // BottomTee, + //} + /// /// ConsoleDriver is an abstract class that defines the requirements for a console driver. /// There are currently three implementations: (for Unix and Mac), , and that uses the .NET Console API. @@ -696,27 +761,9 @@ namespace Terminal.Gui { public abstract IClipboard Clipboard { get; } /// - /// - /// If (the default) the height of the Terminal.Gui application () - /// tracks to the height of the visible console view when the console is resized. In this case - /// scrolling in the console will be disabled and all will remain visible. - /// - /// - /// If then height of the Terminal.Gui application only tracks - /// the height of the visible console view when the console is made larger (the application will only grow in height, never shrink). - /// In this case console scrolling is enabled and the contents ( high) will scroll - /// as the console scrolls. - /// + /// If false height is measured by the window height and thus no scrolling. + /// If true then height is measured by the buffer height, enabling scrolling. /// - /// - /// NOTE: This functionaliy is currently broken on Windows Terminal. - /// - public abstract bool EnableConsoleScrolling { get; set; } - - /// - /// This API is deprecated; use instead. - /// - [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] public abstract bool HeightAsBuffer { get; set; } /// diff --git a/Terminal.Gui/Core/ConsoleKeyMapping.cs b/Terminal.Gui/Core/ConsoleKeyMapping.cs index 441adac48..d7bc3d584 100644 --- a/Terminal.Gui/Core/ConsoleKeyMapping.cs +++ b/Terminal.Gui/Core/ConsoleKeyMapping.cs @@ -334,25 +334,6 @@ namespace Terminal.Gui { return (Key)consoleKey; } - /// - /// Maps a to a . - /// - /// The console key info. - /// The key. - /// The with or the - public static Key MapKeyModifiers (ConsoleKeyInfo keyInfo, Key key) - { - Key keyMod = new Key (); - if ((keyInfo.Modifiers & ConsoleModifiers.Shift) != 0) - keyMod = Key.ShiftMask; - if ((keyInfo.Modifiers & ConsoleModifiers.Control) != 0) - keyMod |= Key.CtrlMask; - if ((keyInfo.Modifiers & ConsoleModifiers.Alt) != 0) - keyMod |= Key.AltMask; - - return keyMod != Key.Null ? keyMod | key : key; - } - private static HashSet scanCodes = new HashSet { new ScanCodeMapping (1,27,0,27), // Escape new ScanCodeMapping (1,27,ConsoleModifiers.Shift,27), diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Core/Event.cs index a46bbf7e5..4203faa86 100644 --- a/Terminal.Gui/Core/Event.cs +++ b/Terminal.Gui/Core/Event.cs @@ -749,7 +749,7 @@ namespace Terminal.Gui { /// WheeledUp = unchecked((int)0x10000000), /// - /// Vertical button wheeled down. + /// Vertical button wheeled up. /// WheeledDown = unchecked((int)0x20000000), /// diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 511ce233a..2b85cfbc5 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1521,6 +1521,7 @@ namespace Terminal.Gui { Driver.SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ()); } + var boundsAdjustedForBorder = Bounds; if (!IgnoreBorderPropertyOnRedraw && Border != null) { Border.DrawContent (this); boundsAdjustedForBorder = new Rect (bounds.X + 1, bounds.Y + 1, Math.Max (0, bounds.Width - 2), Math.Max(0, bounds.Height - 2)); @@ -1547,7 +1548,7 @@ namespace Terminal.Gui { } // Invoke DrawContentEvent - OnDrawContent (bounds); + OnDrawContent (boundsAdjustedForBorder); if (subviews != null) { foreach (var view in subviews) { @@ -1573,7 +1574,7 @@ namespace Terminal.Gui { } // Invoke DrawContentCompleteEvent - OnDrawContentComplete (bounds); + OnDrawContentComplete (boundsAdjustedForBorder); ClearLayoutNeeded (); ClearNeedsDisplay (); @@ -2219,51 +2220,35 @@ namespace Terminal.Gui { newDimension = dim.Anchor (superviewDimension); newDimension = AutoSize && autosizeDimension > newDimension ? autosizeDimension : newDimension; } - actY = y.Anchor (hostFrame.Height - actH); - } else { - actY = y?.Anchor (hostFrame.Height) ?? 0; + newLocation = pos.Anchor (superviewDimension - newDimension); + break; - actH = Math.Max (CalculateActualHight (height, hostFrame, actY, s), 0); - } + case Pos.PosCombine: + var combine = pos as Pos.PosCombine; + int left, right; + (left, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.left, dim, autosizeDimension); + (right, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.right, dim, autosizeDimension); + if (combine.add) { + newLocation = left + right; + } else { + newLocation = left - right; + } + newDimension = Math.Max (CalculateNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0); + break; - var r = new Rect (actX, actY, actW, actH); - if (Frame != r) { - Frame = r; - if (!SetMinWidthHeight ()) - TextFormatter.Size = GetBoundsTextFormatterSize (); - } - } - - private int CalculateActualWidth (Dim width, Rect hostFrame, int actX, Size s) - { - int actW; - switch (width) { - case null: - actW = AutoSize ? s.Width : hostFrame.Width; - break; - case Dim.DimCombine combine: - int leftActW = CalculateActualWidth (combine.left, hostFrame, actX, s); - int rightActW = CalculateActualWidth (combine.right, hostFrame, actX, s); - if (combine.add) { - actW = leftActW + rightActW; - } else { - actW = leftActW - rightActW; + case Pos.PosAbsolute: + case Pos.PosAnchorEnd: + case Pos.PosFactor: + case Pos.PosFunc: + case Pos.PosView: + default: + newLocation = pos?.Anchor (superviewDimension) ?? 0; + newDimension = Math.Max (CalculateNewDimension (dim, newLocation, superviewDimension, autosizeDimension), 0); + break; } - actW = AutoSize && s.Width > actW ? s.Width : actW; - break; - case Dim.DimFactor factor when !factor.IsFromRemaining (): - actW = width.Anchor (hostFrame.Width); - actW = AutoSize && s.Width > actW ? s.Width : actW; - break; - default: - actW = Math.Max (width.Anchor (hostFrame.Width - actX), 0); - actW = AutoSize && s.Width > actW ? s.Width : actW; - break; + return (newLocation, newDimension); } - return actW; - } - // Recursively calculates the new dimension (width or height) of the given Dim given: // the current location (x or y) // the current dimennsion (width or height) @@ -2300,51 +2285,20 @@ namespace Terminal.Gui { return newDimension; } - // https://en.wikipedia.org/wiki/Topological_sorting - List TopologicalSort (IEnumerable nodes, ICollection<(View From, View To)> edges) - { - var result = new List (); - // Set of all nodes with no incoming edges - var noEdgeNodes = new HashSet (nodes.Where (n => edges.All (e => !e.To.Equals (n)))); + // horiztonal + (newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, Width, autosize.Width); - while (noEdgeNodes.Any ()) { - // remove a node n from S - var n = noEdgeNodes.First (); - noEdgeNodes.Remove (n); + // vertical + (newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, Height, autosize.Height); - // add n to tail of L - if (n != this?.SuperView) - result.Add (n); - - // for each node m with an edge e from n to m do - foreach (var e in edges.Where (e => e.From.Equals (n)).ToArray ()) { - var m = e.To; - - // remove edge e from the graph - edges.Remove (e); - - // if m has no other incoming edges then - if (edges.All (me => !me.To.Equals (m)) && m != this?.SuperView) { - // insert m into S - noEdgeNodes.Add (m); - } + var r = new Rect (newX, newY, newW, newH); + if (Frame != r) { + Frame = r; + if (!SetMinWidthHeight ()) { + TextFormatter.Size = GetBoundsTextFormatterSize (); } } - - if (edges.Any ()) { - (var from, var to) = edges.First (); - if (from != Application.Top) { - if (!ReferenceEquals (from, to)) { - throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {this}?"); - } else { - throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + this); - } - } - } - - // return L (a topologically sorted order) - return result; } /// @@ -2436,21 +2390,82 @@ namespace Terminal.Gui { } } - void CollectAll (View from, ref HashSet nNodes, ref HashSet<(View, View)> nEdges) - { - foreach (var v in from.InternalSubviews) { - nNodes.Add (v); - if (v.layoutStyle != LayoutStyle.Computed) { - continue; + internal void CollectAll (View from, ref HashSet nNodes, ref HashSet<(View, View)> nEdges) + { + foreach (var v in from.InternalSubviews) { + nNodes.Add (v); + if (v.layoutStyle != LayoutStyle.Computed) { + continue; + } + CollectPos (v.X, v, ref nNodes, ref nEdges); + CollectPos (v.Y, v, ref nNodes, ref nEdges); + CollectDim (v.Width, v, ref nNodes, ref nEdges); + CollectDim (v.Height, v, ref nNodes, ref nEdges); + } + } + + // https://en.wikipedia.org/wiki/Topological_sorting + internal static List TopologicalSort (View superView, IEnumerable nodes, ICollection<(View From, View To)> edges) + { + var result = new List (); + + // Set of all nodes with no incoming edges + var noEdgeNodes = new HashSet (nodes.Where (n => edges.All (e => !e.To.Equals (n)))); + + while (noEdgeNodes.Any ()) { + // remove a node n from S + var n = noEdgeNodes.First (); + noEdgeNodes.Remove (n); + + // add n to tail of L + if (n != superView) + result.Add (n); + + // for each node m with an edge e from n to m do + foreach (var e in edges.Where (e => e.From.Equals (n)).ToArray ()) { + var m = e.To; + + // remove edge e from the graph + edges.Remove (e); + + // if m has no other incoming edges then + if (edges.All (me => !me.To.Equals (m)) && m != superView) { + // insert m into S + noEdgeNodes.Add (m); } - CollectPos (v.X, v, ref nNodes, ref nEdges); - CollectPos (v.Y, v, ref nNodes, ref nEdges); - CollectDim (v.Width, v, ref nNodes, ref nEdges); - CollectDim (v.Height, v, ref nNodes, ref nEdges); } } - CollectAll (this, ref nodes, ref edges); + if (edges.Any ()) { + (var from, var to) = edges.First (); + if (from != Application.Top) { + if (!ReferenceEquals (from, to)) { + throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {superView}?"); + } else { + throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + superView); + } + } + } + // return L (a topologically sorted order) + return result; + } // TopologicalSort + + + /// + /// Invoked when a view starts executing or when the dimensions of the view have changed, for example in + /// response to the container view or terminal resizing. + /// + /// + /// Calls (which raises the event) before it returns. + /// + public virtual void LayoutSubviews () + { + if (!LayoutNeeded) { + return; + } + + var oldBounds = Bounds; + OnLayoutStarted (new LayoutEventArgs () { OldBounds = oldBounds }); TextFormatter.Size = GetBoundsTextFormatterSize (); diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs index d95b64d4d..ff9f3233b 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Core/Window.cs @@ -38,9 +38,6 @@ namespace Terminal.Gui { if (!OnTitleChanging (title, value)) { var old = title; title = value; - if (Border != null) { - Border.Title = title; - } OnTitleChanged (old, title); } SetNeedsDisplay (); @@ -195,13 +192,10 @@ namespace Terminal.Gui { Border = new Border () { BorderStyle = DefaultBorderStyle, Padding = new Thickness (padding), - Title = title + BorderBrush = ColorScheme.Normal.Background }; } else { Border = border; - if (ustring.IsNullOrEmpty (border.Title)) { - border.Title = title; - } } AdjustContentView (frame); } @@ -293,6 +287,9 @@ namespace Terminal.Gui { /// public override void Redraw (Rect bounds) { + var padding = Border.GetSumThickness (); + var scrRect = ViewToScreen (new Rect (0, 0, Frame.Width, Frame.Height)); + if (!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded) { Driver.SetAttribute (GetNormalColor ()); Clear (); @@ -301,6 +298,7 @@ namespace Terminal.Gui { var savedClip = contentView.ClipToBounds (); // Redraw our contentView + // DONE: smartly constrict contentView.Bounds to just be what intersects with the 'bounds' we were passed contentView.Redraw (!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded ? contentView.Bounds : bounds); Driver.Clip = savedClip; @@ -308,7 +306,14 @@ namespace Terminal.Gui { ClearNeedsDisplay (); Driver.SetAttribute (GetNormalColor ()); + //Driver.DrawWindowFrame (scrRect, padding.Left + borderLength, padding.Top + borderLength, padding.Right + borderLength, padding.Bottom + borderLength, + // Border.BorderStyle != BorderStyle.None, fill: true, Border.BorderStyle); Border.DrawContent (this, false); + if (HasFocus) + Driver.SetAttribute (ColorScheme.HotNormal); + if (Border.DrawMarginFrame) + Driver.DrawWindowTitle (scrRect, Title, padding.Left, padding.Top, padding.Right, padding.Bottom); + Driver.SetAttribute (GetNormalColor ()); } /// diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 62b2696fc..75cdb8e2a 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -60,7 +60,6 @@ - net472;netstandard2.0;net6.0 diff --git a/Terminal.Gui/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs index d25d2fb27..f6809d109 100644 --- a/Terminal.Gui/Views/FrameView.cs +++ b/Terminal.Gui/Views/FrameView.cs @@ -67,9 +67,6 @@ namespace Terminal.Gui { get => title; set { title = value; - if (Border != null) { - Border.Title = title; - } SetNeedsDisplay (); } } @@ -166,9 +163,6 @@ namespace Terminal.Gui { }; } else { Border = border; - if (ustring.IsNullOrEmpty (border.Title)) { - border.Title = title; - } } AdjustContentView (frame, views); } @@ -267,8 +261,12 @@ namespace Terminal.Gui { /// public override void Redraw (Rect bounds) { + var padding = Border.GetSumThickness (); + var scrRect = ViewToScreen (new Rect (0, 0, Frame.Width, Frame.Height)); + if (!NeedDisplay.IsEmpty) { Driver.SetAttribute (GetNormalColor ()); + //Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: true); Clear (); } @@ -276,7 +274,6 @@ namespace Terminal.Gui { contentView.Redraw (!NeedDisplay.IsEmpty ? contentView.Bounds : bounds); Driver.Clip = savedClip; - ClearLayoutNeeded (); ClearNeedsDisplay (); if (!IgnoreBorderPropertyOnRedraw) { diff --git a/Terminal.Gui/Views/TileView.cs b/Terminal.Gui/Views/TileView.cs index 3df7b276a..d5a431721 100644 --- a/Terminal.Gui/Views/TileView.cs +++ b/Terminal.Gui/Views/TileView.cs @@ -455,8 +455,10 @@ namespace Terminal.Gui { } Driver.SetAttribute (ColorScheme.Normal); - lc.Draw (this, bounds); - + foreach (var p in lc.GenerateImage (bounds)) { + this.AddRune (p.Key.X, p.Key.Y, p.Value); + } + // Redraw the lines so that focus/drag symbol renders foreach (var line in allLines) { line.DrawSplitterSymbol (); diff --git a/UICatalog/Properties/launchSettings.json b/UICatalog/Properties/launchSettings.json index e2cc967c3..80329d78d 100644 --- a/UICatalog/Properties/launchSettings.json +++ b/UICatalog/Properties/launchSettings.json @@ -3,12 +3,6 @@ "UICatalog": { "commandName": "Project" }, - "WSL : UICatalog": { - "commandName": "Executable", - "executablePath": "wsl", - "commandLineArgs": "dotnet UICatalog.dll", - "distributionName": "" - }, "UICatalog -usc": { "commandName": "Project", "commandLineArgs": "-usc" @@ -35,6 +29,10 @@ "commandName": "Project", "commandLineArgs": "WizardAsView" }, + "VkeyPacketSimulator": { + "commandName": "Project", + "commandLineArgs": "VkeyPacketSimulator" + }, "CollectionNavigatorTester": { "commandName": "Project", "commandLineArgs": "\"Search Collection Nav\"" diff --git a/UICatalog/Scenarios/BordersComparisons.cs b/UICatalog/Scenarios/BordersComparisons.cs index 46c363c12..1aac4dca5 100644 --- a/UICatalog/Scenarios/BordersComparisons.cs +++ b/UICatalog/Scenarios/BordersComparisons.cs @@ -12,10 +12,9 @@ namespace UICatalog.Scenarios { var borderStyle = BorderStyle.Double; var drawMarginFrame = false; var borderThickness = new Thickness (1, 2, 3, 4); - var borderBrush = Color.BrightMagenta; - ; + var borderBrush = Colors.Base.HotFocus.Foreground; var padding = new Thickness (1, 2, 3, 4); - var background = Color.Cyan; + var background = Colors.Base.HotNormal.Foreground; var effect3D = true; var win = new Window (new Rect (5, 5, 40, 20), "Test", 8, diff --git a/UICatalog/Scenarios/TileViewExperiment.cs b/UICatalog/Scenarios/TileViewExperiment.cs index 065aff784..6430ce9a6 100644 --- a/UICatalog/Scenarios/TileViewExperiment.cs +++ b/UICatalog/Scenarios/TileViewExperiment.cs @@ -27,7 +27,7 @@ namespace UICatalog.Scenarios { Application.Top.Add (menu); - var frame = new FrameView () { + var frame1 = new FrameView () { X = 0, Y = 1, Width = 15, //Dim.Fill (), @@ -35,16 +35,22 @@ namespace UICatalog.Scenarios { //IgnoreBorderPropertyOnRedraw = true }; - frame.Border.BorderStyle = BorderStyle.Double; + frame1.Border.BorderStyle = BorderStyle.Double; - Application.Top.Add (frame); + var frame2 = new FrameView () { + X = 0, + Y = Pos.Bottom (frame1) + 1, + Width = 15, //Dim.Fill (), + Height = 15, //Dim.Fill (), + //IgnoreBorderPropertyOnRedraw = true }; frame2.Border.BorderStyle = BorderStyle.Single; - ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler; + //ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler; Application.Top.Add (frame1); + Application.Top.Add (frame2); var view1 = new TextField () { //Title = "View 1", @@ -65,9 +71,8 @@ namespace UICatalog.Scenarios { }; frame1.Add (view1); - frame2.Add (view1); - frame.Add (view3); + //var view12splitter = new SplitterEventArgs //var view2 = new FrameView () { // Title = "View 2", @@ -106,20 +111,20 @@ namespace UICatalog.Scenarios { // Border = new Border () { BorderStyle = BorderStyle.Single } //}; - frame.Add (view4); + //frame.Add (view4); - var view5 = new FrameView () { - Title = "View 5", - Text = "View5 below View4 view4.Width/5 Double", - X = Pos.Left (view2), - Y = Pos.Bottom (view4) - 1, - Width = view4.Width, - Height = 5, - ColorScheme = Colors.ColorSchemes ["TopLevel"], - Border = new Border () { BorderStyle = BorderStyle.Double } - }; + //var view5 = new FrameView () { + // Title = "View 5", + // Text = "View5 below View4 view4.Width/5 Double", + // X = Pos.Left (view2), + // Y = Pos.Bottom (view4) - 1, + // Width = view4.Width, + // Height = 5, + // ColorScheme = Colors.ColorSchemes ["TopLevel"], + // Border = new Border () { BorderStyle = BorderStyle.Double } + //}; - frame.Add (view5); + //frame.Add (view5); } } } \ No newline at end of file diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 3ea99fbf3..161657f70 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -193,9 +193,6 @@ namespace UICatalog { // Run UI Catalog UI. When it exits, if _selectedScenario is != null then // a Scenario was selected. Otherwise, the user wants to exit UI Catalog. Application.Init (); - - Application.EnableConsoleScrolling = _enableConsoleScrolling; - Application.Run (); Application.Shutdown (); @@ -229,7 +226,7 @@ namespace UICatalog { /// public class UICatalogTopLevel : Toplevel { public MenuItem miIsMouseDisabled; - public MenuItem miEnableConsoleScrolling; + public MenuItem miHeightAsBuffer; public TileView ContentPane; public ListView CategoryListView; @@ -451,7 +448,7 @@ namespace UICatalog { return menuItems.ToArray (); } - MenuItem [] CreateEnableConsoleScrollingMenuItems () + MenuItem [] CreateHeightAsBufferMenuItems () { List menuItems = new List (); miHeightAsBuffer = new MenuItem { @@ -463,7 +460,7 @@ namespace UICatalog { miHeightAsBuffer.Checked = !miHeightAsBuffer.Checked; Application.HeightAsBuffer = (bool)miHeightAsBuffer.Checked; }; - menuItems.Add (miEnableConsoleScrolling); + menuItems.Add (miHeightAsBuffer); return menuItems.ToArray (); } diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 6ad129c3f..eaa15848f 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -37,7 +37,7 @@ namespace Terminal.Gui.ApplicationTests { Assert.NotNull (Application.Driver); Assert.NotNull (Application.Top); Assert.NotNull (Application.Current); - Assert.False (Application.EnableConsoleScrolling); + Assert.False (Application.HeightAsBuffer); Assert.NotNull (Application.MainLoop); Assert.Null (Application.Iteration); Assert.Null (Application.RootMouseEvent); @@ -314,7 +314,7 @@ namespace Terminal.Gui.ApplicationTests { public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws () { Init (); - + Application.Driver = null; Application.Iteration = () => { @@ -334,8 +334,8 @@ namespace Terminal.Gui.ApplicationTests { [Fact] public void Run_T_NoInit_DoesNotThrow () { - Application.ForceFakeConsole = true; - + Application.ForceFakeConsole = true; + Application.Iteration = () => { Application.RequestStop (); }; @@ -431,7 +431,7 @@ namespace Terminal.Gui.ApplicationTests { } // TODO: Add tests for Run that test errorHandler - + #endregion #region ShutdownTests diff --git a/UnitTests/Core/BorderTests.cs b/UnitTests/Core/BorderTests.cs index 64d4e341b..b8c330eb3 100644 --- a/UnitTests/Core/BorderTests.cs +++ b/UnitTests/Core/BorderTests.cs @@ -226,12 +226,7 @@ namespace Terminal.Gui.CoreTests { var color = (Attribute)driver.Contents [r, c, 1]; var rune = (Rune)driver.Contents [r, c, 0]; - if (r == frame.Y - drawMarginFrame || r == frame.Bottom + drawMarginFrame - 1 - || c == frame.X - drawMarginFrame || c == frame.Right + drawMarginFrame - 1) { - Assert.Equal (Color.BrightGreen, color.Background); - } else { - Assert.Equal (Color.Black, color.Background); - } + Assert.Equal (Color.Black, color.Background); if (c == frame.X - drawMarginFrame && r == frame.Y - drawMarginFrame) { Assert.Equal (uLCorner, rune); } else if (c == frame.Right && r == frame.Y - drawMarginFrame) { @@ -461,12 +456,7 @@ namespace Terminal.Gui.CoreTests { var color = (Attribute)driver.Contents [r, c, 1]; var rune = (Rune)driver.Contents [r, c, 0]; - if (r == frame.Y + sumThickness.Top || r == frame.Bottom - sumThickness.Bottom - 1 - || c == frame.X + sumThickness.Left || c == frame.Right - sumThickness.Right - 1) { - Assert.Equal (Color.BrightGreen, color.Background); - } else { - Assert.Equal (Color.Black, color.Background); - } + Assert.Equal (Color.Black, color.Background); if (c == frame.X + sumThickness.Left && r == frame.Y + sumThickness.Top) { Assert.Equal (uLCorner, rune); } else if (c == frame.Right - drawMarginFrame - sumThickness.Right diff --git a/UnitTests/Drivers/ConsoleDriverTests.cs b/UnitTests/Drivers/ConsoleDriverTests.cs index 6444b8f1c..8289e9737 100644 --- a/UnitTests/Drivers/ConsoleDriverTests.cs +++ b/UnitTests/Drivers/ConsoleDriverTests.cs @@ -171,7 +171,7 @@ namespace Terminal.Gui.DriverTests { // MockDriver will still be 120x40 wasTerminalResized = false; - Application.EnableConsoleScrolling = true; + Application.HeightAsBuffer = true; driver.SetWindowSize (40, 20); Assert.Equal (120, Application.Driver.Cols); Assert.Equal (40, Application.Driver.Rows); @@ -186,12 +186,12 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) + public void HeightAsBuffer_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Assert.False (Application.EnableConsoleScrolling); + Assert.False (Application.HeightAsBuffer); Assert.Equal (0, Console.WindowLeft); Assert.Equal (0, Console.WindowTop); @@ -204,13 +204,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) + public void HeightAsBuffer_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); + Application.HeightAsBuffer = true; + Assert.True (Application.HeightAsBuffer); driver.SetWindowPosition (81, 25); Assert.Equal (0, Console.WindowLeft); @@ -221,13 +221,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) + public void HeightAsBuffer_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); + Application.HeightAsBuffer = true; + Assert.True (Application.HeightAsBuffer); driver.SetWindowPosition (81, 25); Assert.Equal (0, Console.WindowLeft); @@ -261,13 +261,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) + public void HeightAsBuffer_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); + Application.HeightAsBuffer = true; + Assert.True (Application.HeightAsBuffer); driver.SetWindowPosition (80, 26); Assert.Equal (0, Console.WindowLeft); @@ -278,13 +278,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) + public void HeightAsBuffer_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.EnableConsoleScrolling = true; - Assert.True (Application.EnableConsoleScrolling); + Application.HeightAsBuffer = true; + Assert.True (Application.HeightAsBuffer); driver.SetWindowPosition (80, 26); Assert.Equal (0, Console.WindowLeft); diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index bd8677ca0..ae3766244 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -21,8 +21,8 @@ TRACE;DEBUG_IDISPOSABLE - - + +