From ed27696b9eb1bdd68b244457e31f1cfd2cbf49da Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 25 Feb 2023 22:26:04 +0000 Subject: [PATCH 01/88] Fixes 2342. Border: can't change border color in window by Border.BorderBrush. (#2345) * Fixes 2342. Border: can't change border color in window by Border.BorderBrush. * Fixes border initialization. --------- Co-authored-by: Tig --- Terminal.Gui/Core/Border.cs | 62 +++++++++++++++++++---- Terminal.Gui/Core/ConsoleDriver.cs | 6 +-- Terminal.Gui/Core/Window.cs | 19 +++---- Terminal.Gui/Views/FrameView.cs | 20 ++++---- UICatalog/Scenarios/BordersComparisons.cs | 5 +- UnitTests/Core/BorderTests.cs | 14 ++++- 6 files changed, 86 insertions(+), 40 deletions(-) diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index 55d73a65c..202c1ffbf 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -325,6 +325,7 @@ 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. @@ -433,7 +434,47 @@ namespace Terminal.Gui { /// /// Gets or sets the single child element of a . /// - public View Child { get; set; } + public View Child { + get => child; + set { + child = value; + if (child != null && Parent != null) { + Parent.Initialized += Parent_Initialized; + Parent.Removed += Parent_Removed; + } + } + } + + private void Parent_Removed (View obj) + { + BorderBrush = default; + Background = default; + child.Removed -= Parent_Removed; + } + + private void Parent_Initialized (object s, EventArgs e) + { + SetMarginFrameTitleBrush (); + child.Initialized -= Parent_Initialized; + } + + private void SetMarginFrameTitleBrush () + { + if (child != null) { + var view = Parent?.Border != null ? Parent : child; + if (view.ColorScheme != null) { + if (borderBrush == default) { + BorderBrush = view.GetNormalColor ().Foreground; + } + if (background == default) { + Background = view.GetNormalColor ().Background; + } + return; + } + } + BorderBrush = default; + Background = default; + } /// /// Gets the parent parent if any. @@ -583,7 +624,7 @@ namespace Terminal.Gui { Child.Clear (borderRect); } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw margin frame if (DrawMarginFrame) { @@ -607,6 +648,7 @@ 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) @@ -703,7 +745,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw the MarginFrame if (DrawMarginFrame) { @@ -858,7 +900,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw the MarginFrame if (DrawMarginFrame) { @@ -947,9 +989,9 @@ namespace Terminal.Gui { { var driver = Application.Driver; if (DrawMarginFrame) { - driver.SetAttribute (Child.GetNormalColor ()); - if (Child.HasFocus) - driver.SetAttribute (Child.ColorScheme.HotNormal); + driver.SetAttribute (new Attribute (BorderBrush, Background)); + if (view.HasFocus) + driver.SetAttribute (new Attribute (Child.ColorScheme.HotNormal.Foreground, Background)); var padding = view.Border.GetSumThickness (); Rect scrRect; if (view == Child) { @@ -958,7 +1000,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, Title, + driver.DrawWindowTitle (scrRect, Parent.Border.Title, padding.Left, padding.Top, padding.Right, padding.Bottom); } } @@ -974,9 +1016,9 @@ namespace Terminal.Gui { { var driver = Application.Driver; if (DrawMarginFrame) { - driver.SetAttribute (view.GetNormalColor ()); + driver.SetAttribute (new Attribute (BorderBrush, Background)); if (view.HasFocus) { - driver.SetAttribute (view.ColorScheme.HotNormal); + driver.SetAttribute (new Attribute (view.ColorScheme.HotNormal.Foreground, Background)); } 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 5f88b5d86..0bfc2a44e 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -85,7 +85,7 @@ namespace Terminal.Gui { } /// - /// + /// Indicates the RGB for true colors. /// public class TrueColor { /// @@ -115,7 +115,7 @@ namespace Terminal.Gui { } /// - /// + /// Converts true color to console color. /// /// public Color ToConsoleColor () @@ -493,7 +493,7 @@ namespace Terminal.Gui { public bool Equals (string x, string y) { if (x != null && y != null) { - return x.ToLowerInvariant () == y.ToLowerInvariant (); + return string.Equals (x, y, StringComparison.InvariantCultureIgnoreCase); } return false; } diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs index 85c8929cc..b865cd670 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Core/Window.cs @@ -35,6 +35,9 @@ namespace Terminal.Gui { if (!OnTitleChanging (title, value)) { var old = title; title = value; + if (Border != null) { + Border.Title = title; + } OnTitleChanged (old, title); } SetNeedsDisplay (); @@ -180,10 +183,13 @@ namespace Terminal.Gui { Border = new Border () { BorderStyle = BorderStyle.Single, Padding = new Thickness (padding), - BorderBrush = ColorScheme.Normal.Background + Title = title }; } else { Border = border; + if (ustring.IsNullOrEmpty (border.Title)) { + border.Title = title; + } } AdjustContentView (frame); } @@ -275,9 +281,6 @@ 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 (); @@ -286,7 +289,6 @@ 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; @@ -294,14 +296,7 @@ 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/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs index 09ad21884..c6ca31e63 100644 --- a/Terminal.Gui/Views/FrameView.cs +++ b/Terminal.Gui/Views/FrameView.cs @@ -30,6 +30,9 @@ namespace Terminal.Gui { get => title; set { title = value; + if (Border != null) { + Border.Title = title; + } SetNeedsDisplay (); } } @@ -112,10 +115,14 @@ namespace Terminal.Gui { this.Title = title; if (border == null) { Border = new Border () { - BorderStyle = BorderStyle.Single + BorderStyle = BorderStyle.Single, + Title = title }; } else { Border = border; + if (ustring.IsNullOrEmpty (border.Title)) { + border.Title = title; + } } AdjustContentView (frame, views); } @@ -214,12 +221,8 @@ 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 (); } @@ -227,16 +230,11 @@ namespace Terminal.Gui { contentView.Redraw (!NeedDisplay.IsEmpty ? contentView.Bounds : bounds); Driver.Clip = savedClip; + ClearLayoutNeeded (); ClearNeedsDisplay (); Driver.SetAttribute (GetNormalColor ()); - //Driver.DrawWindowFrame (scrRect, padding + 1, padding + 1, padding + 1, padding + 1, border: true, fill: false); 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/UICatalog/Scenarios/BordersComparisons.cs b/UICatalog/Scenarios/BordersComparisons.cs index 1aac4dca5..46c363c12 100644 --- a/UICatalog/Scenarios/BordersComparisons.cs +++ b/UICatalog/Scenarios/BordersComparisons.cs @@ -12,9 +12,10 @@ namespace UICatalog.Scenarios { var borderStyle = BorderStyle.Double; var drawMarginFrame = false; var borderThickness = new Thickness (1, 2, 3, 4); - var borderBrush = Colors.Base.HotFocus.Foreground; + var borderBrush = Color.BrightMagenta; + ; var padding = new Thickness (1, 2, 3, 4); - var background = Colors.Base.HotNormal.Foreground; + var background = Color.Cyan; var effect3D = true; var win = new Window (new Rect (5, 5, 40, 20), "Test", 8, diff --git a/UnitTests/Core/BorderTests.cs b/UnitTests/Core/BorderTests.cs index bcd6bf67e..c59b085ce 100644 --- a/UnitTests/Core/BorderTests.cs +++ b/UnitTests/Core/BorderTests.cs @@ -228,7 +228,12 @@ namespace Terminal.Gui.CoreTests { var color = (Attribute)driver.Contents [r, c, 1]; var rune = (Rune)driver.Contents [r, c, 0]; - Assert.Equal (Color.Black, color.Background); + 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); + } if (c == frame.X - drawMarginFrame && r == frame.Y - drawMarginFrame) { Assert.Equal (uLCorner, rune); } else if (c == frame.Right && r == frame.Y - drawMarginFrame) { @@ -457,7 +462,12 @@ namespace Terminal.Gui.CoreTests { var color = (Attribute)driver.Contents [r, c, 1]; var rune = (Rune)driver.Contents [r, c, 0]; - Assert.Equal (Color.Black, color.Background); + 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); + } if (c == frame.X + sumThickness.Left && r == frame.Y + sumThickness.Top) { Assert.Equal (uLCorner, rune); } else if (c == frame.Right - drawMarginFrame - sumThickness.Right From 1d2dc40c8a69cb6bd1768382b21893970d1447c1 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 25 Feb 2023 22:30:44 +0000 Subject: [PATCH 02/88] Fixes #2305. Improves the handling of escape sequence. (#2375) * Changed ansi esc sequence used on exit. * Changed ansi esc sequence used on exit. * Improves HeightAsBuffer although currently only works on Windows. * Fixes #2267. Toplevel.EnsureVisibleBounds throws an exception if border is null. * Changing comment as requested. * Fixes indentation. * Seems not needed for now, maybe some update, comment for now. * Renamed HeightAsBuffer to EnableConsoleScrolling and made it obsolete. * Add comment on remarks for EnableConsoleScrolling. * merged @bdisp's EnableConsoleScrolling PR * Fixes buffer for Windows Terminal. * Fixes issue in Windows Terminal on resizing causing some lines not be drawing after exceptions. * merge #9 * merged #9 * use ESC [ ? 1047 * Tweaks with new esc codes * Fixed curses driver to not nuke scroll buffer and to resize properly * merge * Cleand up netdriver escape codes * fixed spaces->tabs * fixed spaces->tabs * fixed spaces->tabs * fixed spaces->tabs * fixed merge issue and spaces->tabs * fixed spaces->tabs * fixed spaces->tabs * fixed spaces->tabs * fixed build error * removed old comments * Resolving merge conflicts. * Ensuring reset the EnableConsoleScrolling. * Changing from HeightAsBuffer to EnableConsoleScrolling. * Done requested changes. * Reformatting. * Rename to EscSeqReqStatus. * Removing Console.Out.Flush (); --------- Co-authored-by: Charlie Kindel Co-authored-by: Tig Kindel --- 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 | 1477 ++++++----------- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 92 +- Terminal.Gui/Core/Application.cs | 48 +- Terminal.Gui/Core/ConsoleDriver.cs | 89 +- Terminal.Gui/Core/ConsoleKeyMapping.cs | 19 + Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs | 109 ++ Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs | 907 ++++++++++ Terminal.Gui/Core/Event.cs | 2 +- Terminal.Gui/Terminal.Gui.csproj | 1 + UICatalog/Properties/launchSettings.json | 16 +- UICatalog/UICatalog.cs | 33 +- UnitTests/Application/ApplicationTests.cs | 11 +- UnitTests/Core/EscSeqReqTests.cs | 78 + UnitTests/Core/EscSeqUtilsTests.cs | 870 ++++++++++ UnitTests/Drivers/ConsoleDriverTests.cs | 30 +- UnitTests/UnitTests.csproj | 4 +- 24 files changed, 3425 insertions(+), 2313 deletions(-) create mode 100644 Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs create mode 100644 Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs create mode 100644 UnitTests/Core/EscSeqReqTests.cs create mode 100644 UnitTests/Core/EscSeqUtilsTests.cs diff --git a/ReactiveExample/ReactiveExample.csproj b/ReactiveExample/ReactiveExample.csproj index c2ce6640c..04793513d 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 ec2220519..7e5f4dcfd 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -1,9 +1,6 @@ // // Driver.cs: Curses-based Driver // -// Authors: -// Miguel de Icaza (miguel@gnome.org) -// using System; using System.Collections.Generic; using System.Diagnostics; @@ -23,7 +20,12 @@ namespace Terminal.Gui { public override int Rows => Curses.Lines; public override int Left => 0; public override int Top => 0; - public override bool HeightAsBuffer { get; set; } + 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 IClipboard Clipboard { get => clipboard; } CursorVisibility? initialCursorVisibility = null; @@ -116,7 +118,7 @@ namespace Terminal.Gui { if (runeWidth < 0 || runeWidth > 0) { ccol++; } - + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -158,26 +160,10 @@ namespace Terminal.Gui { public override void End () { - if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) { - StopReportingMouseMoves (); - } - + 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 (); @@ -324,305 +310,6 @@ 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) @@ -656,9 +343,18 @@ namespace Terminal.Gui { ProcessWinChange (); } if (wch == Curses.KeyMouse) { - 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)); + 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); + } return; } k = MapCursesKey (wch); @@ -694,7 +390,7 @@ namespace Terminal.Gui { k = Key.AltMask | MapCursesKey (wch); } if (code == 0) { - KeyEvent key; + KeyEvent key = null; // The ESC-number handling, debatable. // Simulates the AltMask itself by pressing Alt + Space. @@ -706,55 +402,13 @@ 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 == 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 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 { // Unfortunately there are no way to differentiate Ctrl+Alt+alfa and Ctrl+Shift+Alt+alfa. if (((Key)wch2 & Key.CtrlMask) != 0) { @@ -809,6 +463,52 @@ 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; @@ -835,17 +535,12 @@ 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) { @@ -892,10 +587,8 @@ namespace Terminal.Gui { Curses.noecho (); Curses.Window.Standard.keypad (true); - reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out oldMouseEvents); TerminalResized = terminalResized; - if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) - StartReportingMouseMoves (); + StartReportingMouseMoves (); CurrentAttribute = MakeColor (Color.White, Color.Black); @@ -944,8 +637,7 @@ namespace Terminal.Gui { public override void ResizeScreen () { Clip = new Rect (0, 0, Cols, Rows); - Console.Out.Write ("\x1b[3J"); - Console.Out.Flush (); + Curses.refresh (); } public override void UpdateOffScreen () @@ -1065,25 +757,21 @@ namespace Terminal.Gui { public override void Suspend () { - if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) - StopReportingMouseMoves (); + StopReportingMouseMoves (); Platform.Suspend (); Curses.Window.Standard.redrawwin (); Curses.refresh (); - if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) - StartReportingMouseMoves (); + StartReportingMouseMoves (); } public override void StartReportingMouseMoves () { - Console.Out.Write ("\x1b[?1003h"); - Console.Out.Flush (); + Console.Out.Write (EscSeqUtils.EnableMouseEvents); } public override void StopReportingMouseMoves () { - Console.Out.Write ("\x1b[?1003l"); - Console.Out.Flush (); + Console.Out.Write (EscSeqUtils.DisableMouseEvents); } //int lastMouseInterval; @@ -1126,7 +814,6 @@ namespace Terminal.Gui { if (visibility != CursorVisibility.Invisible) { Console.Out.Write ("\x1b[{0} q", ((int)visibility >> 24) & 0xFF); - Console.Out.Flush (); } currentCursorVisibility = visibility; @@ -1191,8 +878,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; @@ -1285,6 +972,7 @@ 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 ()) { @@ -1294,6 +982,7 @@ 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 977913fa2..df5359542 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/UnixMainLoop.cs @@ -1,30 +1,6 @@ // // 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; @@ -52,7 +28,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 { @@ -127,10 +103,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 b1b60c3a5..cde433744 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,8 +21,6 @@ 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. @@ -45,7 +43,7 @@ namespace Unix.Terminal { static bool IsNetCore; public static bool IsMacOSPlatform => IsMacOS; - + [DllImport ("libc")] static extern int uname (IntPtr buf); @@ -105,11 +103,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; @@ -164,13 +162,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 } /// @@ -209,12 +207,11 @@ 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); @@ -222,8 +219,7 @@ 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); @@ -231,8 +227,7 @@ 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); @@ -247,8 +242,7 @@ 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); @@ -261,13 +255,12 @@ 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 4195344eb..42612b3ae 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs @@ -145,11 +145,6 @@ 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 b9a63834a..fb9bc326b 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs @@ -53,7 +53,6 @@ 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); @@ -69,7 +68,7 @@ namespace Unix.Terminal { Button2Released = unchecked((int)0x20), Button2Clicked = unchecked((int)0x80), Button2DoubleClicked = unchecked((int)0x100), - Button2TrippleClicked = unchecked((int)0x200), + Button2TripleClicked = unchecked((int)0x200), Button3Pressed = unchecked((int)0x800), Button3Released = unchecked((int)0x400), Button3Clicked = unchecked((int)0x1000), @@ -106,6 +105,7 @@ 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 e78baa96a..017050ef0 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeConsole.cs @@ -1,15 +1,10 @@ // // 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 { @@ -22,23 +17,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. /// @@ -57,113 +52,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; @@ -174,21 +169,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; @@ -198,299 +193,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. /// /// /// @@ -498,12 +493,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. /// /// /// @@ -513,24 +508,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. /// /// /// @@ -540,11 +535,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]; @@ -559,41 +554,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. /// /// /// @@ -604,54 +599,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] /// /// @@ -663,10 +658,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard error stream. + // Acquires the standard error stream. // // Returns: - // The standard error stream. + // The standard error stream. /// /// /// @@ -677,18 +672,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. /// /// /// @@ -699,18 +694,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. /// /// /// @@ -721,10 +716,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard input stream. + // Acquires the standard input stream. // // Returns: - // The standard input stream. + // The standard input stream. /// /// /// @@ -735,18 +730,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. /// /// /// @@ -757,10 +752,10 @@ namespace Terminal.Gui { // // Summary: - // Acquires the standard output stream. + // Acquires the standard output stream. // // Returns: - // The standard output stream. + // The standard output stream. /// /// /// @@ -771,15 +766,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. /// /// /// @@ -790,25 +785,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] /// /// @@ -829,20 +824,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. /// /// /// @@ -853,21 +848,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. /// /// /// @@ -878,14 +873,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] /// /// @@ -898,27 +893,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] /// /// @@ -932,27 +927,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] /// /// @@ -967,19 +962,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] /// /// @@ -991,18 +986,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] /// /// @@ -1014,18 +1009,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] /// /// @@ -1038,26 +1033,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] /// /// @@ -1072,27 +1067,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] /// /// @@ -1107,15 +1102,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. /// /// /// @@ -1127,16 +1122,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. /// /// /// @@ -1148,16 +1143,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)] /// /// @@ -1170,16 +1165,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. /// /// /// @@ -1191,28 +1186,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. /// /// /// @@ -1226,16 +1221,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. /// /// /// @@ -1247,25 +1242,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. /// /// /// @@ -1278,16 +1273,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)] /// /// @@ -1314,25 +1309,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. /// /// /// @@ -1345,16 +1340,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. /// /// /// @@ -1366,15 +1361,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. /// /// /// @@ -1386,15 +1381,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. /// /// /// @@ -1409,30 +1404,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. /// /// /// @@ -1446,31 +1441,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. /// /// /// @@ -1485,16 +1480,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. /// /// /// @@ -1506,16 +1501,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. /// /// /// @@ -1527,16 +1522,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. /// /// /// @@ -1548,11 +1543,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. /// /// /// @@ -1563,16 +1558,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. /// /// /// @@ -1584,16 +1579,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. /// /// /// @@ -1605,16 +1600,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)] /// /// @@ -1627,16 +1622,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. /// /// /// @@ -1648,16 +1643,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)] /// /// @@ -1670,16 +1665,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. /// /// /// @@ -1691,16 +1686,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. /// /// /// @@ -1712,25 +1707,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. /// /// /// @@ -1743,31 +1738,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. /// /// /// @@ -1796,26 +1791,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. /// /// /// @@ -1828,31 +1823,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. /// /// /// @@ -1866,16 +1861,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. /// /// /// @@ -1887,16 +1882,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. /// /// /// @@ -1908,16 +1903,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. /// /// /// @@ -1929,16 +1924,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. /// /// /// @@ -1950,28 +1945,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. /// /// /// @@ -1985,16 +1980,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 661daaca4..824a63829 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs @@ -1,9 +1,6 @@ // // FakeDriver.cs: A fake ConsoleDriver for unit tests. // -// Authors: -// Charlie Kindel (github.com/tig) -// using System; using System.Collections.Generic; using System.Diagnostics; @@ -48,7 +45,12 @@ 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 HeightAsBuffer { get; set; } + public override bool EnableConsoleScrolling { get; set; } + [Obsolete ("This API is deprecated; use EnableConsoleScrolling instead.", false)] + public override bool HeightAsBuffer { + get => EnableConsoleScrolling; + set => EnableConsoleScrolling = value; + } private IClipboard clipboard = null; public override IClipboard Clipboard => clipboard; @@ -245,8 +247,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); } @@ -535,7 +537,7 @@ namespace Terminal.Gui { FakeConsole.SetBufferSize (width, height); cols = width; rows = height; - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { SetWindowSize (width, height); } ProcessResize (); @@ -544,7 +546,7 @@ namespace Terminal.Gui { public void SetWindowSize (int width, int height) { FakeConsole.SetWindowSize (width, height); - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { if (width != cols || height != rows) { SetBufferSize (width, height); cols = width; @@ -556,7 +558,7 @@ namespace Terminal.Gui { public void SetWindowPosition (int left, int top) { - if (HeightAsBuffer) { + if (EnableConsoleScrolling) { 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) { @@ -575,7 +577,7 @@ namespace Terminal.Gui { public override void ResizeScreen () { - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { if (FakeConsole.WindowHeight > 0) { // Can raise an exception while is still resizing. try { @@ -629,8 +631,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 9ae4eb20e..da969d136 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1,5 +1,4 @@ -//#define PROCESS_REQUEST -// +// // NetDriver.cs: The System.Console-based .NET driver, works on Windows and Unix, but is not particularly efficient. // // Authors: @@ -7,6 +6,7 @@ // using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Threading; @@ -111,27 +111,37 @@ namespace Terminal.Gui { ManualResetEventSlim winChange = new ManualResetEventSlim (false); Queue inputResultQueue = new Queue (); ConsoleDriver consoleDriver; + volatile ConsoleKeyInfo [] cki = null; + static volatile bool isEscSeq; int lastWindowHeight; - int largestWindowHeight; + bool stopTasks; #if PROCESS_REQUEST - bool neededProcessRequest; + bool neededProcessRequest; #endif - public int NumberOfCSI { get; } + public bool IsTerminalWithOptions { get; set; } + public EscSeqReqProc EscSeqReqProc { get; } = new EscSeqReqProc (); - public NetEvents (ConsoleDriver consoleDriver, int numberOfCSI = 1) + public NetEvents (ConsoleDriver consoleDriver) { 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 (); @@ -140,7 +150,7 @@ namespace Terminal.Gui { inputReady.Reset (); } #if PROCESS_REQUEST - neededProcessRequest = false; + neededProcessRequest = false; #endif if (inputResultQueue.Count > 0) { return inputResultQueue.Dequeue (); @@ -155,16 +165,53 @@ namespace Terminal.Gui { waitForStart.Reset (); if (inputResultQueue.Count == 0) { - GetConsoleInputType (Console.ReadKey (true)); + GetConsoleKey (); } 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 (); @@ -177,44 +224,58 @@ 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 (!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)); + 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)) { + return; } - } 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 + break; + case true: + //Request the size of the text area in characters. + EscSeqReqProc.Add ("t"); + Console.Out.Write ("\x1b[18t"); + break; } } } + 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 () { @@ -232,876 +293,245 @@ namespace Terminal.Gui { InputResult inputResult = new InputResult { EventType = EventType.Key }; - ConsoleKeyInfo newConsoleKeyInfo = consoleKeyInfo; - ConsoleKey key = 0; MouseEvent mouseEvent = new MouseEvent (); - 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); + ConsoleKeyInfo newConsoleKeyInfo = EscSeqUtils.GetConsoleInputKey (consoleKeyInfo); + if (inputResult.EventType == EventType.Key) { + inputResult.ConsoleKeyInfo = newConsoleKeyInfo; + } else { + inputResult.MouseEvent = mouseEvent; + } + + inputResultQueue.Enqueue (inputResult); + } + + void DecodeEscSeq (ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ConsoleKeyInfo [] cki, 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); } - 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); + return; + } else if (isReq) { + GetRequestEvent (c1Control, code, values, terminating); + return; + } + InputResult inputResult = new InputResult { + EventType = EventType.Key, + ConsoleKeyInfo = newConsoleKeyInfo + }; + + 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; } - 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 { - inputResult.MouseEvent = mouseEvent; - } - - inputResultQueue.Enqueue (inputResult); - } - - void SplitCSI (ConsoleKeyInfo [] cki, ref InputResult inputResult, ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ref MouseEvent mouseEvent, ref ConsoleModifiers mod) - { - 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; - case int n when n >= 8: - GetMouseEvent (cki); - return; - } - if (inputResult.EventType == EventType.Key) { - inputResult.ConsoleKeyInfo = newConsoleKeyInfo; - } else { - inputResult.MouseEvent = mouseEvent; - } - - inputResultQueue.Enqueue (inputResult); + return mbs; } Point lastCursorPosition; - void GetRequestEvent (char [] kChar) + void GetRequestEvent (string c1Control, string code, string [] values, string terminating) { EventType eventType = new EventType (); - 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; - - 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 (); - } + 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); + } + + 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; + } + 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 (); } - MouseEvent lastMouseEvent; - bool isButtonPressed; - bool isButtonClicked; - bool isButtonDoubleClicked; - bool isButtonTripleClicked; - bool isProcContBtnPressedRuning; - int buttonPressedCount; - //bool isButtonReleased; - - void GetMouseEvent (ConsoleKeyInfo [] cki) + void SetRequestedEvent (string c1Control, string code, string [] values, string terminating) { - 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; + EventType eventType = EventType.RequestResponse; + var requestRespEv = new RequestResponseEvent () { + ResultTuple = (c1Control, code, values, terminating) + }; + inputResultQueue.Enqueue (new InputResult () { + EventType = eventType, + RequestResponseEvent = requestRespEv + }); + } - //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; - //} + void GetMouseEvent (MouseButtonState buttonState, Point pos) + { + MouseEvent mouseEvent = new MouseEvent () { + Position = pos, + ButtonState = buttonState, + }; 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 + WindowPosition = 4, + RequestResponse = 5 } [Flags] @@ -1115,7 +545,7 @@ namespace Terminal.Gui { Button2Released = 0x40, Button2Clicked = 0x80, Button2DoubleClicked = 0x100, - Button2TrippleClicked = 0x200, + Button2TripleClicked = 0x200, Button3Pressed = 0x400, Button3Released = 0x800, Button3Clicked = 0x1000, @@ -1134,7 +564,7 @@ namespace Terminal.Gui { ButtonCtrl = 0x2000000, ButtonAlt = 0x4000000, ReportMousePosition = 0x8000000, - 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 + AllEvents = -1 } public struct MouseEvent { @@ -1152,12 +582,17 @@ 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; } } @@ -1185,14 +620,19 @@ namespace Terminal.Gui { public override int Rows => rows; public override int Left => left; public override int Top => top; - public override bool HeightAsBuffer { get; set; } + 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 NetWinVTConsole NetWinConsole { get; } public bool IsWinPlatform { get; } public override IClipboard Clipboard { get; } public override int [,,] Contents => contents; - int largestWindowHeight; + int largestBufferHeight; public NetDriver () { @@ -1201,8 +641,6 @@ 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)) { @@ -1283,7 +721,7 @@ namespace Terminal.Gui { if (runeWidth < 0 || runeWidth > 0) { ccol++; } - + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -1292,11 +730,6 @@ namespace Terminal.Gui { ccol++; } - //if (ccol == Cols) { - // ccol = 0; - // if (crow + 1 < Rows) - // crow++; - //} if (sync) { UpdateScreen (); } @@ -1310,25 +743,22 @@ namespace Terminal.Gui { public override void End () { + mainLoop.netEvents.StopTasks (); + if (IsWinPlatform) { NetWinConsole.Cleanup (); } StopReportingMouseMoves (); Console.ResetColor (); - Clear (); + + //Disable alternative screen buffer. + Console.Out.Write ("\x1b[?1049l"); + //Set cursor key to cursor. Console.Out.Write ("\x1b[?25h"); - Console.Out.Flush (); - } - void Clear () - { - if (Rows > 0) { - Console.Clear (); - Console.Out.Write ("\x1b[3J"); - //Console.Out.Write ("\x1b[?25l"); - } + Console.Out.Close (); } public override Attribute MakeColor (Color foreground, Color background) @@ -1350,14 +780,25 @@ 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 = Console.WindowHeight; + rows = largestBufferHeight; + + CurrentAttribute = MakeColor (Color.White, Color.Black); + InitalizeColorSchemes (); CurrentAttribute = MakeColor (Color.White, Color.Black); InitalizeColorSchemes (); @@ -1366,55 +807,64 @@ namespace Terminal.Gui { UpdateOffScreen (); StartReportingMouseMoves (); - - - Clear (); } public override void ResizeScreen () { - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { if (Console.WindowHeight > 0) { - // Can raise an exception while is still resizing. - try { - // Not supported on Unix. - if (IsWinPlatform) { + // Not supported on Unix. + if (IsWinPlatform) { + // Can raise an exception while is still resizing. + try { #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 - } else { - //Console.Out.Write ($"\x1b[8;{Console.WindowHeight};{Console.WindowWidth}t"); - Console.Out.Write ($"\x1b[0;0" + - $";{Rows};{Cols}w"); + } catch (System.IO.IOException) { + setClip (); + } catch (ArgumentOutOfRangeException) { + setClip (); } - } catch (System.IO.IOException) { - return; - } catch (ArgumentOutOfRangeException) { - return; + } else { + Console.Out.Write ($"\x1b[8;{Rows};{Cols}t"); } } } else { - if (IsWinPlatform && Console.WindowHeight > 0) { - // Can raise an exception while is still resizing. - try { + if (IsWinPlatform) { + if (Console.WindowHeight > 0) { + // Can raise an exception while is still resizing. + try { #pragma warning disable CA1416 - Console.WindowTop = Math.Max (Math.Min (top, Rows - Console.WindowHeight), 0); + Console.CursorTop = 0; + Console.CursorLeft = 0; + if (Console.WindowHeight > Rows) { + Console.SetWindowSize (Cols, Rows); + } + Console.SetBufferSize (Cols, Rows); #pragma warning restore CA1416 - } catch (Exception) { - return; + } catch (System.IO.IOException) { + setClip (); + } catch (ArgumentOutOfRangeException) { + setClip (); + } } } else { - Console.Out.Write ($"\x1b[{top};{Console.WindowLeft}" + - $";{Rows};{Cols}w"); + Console.Out.Write ($"\x1b[30;{Rows};{Cols}t"); } } - Clip = new Rect (0, 0, Cols, Rows); - Console.Out.Write ("\x1b[3J"); - Console.Out.Flush (); + setClip (); + + void setClip () + { + Clip = new Rect (0, 0, Cols, Rows); + } } public override void UpdateOffScreen () @@ -1448,42 +898,43 @@ namespace Terminal.Gui { UpdateCursor (); } - int redrawAttr = -1; - public override void UpdateScreen () { - if (Console.WindowHeight == 0 || contents.Length != Rows * Cols * 3 - || (!HeightAsBuffer && Rows != Console.WindowHeight) - || (HeightAsBuffer && Rows != largestWindowHeight)) { + if (winChanging || Console.WindowHeight < 1 || contents.Length != Rows * Cols * 3 + || (!EnableConsoleScrolling && Rows != Console.WindowHeight) + || (EnableConsoleScrolling && Rows != largestBufferHeight)) { return; } - int top = Top; - int left = Left; - int rows = Math.Min (Console.WindowHeight + top, Rows); + int top = 0; + int left = 0; + int rows = 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) { - //Console.CursorLeft = lastCol; - //Console.CursorTop = row; - SetVirtualCursorPosition (lastCol, row); + SetCursorPosition (lastCol, row); Console.Write (output); output.Clear (); lastCol += outputWidth; @@ -1501,6 +952,7 @@ namespace Terminal.Gui { var attr = contents [row, col, 1]; if (attr != redrawAttr) { + redrawAttr = attr; output.Append (WriteAttributes (attr)); } outputWidth++; @@ -1515,18 +967,16 @@ namespace Terminal.Gui { } } if (output.Length > 0) { - //Console.CursorLeft = lastCol; - //Console.CursorTop = row; - SetVirtualCursorPosition (lastCol, row); + SetCursorPosition (lastCol, row); Console.Write (output); } } + SetCursorPosition (0, 0); } - void SetVirtualCursorPosition (int lastCol, int row) + void SetVirtualCursorPosition (int col, int row) { - Console.Out.Write ($"\x1b[{row + 1};{lastCol + 1}H"); - Console.Out.Flush (); + Console.Out.Write ($"\x1b[{row + 1};{col + 1}H"); } System.Text.StringBuilder WriteAttributes (int attr) @@ -1536,10 +986,9 @@ 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); } @@ -1592,42 +1041,80 @@ namespace Terminal.Gui { bool SetCursorPosition (int col, int row) { - // Could happens that the windows is still resizing and the col is bigger than Console.WindowWidth. - try { - Console.SetCursorPosition (col, 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); 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 () { - if (!EnsureCursorVisibility ()) - return; + EnsureCursorVisibility (); + //Debug.WriteLine ($"Before - CursorTop: {Console.CursorTop};CursorLeft: {Console.CursorLeft}"); - // 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) { + if (ccol >= 0 && ccol < Cols && crow >= 0 && crow < Rows) { + SetCursorPosition (ccol, crow); + SetWindowPosition (0, crow); } + //Debug.WriteLine ($"WindowTop: {Console.WindowTop};WindowLeft: {Console.WindowLeft}"); + //Debug.WriteLine ($"After - CursorTop: {Console.CursorTop};CursorLeft: {Console.CursorLeft}"); } public override void StartReportingMouseMoves () { - Console.Out.Write ("\x1b[?1003h\x1b[?1015h\x1b[?1006h"); - Console.Out.Flush (); + Console.Out.Write (EscSeqUtils.EnableMouseEvents); } public override void StopReportingMouseMoves () { - Console.Out.Write ("\x1b[?1003l\x1b[?1015l\x1b[?1006l"); - Console.Out.Flush (); + Console.Out.Write (EscSeqUtils.DisableMouseEvents); } public override void Suspend () @@ -1782,6 +1269,7 @@ 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) { @@ -1790,10 +1278,14 @@ namespace Terminal.Gui { this.keyUpHandler = keyUpHandler; this.mouseHandler = mouseHandler; - var mLoop = mainLoop.Driver as NetMainLoop; + var mLoop = this.mainLoop = 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) @@ -1822,38 +1314,31 @@ namespace Terminal.Gui { mouseHandler (ToDriverMouse (inputEvent.MouseEvent)); break; case NetEvents.EventType.WindowSize: - ChangeWin (); + ChangeWin (inputEvent.WindowSizeEvent.Size); break; - 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 (); - } + case NetEvents.EventType.RequestResponse: + Application.Top.Data = inputEvent.RequestResponseEvent.ResultTuple; break; } } - void ChangeWin () + volatile bool winChanging; + + void ChangeWin (Size size) { - 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; + winChanging = true; + if (!EnableConsoleScrolling) { + largestBufferHeight = Math.Max (size.Height, 0); } else { - //largestWindowHeight = Math.Max (Console.BufferHeight, largestWindowHeight); - largestWindowHeight = Console.BufferHeight; - size = new Size (Console.BufferWidth, largestWindowHeight); + largestBufferHeight = Math.Max (size.Height, largestBufferHeight); } + top = 0; + left = 0; cols = size.Width; - rows = size.Height; + rows = largestBufferHeight; ResizeScreen (); UpdateOffScreen (); + winChanging = false; TerminalResized?.Invoke (); } @@ -1890,7 +1375,7 @@ namespace Terminal.Gui { if ((me.ButtonState & NetEvents.MouseButtonState.Button2DoubleClicked) != 0) { mouseFlag |= MouseFlags.Button2DoubleClicked; } - if ((me.ButtonState & NetEvents.MouseButtonState.Button2TrippleClicked) != 0) { + if ((me.ButtonState & NetEvents.MouseButtonState.Button2TripleClicked) != 0) { mouseFlag |= MouseFlags.Button2TripleClicked; } if ((me.ButtonState & NetEvents.MouseButtonState.Button3Pressed) != 0) { @@ -2001,8 +1486,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); @@ -2053,7 +1538,7 @@ namespace Terminal.Gui { Queue inputResult = new Queue (); MainLoop mainLoop; CancellationTokenSource tokenSource = new CancellationTokenSource (); - NetEvents netEvents; + internal NetEvents netEvents; /// /// Invoked when a Key is pressed. diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index d7b72fe37..a2f87af0e 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1,30 +1,6 @@ // // 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; @@ -646,7 +622,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 (); @@ -739,7 +715,12 @@ namespace Terminal.Gui { public override int Rows => rows; public override int Left => left; public override int Top => top; - public override bool HeightAsBuffer { get; set; } + 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 IClipboard Clipboard => clipboard; public override int [,,] Contents => contents; @@ -774,7 +755,7 @@ namespace Terminal.Gui { private void ChangeWin (Size e) { - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { var w = e.Width; if (w == cols - 3 && e.Height < rows) { w += 3; @@ -915,8 +896,12 @@ namespace Terminal.Gui { left = pos.X; top = pos.Y; cols = inputEvent.WindowBufferSizeEvent.size.X; - rows = inputEvent.WindowBufferSizeEvent.size.Y; - //System.Diagnostics.Debug.WriteLine ($"{HeightAsBuffer},{cols},{rows}"); + if (EnableConsoleScrolling) { + rows = Math.Max (inputEvent.WindowBufferSizeEvent.size.Y, rows); + } else { + rows = inputEvent.WindowBufferSizeEvent.size.Y; + } + //System.Diagnostics.Debug.WriteLine ($"{EnableConsoleScrolling},{cols},{rows}"); ResizeScreen (); UpdateOffScreen (); TerminalResized?.Invoke (); @@ -1459,6 +1444,19 @@ 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; @@ -1467,6 +1465,9 @@ namespace Terminal.Gui { CurrentAttribute = MakeColor (Color.White, Color.Black); InitalizeColorSchemes (); + CurrentAttribute = MakeColor (Color.White, Color.Black); + InitalizeColorSchemes (); + ResizeScreen (); UpdateOffScreen (); } catch (Win32Exception e) { @@ -1485,8 +1486,15 @@ namespace Terminal.Gui { Right = (short)Cols }; WinConsole.ForceRefreshCursorVisibility (); - Console.Out.Write ("\x1b[3J"); - Console.Out.Flush (); + 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"); + } } public override void UpdateOffScreen () @@ -1653,7 +1661,7 @@ namespace Terminal.Gui { if (damageRegion.Left == -1) return; - if (!HeightAsBuffer) { + if (!EnableConsoleScrolling) { var windowSize = WinConsole.GetConsoleBufferWindow (out _); if (!windowSize.IsEmpty && (windowSize.Width != Cols || windowSize.Height != Rows)) return; @@ -1700,6 +1708,18 @@ 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 } /// @@ -1780,8 +1800,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); @@ -1897,9 +1917,9 @@ namespace Terminal.Gui { { while (true) { Thread.Sleep (100); - if (!consoleDriver.HeightAsBuffer) { + if (!consoleDriver.EnableConsoleScrolling) { windowSize = winConsole.GetConsoleBufferWindow (out _); - //System.Diagnostics.Debug.WriteLine ($"{consoleDriver.HeightAsBuffer},{windowSize.Width},{windowSize.Height}"); + //System.Diagnostics.Debug.WriteLine ($"{consoleDriver.EnableConsoleScrolling},{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 eb609e609..8d929682b 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -111,29 +111,50 @@ namespace Terminal.Gui { /// public static View WantContinuousButtonPressedView { get; private set; } - private static bool? _heightAsBuffer; + private static bool? _enableConsoleScrolling; /// - /// The current used in the terminal. + /// The current used in the terminal. /// - /// - public static bool HeightAsBuffer { + /// + /// + /// 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. + /// + /// This API was previously named 'HeightAsBuffer` but was renamed to make its purpose more clear. + /// + public static bool EnableConsoleScrolling { get { if (Driver == null) { - return _heightAsBuffer.HasValue && _heightAsBuffer.Value; + return _enableConsoleScrolling.HasValue && _enableConsoleScrolling.Value; } - return Driver.HeightAsBuffer; + return Driver.EnableConsoleScrolling; } set { - _heightAsBuffer = value; + _enableConsoleScrolling = value; if (Driver == null) { return; } - - Driver.HeightAsBuffer = _heightAsBuffer.Value; + 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; + } + static Key alternateForwardKey = Key.PageDown | Key.CtrlMask; /// @@ -152,7 +173,7 @@ namespace Terminal.Gui { static void OnAlternateForwardKeyChanged (Key oldKey) { - foreach (var top in toplevels.ToArray()) { + foreach (var top in toplevels.ToArray ()) { top.OnAlternateForwardKeyChanged (oldKey); } } @@ -175,7 +196,7 @@ namespace Terminal.Gui { static void OnAlternateBackwardKeyChanged (Key oldKey) { - foreach (var top in toplevels.ToArray()) { + foreach (var top in toplevels.ToArray ()) { top.OnAlternateBackwardKeyChanged (oldKey); } } @@ -206,7 +227,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); } } @@ -428,7 +449,7 @@ namespace Terminal.Gui { MainLoop = new MainLoop (mainLoopDriver); try { - Driver.HeightAsBuffer = HeightAsBuffer; + Driver.EnableConsoleScrolling = EnableConsoleScrolling; Driver.Init (TerminalResized); } catch (InvalidOperationException ex) { // This is a case where the driver is unable to initialize the console. @@ -1104,6 +1125,7 @@ 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/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 0bfc2a44e..275396d4d 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -646,72 +646,7 @@ 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. @@ -748,9 +683,27 @@ namespace Terminal.Gui { public abstract IClipboard Clipboard { get; } /// - /// 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. + /// + /// 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. + /// /// + /// + /// 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 d7bc3d584..441adac48 100644 --- a/Terminal.Gui/Core/ConsoleKeyMapping.cs +++ b/Terminal.Gui/Core/ConsoleKeyMapping.cs @@ -334,6 +334,25 @@ 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/EscSeqUtils/EscSeqReq.cs b/Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs new file mode 100644 index 000000000..eaa3084ad --- /dev/null +++ b/Terminal.Gui/Core/EscSeqUtils/EscSeqReq.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; + +namespace Terminal.Gui { + /// + /// Represents the state of an ANSI escape sequence request. + /// + /// + /// This is needed because there are some escape sequence requests responses that are equal + /// with some normal escape sequences and thus, will be only considered the responses to the + /// requests that were registered with this object. + /// + public class EscSeqReqStatus { + /// + /// Gets the terminating. + /// + public string Terminating { get; } + /// + /// Gets the number of requests. + /// + public int NumRequests { get; } + /// + /// Gets information about unfinished requests. + /// + public int NumOutstanding { get; set; } + + /// + /// Creates a new state of escape sequence request. + /// + /// The terminating. + /// The number of requests. + public EscSeqReqStatus (string terminating, int numOfReq) + { + Terminating = terminating; + NumRequests = NumOutstanding = numOfReq; + } + } + + /// + /// Manages a list of . + /// + public class EscSeqReqProc { + /// + /// Gets the list. + /// + public List EscSeqReqStats { get; } = new List (); + + /// + /// Adds a new instance to the list. + /// + /// The terminating. + /// The number of requests. + public void Add (string terminating, int numOfReq = 1) + { + lock (EscSeqReqStats) { + var found = EscSeqReqStats.Find (x => x.Terminating == terminating); + if (found == null) { + EscSeqReqStats.Add (new EscSeqReqStatus (terminating, numOfReq)); + } else if (found != null && found.NumOutstanding < found.NumRequests) { + found.NumOutstanding = Math.Min (found.NumOutstanding + numOfReq, found.NumRequests); + } + } + } + + /// + /// Removes a instance from the list. + /// + /// The terminating string. + public void Remove (string terminating) + { + lock (EscSeqReqStats) { + var found = EscSeqReqStats.Find (x => x.Terminating == terminating); + if (found == null) { + return; + } + if (found != null && found.NumOutstanding == 0) { + EscSeqReqStats.Remove (found); + } else if (found != null && found.NumOutstanding > 0) { + found.NumOutstanding--; + if (found.NumOutstanding == 0) { + EscSeqReqStats.Remove (found); + } + } + } + } + + /// + /// Indicates if a with the exist + /// in the list. + /// + /// + /// if exist, otherwise. + public bool Requested (string terminating) + { + lock (EscSeqReqStats) { + var found = EscSeqReqStats.Find (x => x.Terminating == terminating); + if (found == null) { + return false; + } + if (found != null && found.NumOutstanding > 0) { + return true; + } else { + EscSeqReqStats.Remove (found); + } + return false; + } + } + } +} diff --git a/Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs b/Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs new file mode 100644 index 000000000..bfee2030f --- /dev/null +++ b/Terminal.Gui/Core/EscSeqUtils/EscSeqUtils.cs @@ -0,0 +1,907 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Management; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Terminal.Gui { + /// + /// Provides a platform-independent API for managing ANSI escape sequence codes. + /// + public static class EscSeqUtils { + /// + /// Represents the escape key. + /// + public static readonly char KeyEsc = (char)Key.Esc; + /// + /// Represents the CSI (Control Sequence Introducer). + /// + public static readonly string KeyCSI = $"{KeyEsc}["; + /// + /// Represents the CSI for enable any mouse event tracking. + /// + public static readonly string CSI_EnableAnyEventMouse = KeyCSI + "?1003h"; + /// + /// Represents the CSI for enable SGR (Select Graphic Rendition). + /// + public static readonly string CSI_EnableSgrExtModeMouse = KeyCSI + "?1006h"; + /// + /// Represents the CSI for enable URXVT (Unicode Extended Virtual Terminal). + /// + public static readonly string CSI_EnableUrxvtExtModeMouse = KeyCSI + "?1015h"; + /// + /// Represents the CSI for disable any mouse event tracking. + /// + public static readonly string CSI_DisableAnyEventMouse = KeyCSI + "?1003l"; + /// + /// Represents the CSI for disable SGR (Select Graphic Rendition). + /// + public static readonly string CSI_DisableSgrExtModeMouse = KeyCSI + "?1006l"; + /// + /// Represents the CSI for disable URXVT (Unicode Extended Virtual Terminal). + /// + public static readonly string CSI_DisableUrxvtExtModeMouse = KeyCSI + "?1015l"; + + /// + /// Control sequence for enable mouse events. + /// + public static string EnableMouseEvents { get; set; } = + CSI_EnableAnyEventMouse + CSI_EnableUrxvtExtModeMouse + CSI_EnableSgrExtModeMouse; + /// + /// Control sequence for disable mouse events. + /// + public static string DisableMouseEvents { get; set; } = + CSI_DisableAnyEventMouse + CSI_DisableUrxvtExtModeMouse + CSI_DisableSgrExtModeMouse; + + /// + /// Ensures a console key is mapped to one that works correctly with ANSI escape sequences. + /// + /// The . + /// The modified. + public static ConsoleKeyInfo GetConsoleInputKey (ConsoleKeyInfo consoleKeyInfo) + { + ConsoleKeyInfo newConsoleKeyInfo = consoleKeyInfo; + ConsoleKey key; + 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 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; + } + + return newConsoleKeyInfo; + } + + /// + /// A helper to resize the as needed. + /// + /// The . + /// The array to resize. + /// The resized. + public static ConsoleKeyInfo [] ResizeArray (ConsoleKeyInfo consoleKeyInfo, ConsoleKeyInfo [] cki) + { + Array.Resize (ref cki, cki == null ? 1 : cki.Length + 1); + cki [cki.Length - 1] = consoleKeyInfo; + return cki; + } + + /// + /// Decodes a escape sequence to been processed in the appropriate manner. + /// + /// The which may contain a request. + /// The which may changes. + /// The which may changes. + /// The array. + /// The which may changes. + /// The control returned by the method. + /// The code returned by the method. + /// The values returned by the method. + /// The terminating returned by the method. + /// Indicates if the escape sequence is a mouse key. + /// The button state. + /// The position. + /// Indicates if the escape sequence is a response to a request. + /// The handler that will process the event. + public static void DecodeEscSeq (EscSeqReqProc escSeqReqProc, ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ConsoleKeyInfo [] cki, ref ConsoleModifiers mod, out string c1Control, out string code, out string [] values, out string terminating, out bool isKeyMouse, out List buttonState, out Point pos, out bool isReq, Action continuousButtonPressedHandler) + { + char [] kChars = GetKeyCharArray (cki); + (c1Control, code, values, terminating) = GetEscapeResult (kChars); + isKeyMouse = false; + buttonState = new List () { 0 }; + pos = default; + isReq = false; + switch (c1Control) { + case "ESC": + if (values == null && string.IsNullOrEmpty (terminating)) { + key = ConsoleKey.Escape; + newConsoleKeyInfo = new ConsoleKeyInfo (cki [0].KeyChar, key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + } else 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 "SS3": + key = GetConsoleKey (terminating [0], values [0], ref mod); + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + break; + case "CSI": + if (!string.IsNullOrEmpty (code) && code == "<") { + GetMouse (cki, out buttonState, out pos, continuousButtonPressedHandler); + isKeyMouse = true; + return; + } else if (escSeqReqProc != null && escSeqReqProc.Requested (terminating)) { + isReq = true; + escSeqReqProc.Remove (terminating); + return; + } + key = GetConsoleKey (terminating [0], values [0], ref mod); + if (key != 0 && values.Length > 1) { + mod |= GetConsoleModifiers (values [1]); + } + newConsoleKeyInfo = new ConsoleKeyInfo ('\0', + key, + (mod & ConsoleModifiers.Shift) != 0, + (mod & ConsoleModifiers.Alt) != 0, + (mod & ConsoleModifiers.Control) != 0); + break; + } + } + + /// + /// Gets all the needed information about a escape sequence. + /// + /// The array with all chars. + /// + /// The c1Control returned by , code, values and terminating. + /// + public static (string c1Control, string code, string [] values, string terminating) GetEscapeResult (char [] kChar) + { + if (kChar == null || kChar.Length == 0) { + return (null, null, null, null); + } + if (kChar [0] != '\x1b') { + throw new InvalidOperationException ("Invalid escape character!"); + } + if (kChar.Length == 1) { + return ("ESC", null, null, null); + } + if (kChar.Length == 2) { + return ("ESC", null, null, kChar [1].ToString ()); + } + string c1Control = GetC1ControlChar (kChar [1]); + string code = null; + int nSep = kChar.Count (x => x == ';') + 1; + string [] values = new string [nSep]; + int valueIdx = 0; + string terminating = ""; + for (int i = 2; i < kChar.Length; i++) { + var c = kChar [i]; + if (char.IsDigit (c)) { + values [valueIdx] += c.ToString (); + } else if (c == ';') { + valueIdx++; + } else if (valueIdx == nSep - 1 || i == kChar.Length - 1) { + terminating += c.ToString (); + } else { + code += c.ToString (); + } + } + + return (c1Control, code, values, terminating); + } + + /// + /// Gets the c1Control used in the called escape sequence. + /// + /// The char used. + /// The c1Control. + public static string GetC1ControlChar (char c) + { + // These control characters are used in the vtXXX emulation. + switch (c) { + case 'D': + return "IND"; // Index + case 'E': + return "NEL"; // Next Line + case 'H': + return "HTS"; // Tab Set + case 'M': + return "RI"; // Reverse Index + case 'N': + return "SS2"; // Single Shift Select of G2 Character Set: affects next character only + case 'O': + return "SS3"; // Single Shift Select of G3 Character Set: affects next character only + case 'P': + return "DCS"; // Device Control String + case 'V': + return "SPA"; // Start of Guarded Area + case 'W': + return "EPA"; // End of Guarded Area + case 'X': + return "SOS"; // Start of String + case 'Z': + return "DECID"; // Return Terminal ID Obsolete form of CSI c (DA) + case '[': + return "CSI"; // Control Sequence Introducer + case '\\': + return "ST"; // String Terminator + case ']': + return "OSC"; // Operating System Command + case '^': + return "PM"; // Privacy Message + case '_': + return "APC"; // Application Program Command + default: + return ""; // Not supported + } + } + + /// + /// Gets the from the value. + /// + /// The value. + /// The or zero. + public static ConsoleModifiers GetConsoleModifiers (string value) + { + switch (value) { + case "2": + return ConsoleModifiers.Shift; + case "3": + return ConsoleModifiers.Alt; + case "4": + return ConsoleModifiers.Shift | ConsoleModifiers.Alt; + case "5": + return ConsoleModifiers.Control; + case "6": + return ConsoleModifiers.Shift | ConsoleModifiers.Control; + case "7": + return ConsoleModifiers.Alt | ConsoleModifiers.Control; + case "8": + return ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control; + default: + return 0; + } + } + + /// + /// Gets the depending on terminating and value. + /// + /// The terminating. + /// The value. + /// The which may changes. + /// The and probably the . + public static ConsoleKey GetConsoleKey (char terminating, string value, ref ConsoleModifiers mod) + { + ConsoleKey key; + switch (terminating) { + 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 '~': + switch (value) { + case "2": + key = ConsoleKey.Insert; + break; + case "3": + key = ConsoleKey.Delete; + break; + case "5": + key = ConsoleKey.PageUp; + break; + case "6": + key = ConsoleKey.PageDown; + break; + case "15": + key = ConsoleKey.F5; + break; + case "17": + key = ConsoleKey.F6; + break; + case "18": + key = ConsoleKey.F7; + break; + case "19": + key = ConsoleKey.F8; + break; + case "20": + key = ConsoleKey.F9; + break; + case "21": + key = ConsoleKey.F10; + break; + case "23": + key = ConsoleKey.F11; + break; + case "24": + key = ConsoleKey.F12; + break; + default: + key = 0; + break; + } + break; + default: + key = 0; + break; + } + + return key; + } + + /// + /// A helper to get only the from the array. + /// + /// + /// The char array of the escape sequence. + public static 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; + } + + private static MouseFlags? lastMouseButtonPressed; + //private static MouseFlags? lastMouseButtonReleased; + private static bool isButtonPressed; + //private static bool isButtonReleased; + private static bool isButtonClicked; + private static bool isButtonDoubleClicked; + private static bool isButtonTripleClicked; + private static Point point; + + /// + /// Gets the mouse button flags and the position. + /// + /// The array. + /// The mouse button flags. + /// The mouse position. + /// The handler that will process the event. + public static void GetMouse (ConsoleKeyInfo [] cki, out List mouseFlags, out Point pos, Action continuousButtonPressedHandler) + { + MouseFlags buttonState = 0; + pos = 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) { + pos.X = int.Parse (value) - 1; + } + value = ""; + foundPoint++; + } else if (foundPoint > 0 && c != 'm' && c != 'M') { + value += c.ToString (); + } else if (c == 'm' || c == 'M') { + //pos.Y = int.Parse (value) + Console.WindowTop - 1; + pos.Y = int.Parse (value) - 1; + + switch (buttonCode) { + case 0: + case 8: + case 16: + case 24: + case 32: + case 36: + case 40: + case 48: + case 56: + buttonState = c == 'M' ? MouseFlags.Button1Pressed + : MouseFlags.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' ? MouseFlags.Button2Pressed + : MouseFlags.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' ? MouseFlags.Button3Pressed + : MouseFlags.Button3Released; + break; + case 35: + //// Needed for Windows OS + //if (isButtonPressed && c == 'm' + // && (lastMouseEvent.ButtonState == MouseFlags.Button1Pressed + // || lastMouseEvent.ButtonState == MouseFlags.Button2Pressed + // || lastMouseEvent.ButtonState == MouseFlags.Button3Pressed)) { + + // switch (lastMouseEvent.ButtonState) { + // case MouseFlags.Button1Pressed: + // buttonState = MouseFlags.Button1Released; + // break; + // case MouseFlags.Button2Pressed: + // buttonState = MouseFlags.Button2Released; + // break; + // case MouseFlags.Button3Pressed: + // buttonState = MouseFlags.Button3Released; + // break; + // } + //} else { + // buttonState = MouseFlags.ReportMousePosition; + //} + //break; + case 39: + case 43: + case 47: + case 51: + case 55: + case 59: + case 63: + buttonState = MouseFlags.ReportMousePosition; + break; + case 64: + buttonState = MouseFlags.WheeledUp; + break; + case 65: + buttonState = MouseFlags.WheeledDown; + break; + case 68: + case 72: + case 80: + buttonState = MouseFlags.WheeledLeft; // Shift/Ctrl+WheeledUp + break; + case 69: + case 73: + case 81: + buttonState = MouseFlags.WheeledRight; // Shift/Ctrl+WheeledDown + break; + } + // Modifiers. + switch (buttonCode) { + case 8: + case 9: + case 10: + case 43: + buttonState |= MouseFlags.ButtonAlt; + break; + case 14: + case 47: + buttonState |= MouseFlags.ButtonAlt | MouseFlags.ButtonShift; + break; + case 16: + case 17: + case 18: + case 51: + buttonState |= MouseFlags.ButtonCtrl; + break; + case 22: + case 55: + buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonShift; + break; + case 24: + case 25: + case 26: + case 59: + buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonAlt; + break; + case 30: + case 63: + buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonShift | MouseFlags.ButtonAlt; + break; + case 32: + case 33: + case 34: + buttonState |= MouseFlags.ReportMousePosition; + break; + case 36: + case 37: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonShift; + break; + case 39: + case 68: + case 69: + buttonState |= MouseFlags.ButtonShift; + break; + case 40: + case 41: + case 42: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonAlt; + break; + case 45: + case 46: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonAlt | MouseFlags.ButtonShift; + break; + case 48: + case 49: + case 50: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl; + break; + case 53: + case 54: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonShift; + break; + case 56: + case 57: + case 58: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonAlt; + break; + case 61: + case 62: + buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonShift | MouseFlags.ButtonAlt; + break; + } + } + } + + mouseFlags = new List () { MouseFlags.AllEvents }; + + if (lastMouseButtonPressed != null && !isButtonPressed && !buttonState.HasFlag (MouseFlags.ReportMousePosition) + && !buttonState.HasFlag (MouseFlags.Button1Released) + && !buttonState.HasFlag (MouseFlags.Button2Released) + && !buttonState.HasFlag (MouseFlags.Button3Released) + && !buttonState.HasFlag (MouseFlags.Button4Released)) { + + lastMouseButtonPressed = null; + isButtonPressed = false; + } + + if (!isButtonClicked && !isButtonDoubleClicked && ((buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed || + buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed) && lastMouseButtonPressed == null) || + isButtonPressed && lastMouseButtonPressed != null && buttonState.HasFlag (MouseFlags.ReportMousePosition)) { + + mouseFlags [0] = buttonState; + lastMouseButtonPressed = buttonState; + isButtonPressed = true; + + if ((mouseFlags [0] & MouseFlags.ReportMousePosition) == 0) { + point = new Point () { + X = pos.X, + Y = pos.Y + }; + + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessContinuousButtonPressedAsync (buttonState, continuousButtonPressedHandler)); + return false; + }); + } else if (mouseFlags [0] == MouseFlags.ReportMousePosition) { + isButtonPressed = false; + } + + } else if (isButtonDoubleClicked && (buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed || + buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed)) { + + mouseFlags [0] = GetButtonTripleClicked (buttonState); + isButtonDoubleClicked = false; + isButtonTripleClicked = true; + + } else if (isButtonClicked && (buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed || + buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed)) { + + mouseFlags [0] = GetButtonDoubleClicked (buttonState); + isButtonClicked = false; + isButtonDoubleClicked = true; + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessButtonDoubleClickedAsync ()); + return false; + }); + + } + //else if (isButtonReleased && !isButtonClicked && buttonState == MouseFlags.ReportMousePosition) { + // mouseFlag [0] = GetButtonClicked ((MouseFlags)lastMouseButtonReleased); + // lastMouseButtonReleased = null; + // isButtonReleased = false; + // isButtonClicked = true; + // Application.MainLoop.AddIdle (() => { + // Task.Run (async () => await ProcessButtonClickedAsync ()); + // return false; + // }); + + //} + else if (!isButtonClicked && !isButtonDoubleClicked && (buttonState == MouseFlags.Button1Released || buttonState == MouseFlags.Button2Released || + buttonState == MouseFlags.Button3Released || buttonState == MouseFlags.Button4Released)) { + + mouseFlags [0] = buttonState; + isButtonPressed = false; + + if (isButtonTripleClicked) { + isButtonTripleClicked = false; + } else if (pos.X == point.X && pos.Y == point.Y) { + mouseFlags.Add (GetButtonClicked (buttonState)); + isButtonClicked = true; + Application.MainLoop.AddIdle (() => { + Task.Run (async () => await ProcessButtonClickedAsync ()); + return false; + }); + } + + point = pos; + + //if ((lastMouseButtonPressed & MouseFlags.ReportMousePosition) == 0) { + // lastMouseButtonReleased = buttonState; + // isButtonPressed = false; + // isButtonReleased = true; + //} else { + // lastMouseButtonPressed = null; + // isButtonPressed = false; + //} + + } else if (buttonState == MouseFlags.WheeledUp) { + + mouseFlags [0] = MouseFlags.WheeledUp; + + } else if (buttonState == MouseFlags.WheeledDown) { + + mouseFlags [0] = MouseFlags.WheeledDown; + + } else if (buttonState == MouseFlags.WheeledLeft) { + + mouseFlags [0] = MouseFlags.WheeledLeft; + + } else if (buttonState == MouseFlags.WheeledRight) { + + mouseFlags [0] = MouseFlags.WheeledRight; + + } else if (buttonState == MouseFlags.ReportMousePosition) { + mouseFlags [0] = MouseFlags.ReportMousePosition; + + } else { + mouseFlags [0] = buttonState; + //foreach (var flag in buttonState.GetUniqueFlags()) { + // mouseFlag [0] |= flag; + //} + } + + mouseFlags [0] = SetControlKeyStates (buttonState, mouseFlags [0]); + //buttonState = mouseFlags; + + //System.Diagnostics.Debug.WriteLine ($"buttonState: {buttonState} X: {pos.X} Y: {pos.Y}"); + //foreach (var mf in mouseFlags) { + // System.Diagnostics.Debug.WriteLine ($"mouseFlags: {mf} X: {pos.X} Y: {pos.Y}"); + //} + } + + private static async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag, Action continuousButtonPressedHandler) + { + 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 (() => continuousButtonPressedHandler (mouseFlag, point)); + } + } + } + + private static async Task ProcessButtonClickedAsync () + { + await Task.Delay (300); + isButtonClicked = false; + } + + private static async Task ProcessButtonDoubleClickedAsync () + { + await Task.Delay (300); + isButtonDoubleClicked = false; + } + + private static MouseFlags GetButtonClicked (MouseFlags mouseFlag) + { + MouseFlags mf = default; + switch (mouseFlag) { + case MouseFlags.Button1Released: + mf = MouseFlags.Button1Clicked; + break; + + case MouseFlags.Button2Released: + mf = MouseFlags.Button2Clicked; + break; + + case MouseFlags.Button3Released: + mf = MouseFlags.Button3Clicked; + break; + } + return mf; + } + + private static MouseFlags GetButtonDoubleClicked (MouseFlags mouseFlag) + { + MouseFlags mf = default; + switch (mouseFlag) { + case MouseFlags.Button1Pressed: + mf = MouseFlags.Button1DoubleClicked; + break; + + case MouseFlags.Button2Pressed: + mf = MouseFlags.Button2DoubleClicked; + break; + + case MouseFlags.Button3Pressed: + mf = MouseFlags.Button3DoubleClicked; + break; + } + return mf; + } + + private static MouseFlags GetButtonTripleClicked (MouseFlags mouseFlag) + { + MouseFlags mf = default; + switch (mouseFlag) { + case MouseFlags.Button1Pressed: + mf = MouseFlags.Button1TripleClicked; + break; + + case MouseFlags.Button2Pressed: + mf = MouseFlags.Button2TripleClicked; + break; + + case MouseFlags.Button3Pressed: + mf = MouseFlags.Button3TripleClicked; + break; + } + return mf; + } + + private static MouseFlags SetControlKeyStates (MouseFlags buttonState, MouseFlags mouseFlag) + { + if ((buttonState & MouseFlags.ButtonCtrl) != 0 && (mouseFlag & MouseFlags.ButtonCtrl) == 0) + mouseFlag |= MouseFlags.ButtonCtrl; + + if ((buttonState & MouseFlags.ButtonShift) != 0 && (mouseFlag & MouseFlags.ButtonShift) == 0) + mouseFlag |= MouseFlags.ButtonShift; + + if ((buttonState & MouseFlags.ButtonAlt) != 0 && (mouseFlag & MouseFlags.ButtonAlt) == 0) + mouseFlag |= MouseFlags.ButtonAlt; + return mouseFlag; + } + + /// + /// Get the terminal that holds the console driver. + /// + /// The process. + /// If supported the executable console process, null otherwise. + public static Process GetParentProcess (Process process) + { + if (!RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) { + return null; + } + + string query = "SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = " + process.Id; + using (ManagementObjectSearcher mos = new ManagementObjectSearcher (query)) { + foreach (ManagementObject mo in mos.Get ()) { + if (mo ["ParentProcessId"] != null) { + try { + var id = Convert.ToInt32 (mo ["ParentProcessId"]); + return Process.GetProcessById (id); + } catch { + } + } + } + } + return null; + } + } +} diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Core/Event.cs index 4203faa86..a46bbf7e5 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 up. + /// Vertical button wheeled down. /// WheeledDown = unchecked((int)0x20000000), /// diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index e92806346..0bab49cbf 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -53,6 +53,7 @@ + net472;netstandard2.0;net6.0 diff --git a/UICatalog/Properties/launchSettings.json b/UICatalog/Properties/launchSettings.json index b4df9cb03..4fe02b923 100644 --- a/UICatalog/Properties/launchSettings.json +++ b/UICatalog/Properties/launchSettings.json @@ -3,6 +3,12 @@ "UICatalog": { "commandName": "Project" }, + "WSL : UICatalog": { + "commandName": "Executable", + "executablePath": "wsl", + "commandLineArgs": "dotnet UICatalog.dll", + "distributionName": "" + }, "UICatalog -usc": { "commandName": "Project", "commandLineArgs": "-usc" @@ -29,10 +35,6 @@ "commandName": "Project", "commandLineArgs": "WizardAsView" }, - "VkeyPacketSimulator": { - "commandName": "Project", - "commandLineArgs": "VkeyPacketSimulator" - }, "CollectionNavigatorTester": { "commandName": "Project", "commandLineArgs": "\"Search Collection Nav\"" @@ -48,12 +50,6 @@ "Windows & FrameViews": { "commandName": "Project", "commandLineArgs": "\"Windows & FrameViews\"" - }, - "WSL : UICatalog": { - "commandName": "Executable", - "executablePath": "wsl", - "commandLineArgs": "dotnet UICatalog.dll", - "distributionName": "" } } } \ No newline at end of file diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index c115bb957..b49d70312 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -120,6 +120,9 @@ 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 (); @@ -141,7 +144,7 @@ namespace UICatalog { static bool _useSystemConsole = false; static ConsoleDriver.DiagnosticFlags _diagnosticFlags; - static bool _heightAsBuffer = false; + static bool _enableConsoleScrolling = false; static bool _isFirstRunning = true; static ColorScheme _colorScheme; @@ -151,7 +154,7 @@ namespace UICatalog { /// class UICatalogTopLevel : Toplevel { public MenuItem miIsMouseDisabled; - public MenuItem miHeightAsBuffer; + public MenuItem miEnableConsoleScrolling; public FrameView LeftPane; public ListView CategoryListView; @@ -180,7 +183,7 @@ namespace UICatalog { "About UI Catalog", () => MessageBox.Query ("About UI Catalog", _aboutMessage.ToString(), "_Ok"), null, null, Key.CtrlMask | Key.A), }), }); - + Capslock = new StatusItem (Key.CharMask, "Caps", null); Numlock = new StatusItem (Key.CharMask, "Num", null); Scrolllock = new StatusItem (Key.CharMask, "Scroll", null); @@ -274,14 +277,12 @@ namespace UICatalog { void LoadedHandler () { - Application.HeightAsBuffer = _heightAsBuffer; - if (_colorScheme == null) { ColorScheme = _colorScheme = Colors.Base; } miIsMouseDisabled.Checked = Application.IsMouseDisabled; - miHeightAsBuffer.Checked = Application.HeightAsBuffer; + miEnableConsoleScrolling.Checked = Application.EnableConsoleScrolling; DriverName.Title = $"Driver: {Driver.GetType ().Name}"; OS.Title = $"OS: {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem} {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion}"; @@ -318,7 +319,7 @@ namespace UICatalog { List menuItems = new List (); menuItems.Add (CreateDiagnosticFlagsMenuItems ()); menuItems.Add (new MenuItem [] { null }); - menuItems.Add (CreateHeightAsBufferMenuItems ()); + menuItems.Add (CreateEnableConsoleScrollingMenuItems ()); menuItems.Add (CreateDisabledEnabledMouseItems ()); menuItems.Add (CreateKeybindingsMenuItems ()); return menuItems; @@ -356,18 +357,18 @@ namespace UICatalog { return menuItems.ToArray (); } - MenuItem [] CreateHeightAsBufferMenuItems () + MenuItem [] CreateEnableConsoleScrollingMenuItems () { List menuItems = new List (); - miHeightAsBuffer = new MenuItem (); - miHeightAsBuffer.Title = "_Height As Buffer"; - miHeightAsBuffer.Shortcut = Key.CtrlMask | Key.AltMask | (Key)miHeightAsBuffer.Title.ToString ().Substring (1, 1) [0]; - miHeightAsBuffer.CheckType |= MenuItemCheckStyle.Checked; - miHeightAsBuffer.Action += () => { - miHeightAsBuffer.Checked = !miHeightAsBuffer.Checked; - Application.HeightAsBuffer = miHeightAsBuffer.Checked; + miEnableConsoleScrolling = new MenuItem (); + miEnableConsoleScrolling.Title = "_Enable Console Scrolling"; + miEnableConsoleScrolling.Shortcut = Key.CtrlMask | Key.AltMask | (Key)miEnableConsoleScrolling.Title.ToString ().Substring (1, 1) [0]; + miEnableConsoleScrolling.CheckType |= MenuItemCheckStyle.Checked; + miEnableConsoleScrolling.Action += () => { + miEnableConsoleScrolling.Checked = !miEnableConsoleScrolling.Checked; + Application.EnableConsoleScrolling = miEnableConsoleScrolling.Checked; }; - menuItems.Add (miHeightAsBuffer); + menuItems.Add (miEnableConsoleScrolling); return menuItems.ToArray (); } diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 7228d8ad6..637174d17 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -24,6 +24,7 @@ namespace Terminal.Gui.ApplicationTests { Assert.Null (Application.Driver); Assert.Null (Application.Top); Assert.Null (Application.Current); + Assert.False (Application.EnableConsoleScrolling); Assert.Null (Application.MainLoop); Assert.Null (Application.Iteration); Assert.Null (Application.RootMouseEvent); @@ -35,7 +36,7 @@ namespace Terminal.Gui.ApplicationTests { Assert.NotNull (Application.Driver); Assert.NotNull (Application.Top); Assert.NotNull (Application.Current); - Assert.False (Application.HeightAsBuffer); + Assert.False (Application.EnableConsoleScrolling); Assert.NotNull (Application.MainLoop); Assert.Null (Application.Iteration); Assert.Null (Application.RootMouseEvent); @@ -312,7 +313,7 @@ namespace Terminal.Gui.ApplicationTests { public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws () { Init (); - + Application.Driver = null; Application.Iteration = () => { @@ -332,8 +333,8 @@ namespace Terminal.Gui.ApplicationTests { [Fact] public void Run_T_NoInit_DoesNotThrow () { - Application.ForceFakeConsole = true; - + Application.ForceFakeConsole = true; + Application.Iteration = () => { Application.RequestStop (); }; @@ -429,7 +430,7 @@ namespace Terminal.Gui.ApplicationTests { } // TODO: Add tests for Run that test errorHandler - + #endregion #region ShutdownTests diff --git a/UnitTests/Core/EscSeqReqTests.cs b/UnitTests/Core/EscSeqReqTests.cs new file mode 100644 index 000000000..33f955d49 --- /dev/null +++ b/UnitTests/Core/EscSeqReqTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace Terminal.Gui.CoreTests { + public class EscSeqReqTests { + [Fact] + public void Constructor_Defaults () + { + var escSeqReq = new EscSeqReqProc (); + Assert.NotNull (escSeqReq.EscSeqReqStats); + Assert.Empty (escSeqReq.EscSeqReqStats); + } + + [Fact] + public void Add_Tests () + { + var escSeqReq = new EscSeqReqProc (); + escSeqReq.Add ("t"); + Assert.Single (escSeqReq.EscSeqReqStats); + Assert.Equal ("t", escSeqReq.EscSeqReqStats [^1].Terminating); + Assert.Equal (1, escSeqReq.EscSeqReqStats [^1].NumRequests); + Assert.Equal (1, escSeqReq.EscSeqReqStats [^1].NumOutstanding); + + escSeqReq.Add ("t", 2); + Assert.Single (escSeqReq.EscSeqReqStats); + Assert.Equal ("t", escSeqReq.EscSeqReqStats [^1].Terminating); + Assert.Equal (1, escSeqReq.EscSeqReqStats [^1].NumRequests); + Assert.Equal (1, escSeqReq.EscSeqReqStats [^1].NumOutstanding); + + escSeqReq = new EscSeqReqProc (); + escSeqReq.Add ("t", 2); + Assert.Single (escSeqReq.EscSeqReqStats); + Assert.Equal ("t", escSeqReq.EscSeqReqStats [^1].Terminating); + Assert.Equal (2, escSeqReq.EscSeqReqStats [^1].NumRequests); + Assert.Equal (2, escSeqReq.EscSeqReqStats [^1].NumOutstanding); + + escSeqReq.Add ("t", 3); + Assert.Single (escSeqReq.EscSeqReqStats); + Assert.Equal ("t", escSeqReq.EscSeqReqStats [^1].Terminating); + Assert.Equal (2, escSeqReq.EscSeqReqStats [^1].NumRequests); + Assert.Equal (2, escSeqReq.EscSeqReqStats [^1].NumOutstanding); + } + + [Fact] + public void Remove_Tests () + { + var escSeqReq = new EscSeqReqProc (); + escSeqReq.Add ("t"); + escSeqReq.Remove ("t"); + Assert.Empty (escSeqReq.EscSeqReqStats); + + escSeqReq.Add ("t", 2); + escSeqReq.Remove ("t"); + Assert.Single (escSeqReq.EscSeqReqStats); + Assert.Equal ("t", escSeqReq.EscSeqReqStats [^1].Terminating); + Assert.Equal (2, escSeqReq.EscSeqReqStats [^1].NumRequests); + Assert.Equal (1, escSeqReq.EscSeqReqStats [^1].NumOutstanding); + + escSeqReq.Remove ("t"); + Assert.Empty (escSeqReq.EscSeqReqStats); + } + + [Fact] + public void Requested_Tests () + { + var escSeqReq = new EscSeqReqProc (); + Assert.False (escSeqReq.Requested ("t")); + + escSeqReq.Add ("t"); + Assert.False (escSeqReq.Requested ("r")); + Assert.True (escSeqReq.Requested ("t")); + } + } +} diff --git a/UnitTests/Core/EscSeqUtilsTests.cs b/UnitTests/Core/EscSeqUtilsTests.cs new file mode 100644 index 000000000..6db843ffe --- /dev/null +++ b/UnitTests/Core/EscSeqUtilsTests.cs @@ -0,0 +1,870 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using Xunit; + +namespace Terminal.Gui.CoreTests { + public class EscSeqUtilsTests { + [Fact] + public void Defaults_Values () + { + Assert.Equal ('\x1b', EscSeqUtils.KeyEsc); + Assert.Equal ("\x1b[", EscSeqUtils.KeyCSI); + Assert.Equal ("\x1b[?1003h", EscSeqUtils.CSI_EnableAnyEventMouse); + Assert.Equal ("\x1b[?1006h", EscSeqUtils.CSI_EnableSgrExtModeMouse); + Assert.Equal ("\x1b[?1015h", EscSeqUtils.CSI_EnableUrxvtExtModeMouse); + Assert.Equal ("\x1b[?1003l", EscSeqUtils.CSI_DisableAnyEventMouse); + Assert.Equal ("\x1b[?1006l", EscSeqUtils.CSI_DisableSgrExtModeMouse); + Assert.Equal ("\x1b[?1015l", EscSeqUtils.CSI_DisableUrxvtExtModeMouse); + Assert.Equal ("\x1b[?1003h\x1b[?1015h\u001b[?1006h", EscSeqUtils.EnableMouseEvents); + Assert.Equal ("\x1b[?1003l\x1b[?1015l\u001b[?1006l", EscSeqUtils.DisableMouseEvents); + } + + [Fact] + public void GetConsoleInputKey_ConsoleKeyInfo () + { + var cki = new ConsoleKeyInfo ('r', 0, false, false, false); + var expectedCki = new ConsoleKeyInfo ('r', 0, false, false, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, true, false, false); + expectedCki = new ConsoleKeyInfo ('r', 0, true, false, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, false, true, false); + expectedCki = new ConsoleKeyInfo ('r', 0, false, true, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, false, false, true); + expectedCki = new ConsoleKeyInfo ('r', 0, false, false, true); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, true, true, false); + expectedCki = new ConsoleKeyInfo ('r', 0, true, true, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, false, true, true); + expectedCki = new ConsoleKeyInfo ('r', 0, false, true, true); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('r', 0, true, true, true); + expectedCki = new ConsoleKeyInfo ('r', 0, true, true, true); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('\u0012', 0, false, false, false); + expectedCki = new ConsoleKeyInfo ('R', ConsoleKey.R, false, false, true); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('\0', (ConsoleKey)64, false, false, true); + expectedCki = new ConsoleKeyInfo (' ', ConsoleKey.Spacebar, false, false, true); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('\r', 0, false, false, false); + expectedCki = new ConsoleKeyInfo ('\r', ConsoleKey.Enter, false, false, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('\u007f', 0, false, false, false); + expectedCki = new ConsoleKeyInfo ('\u007f', ConsoleKey.Backspace, false, false, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + + cki = new ConsoleKeyInfo ('R', 0, false, false, false); + expectedCki = new ConsoleKeyInfo ('R', 0, false, false, false); + Assert.Equal (expectedCki, EscSeqUtils.GetConsoleInputKey (cki)); + } + + [Fact] + public void ResizeArray_ConsoleKeyInfo () + { + ConsoleKeyInfo [] expectedCkInfos = null; + var cki = new ConsoleKeyInfo ('\u001b', ConsoleKey.Escape, false, false, false); + expectedCkInfos = EscSeqUtils.ResizeArray (cki, expectedCkInfos); + Assert.Single (expectedCkInfos); + Assert.Equal (cki, expectedCkInfos [0]); + } + + private EscSeqReqProc escSeqReqProc; + private ConsoleKeyInfo newConsoleKeyInfo; + private ConsoleKey key; + private ConsoleKeyInfo [] cki; + private ConsoleModifiers mod; + private string c1Control, code, terminating; + private string [] values; + private bool isKeyMouse; + private bool isReq; + private List mouseFlags; + Point pos; + private MouseFlags arg1; + private Point arg2; + private bool actionStarted; + + [Fact, AutoInitShutdown] + public void DecodeEscSeq_Tests () + { + // ESC + cki = new ConsoleKeyInfo [] { new ConsoleKeyInfo ('\u001b', 0, false, false, false) }; + var expectedCki = new ConsoleKeyInfo ('\u001b', ConsoleKey.Escape, false, false, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.Escape, key); + Assert.Equal (0, (int)mod); + Assert.Equal ("ESC", c1Control); + Assert.Null (code); + Assert.Null (values); + Assert.Null (terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('\u0012', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\u0012', ConsoleKey.R, false, true, true); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.R, key); + Assert.Equal (0, (int)mod); + Assert.Equal ("ESC", c1Control); + Assert.Null (code); + Assert.Null (values); + Assert.Equal ("\u0012", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('r', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('R', ConsoleKey.R, false, true, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.R, key); + Assert.Equal (0, (int)mod); + Assert.Equal ("ESC", c1Control); + Assert.Null (code); + Assert.Null (values); + Assert.Equal ("r", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + // SS3 + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('O', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, false, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (0, (int)mod); + Assert.Equal ("SS3", c1Control); + Assert.Null (code); + Assert.Single (values); + Assert.Null (values [0]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + // CSI + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, true, false, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Shift, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("2", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, true, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Alt, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('4', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, true, true, false); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Alt, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("4", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('5', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, false, true); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Control, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("5", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('6', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, true, false, true); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Control, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("6", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('7', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, false, true, true); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Alt | ConsoleModifiers.Control, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("7", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('8', 0, false, false, false), + new ConsoleKeyInfo ('R', 0, false, false, false) + }; + expectedCki = new ConsoleKeyInfo ('\0', ConsoleKey.F3, true, true, true); + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (ConsoleKey.F3, key); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control, mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("1", values [0]); + Assert.Equal ("8", values [^1]); + Assert.Equal ("R", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("M", terminating); + Assert.True (isKeyMouse); + Assert.Equal (new List () { MouseFlags.Button1Pressed }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('m', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("m", terminating); + Assert.True (isKeyMouse); + Assert.Equal (2, mouseFlags.Count); + Assert.Equal (new List () { MouseFlags.Button1Released, MouseFlags.Button1Clicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("M", terminating); + Assert.True (isKeyMouse); + Assert.Equal (new List () { MouseFlags.Button1DoubleClicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("M", terminating); + Assert.True (isKeyMouse); + Assert.Equal (new List () { MouseFlags.Button1TripleClicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + + var view = new View () { + Width = Dim.Fill (), + Height = Dim.Fill (), + WantContinuousButtonPressed = true + }; + Application.Top.Add (view); + Application.Begin (Application.Top); + + ReflectionTools.InvokePrivate ( + typeof (Application), + "ProcessMouseEvent", + new MouseEvent () { + X = 0, + Y = 0, + Flags = 0 + }); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("M", terminating); + Assert.True (isKeyMouse); + Assert.Equal (new List () { MouseFlags.Button1Pressed }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + + Application.Iteration += () => { + if (actionStarted) { + // set Application.WantContinuousButtonPressedView to null + view.WantContinuousButtonPressed = false; + ReflectionTools.InvokePrivate ( + typeof (Application), + "ProcessMouseEvent", + new MouseEvent () { + X = 0, + Y = 0, + Flags = 0 + }); + + Application.RequestStop (); + } + }; + + Application.Run (); + + Assert.Null (Application.WantContinuousButtonPressedView); + + Assert.Equal (MouseFlags.Button1Pressed, arg1); + Assert.Equal (new Point (1, 2), arg2); + + ClearAll (); + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('m', 0, false, false, false) + }; + expectedCki = default; + 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); + Assert.Null (escSeqReqProc); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Equal ("<", code); + Assert.Equal (3, values.Length); + Assert.Equal ("0", values [0]); + Assert.Equal ("2", values [1]); + Assert.Equal ("3", values [^1]); + Assert.Equal ("m", terminating); + Assert.True (isKeyMouse); + Assert.Equal (new List () { MouseFlags.Button1Released }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + Assert.False (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + + ClearAll (); + + Assert.Null (escSeqReqProc); + escSeqReqProc = new EscSeqReqProc (); + escSeqReqProc.Add ("t"); + + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('8', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('1', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo ('t', 0, false, false, false) + }; + expectedCki = default; + Assert.Single (escSeqReqProc.EscSeqReqStats); + Assert.Equal ("t", escSeqReqProc.EscSeqReqStats [^1].Terminating); + 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); + Assert.Empty (escSeqReqProc.EscSeqReqStats); + Assert.Equal (expectedCki, newConsoleKeyInfo); + Assert.Equal (0, (int)key); + Assert.Equal (0, (int)mod); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (3, values.Length); + Assert.Equal ("8", values [0]); + Assert.Equal ("10", values [1]); + Assert.Equal ("20", values [^1]); + Assert.Equal ("t", terminating); + Assert.False (isKeyMouse); + Assert.Equal (new List () { 0 }, mouseFlags); + Assert.Equal (Point.Empty, pos); + Assert.True (isReq); + Assert.Equal (0, (int)arg1); + Assert.Equal (Point.Empty, arg2); + } + + private void ClearAll () + { + escSeqReqProc = default; + newConsoleKeyInfo = default; + key = default; + cki = default; + mod = default; + c1Control = default; + code = default; + terminating = default; + values = default; + isKeyMouse = default; + isReq = default; + mouseFlags = default; + pos = default; + arg1 = default; + arg2 = default; + } + + private void ProcessContinuousButtonPressed (MouseFlags arg1, Point arg2) + { + this.arg1 = arg1; + this.arg2 = arg2; + actionStarted = true; + } + + [Fact] + public void GetEscapeResult_Tests () + { + char [] kChars = new char [] { '\u001b', '[', '5', ';', '1', '0', 'r' }; + (c1Control, code, values, terminating) = EscSeqUtils.GetEscapeResult (kChars); + Assert.Equal ("CSI", c1Control); + Assert.Null (code); + Assert.Equal (2, values.Length); + Assert.Equal ("5", values [0]); + Assert.Equal ("10", values [^1]); + Assert.Equal ("r", terminating); + } + + [Fact] + public void GetC1ControlChar_Tests () + { + Assert.Equal ("IND", EscSeqUtils.GetC1ControlChar ('D')); + Assert.Equal ("NEL", EscSeqUtils.GetC1ControlChar ('E')); + Assert.Equal ("HTS", EscSeqUtils.GetC1ControlChar ('H')); + Assert.Equal ("RI", EscSeqUtils.GetC1ControlChar ('M')); + Assert.Equal ("SS2", EscSeqUtils.GetC1ControlChar ('N')); + Assert.Equal ("SS3", EscSeqUtils.GetC1ControlChar ('O')); + Assert.Equal ("DCS", EscSeqUtils.GetC1ControlChar ('P')); + Assert.Equal ("SPA", EscSeqUtils.GetC1ControlChar ('V')); + Assert.Equal ("EPA", EscSeqUtils.GetC1ControlChar ('W')); + Assert.Equal ("SOS", EscSeqUtils.GetC1ControlChar ('X')); + Assert.Equal ("DECID", EscSeqUtils.GetC1ControlChar ('Z')); + Assert.Equal ("CSI", EscSeqUtils.GetC1ControlChar ('[')); + Assert.Equal ("ST", EscSeqUtils.GetC1ControlChar ('\\')); + Assert.Equal ("OSC", EscSeqUtils.GetC1ControlChar (']')); + Assert.Equal ("PM", EscSeqUtils.GetC1ControlChar ('^')); + Assert.Equal ("APC", EscSeqUtils.GetC1ControlChar ('_')); + Assert.Equal ("", EscSeqUtils.GetC1ControlChar ('\0')); + } + + [Fact] + public void GetConsoleModifiers_Tests () + { + Assert.Equal (ConsoleModifiers.Shift, EscSeqUtils.GetConsoleModifiers ("2")); + Assert.Equal (ConsoleModifiers.Alt, EscSeqUtils.GetConsoleModifiers ("3")); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Alt, EscSeqUtils.GetConsoleModifiers ("4")); + Assert.Equal (ConsoleModifiers.Control, EscSeqUtils.GetConsoleModifiers ("5")); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Control, EscSeqUtils.GetConsoleModifiers ("6")); + Assert.Equal (ConsoleModifiers.Alt | ConsoleModifiers.Control, EscSeqUtils.GetConsoleModifiers ("7")); + Assert.Equal (ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control, EscSeqUtils.GetConsoleModifiers ("8")); + Assert.Equal (0, (int)EscSeqUtils.GetConsoleModifiers ("")); + } + + [Fact] + public void GetConsoleKey_Tests () + { + ConsoleModifiers mod = 0; + Assert.Equal (ConsoleKey.UpArrow, EscSeqUtils.GetConsoleKey ('A', "", ref mod)); + Assert.Equal (ConsoleKey.DownArrow, EscSeqUtils.GetConsoleKey ('B', "", ref mod)); + Assert.Equal (key = ConsoleKey.RightArrow, EscSeqUtils.GetConsoleKey ('C', "", ref mod)); + Assert.Equal (ConsoleKey.LeftArrow, EscSeqUtils.GetConsoleKey ('D', "", ref mod)); + Assert.Equal (ConsoleKey.End, EscSeqUtils.GetConsoleKey ('F', "", ref mod)); + Assert.Equal (ConsoleKey.Home, EscSeqUtils.GetConsoleKey ('H', "", ref mod)); + Assert.Equal (ConsoleKey.F1, EscSeqUtils.GetConsoleKey ('P', "", ref mod)); + Assert.Equal (ConsoleKey.F2, EscSeqUtils.GetConsoleKey ('Q', "", ref mod)); + Assert.Equal (ConsoleKey.F3, EscSeqUtils.GetConsoleKey ('R', "", ref mod)); + Assert.Equal (ConsoleKey.F4, EscSeqUtils.GetConsoleKey ('S', "", ref mod)); + Assert.Equal (ConsoleKey.Tab, EscSeqUtils.GetConsoleKey ('Z', "", ref mod)); + Assert.Equal (ConsoleModifiers.Shift, mod); + Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('\0', "", ref mod)); + Assert.Equal (ConsoleKey.Insert, EscSeqUtils.GetConsoleKey ('~', "2", ref mod)); + Assert.Equal (ConsoleKey.Delete, EscSeqUtils.GetConsoleKey ('~', "3", ref mod)); + Assert.Equal (ConsoleKey.PageUp, EscSeqUtils.GetConsoleKey ('~', "5", ref mod)); + Assert.Equal (ConsoleKey.PageDown, EscSeqUtils.GetConsoleKey ('~', "6", ref mod)); + Assert.Equal (ConsoleKey.F5, EscSeqUtils.GetConsoleKey ('~', "15", ref mod)); + Assert.Equal (ConsoleKey.F6, EscSeqUtils.GetConsoleKey ('~', "17", ref mod)); + Assert.Equal (ConsoleKey.F7, EscSeqUtils.GetConsoleKey ('~', "18", ref mod)); + Assert.Equal (ConsoleKey.F8, EscSeqUtils.GetConsoleKey ('~', "19", ref mod)); + Assert.Equal (ConsoleKey.F9, EscSeqUtils.GetConsoleKey ('~', "20", ref mod)); + Assert.Equal (ConsoleKey.F10, EscSeqUtils.GetConsoleKey ('~', "21", ref mod)); + Assert.Equal (ConsoleKey.F11, EscSeqUtils.GetConsoleKey ('~', "23", ref mod)); + Assert.Equal (ConsoleKey.F12, EscSeqUtils.GetConsoleKey ('~', "24", ref mod)); + Assert.Equal (0, (int)EscSeqUtils.GetConsoleKey ('~', "", ref mod)); + } + + [Fact] + public void GetKeyCharArray_Tests () + { + var cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo('\u001b', 0, false, false, false), + new ConsoleKeyInfo('[', 0, false, false, false), + new ConsoleKeyInfo('5', 0, false, false, false), + new ConsoleKeyInfo(';', 0, false, false, false), + new ConsoleKeyInfo('1', 0, false, false, false), + new ConsoleKeyInfo('0', 0, false, false, false), + new ConsoleKeyInfo('r', 0, false, false, false), + }; + + Assert.Equal (new char [] { '\u001b', '[', '5', ';', '1', '0', 'r' }, EscSeqUtils.GetKeyCharArray (cki)); + } + + [Fact, AutoInitShutdown] + public void GetMouse_Tests () + { + var cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + EscSeqUtils.GetMouse (cki, out List mouseFlags, out Point pos, ProcessContinuousButtonPressed); + Assert.Equal (new List () { MouseFlags.Button1Pressed }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('m', 0, false, false, false) + }; + EscSeqUtils.GetMouse (cki, out mouseFlags, out pos, ProcessContinuousButtonPressed); + Assert.Equal (2, mouseFlags.Count); + Assert.Equal (new List () { MouseFlags.Button1Released, MouseFlags.Button1Clicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + EscSeqUtils.GetMouse (cki, out mouseFlags, out pos, ProcessContinuousButtonPressed); + Assert.Equal (new List () { MouseFlags.Button1DoubleClicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('M', 0, false, false, false) + }; + EscSeqUtils.GetMouse (cki, out mouseFlags, out pos, ProcessContinuousButtonPressed); + Assert.Equal (new List () { MouseFlags.Button1TripleClicked }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + + cki = new ConsoleKeyInfo [] { + new ConsoleKeyInfo ('\u001b', 0, false, false, false), + new ConsoleKeyInfo ('[', 0, false, false, false), + new ConsoleKeyInfo ('<', 0, false, false, false), + new ConsoleKeyInfo ('0', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('2', 0, false, false, false), + new ConsoleKeyInfo (';', 0, false, false, false), + new ConsoleKeyInfo ('3', 0, false, false, false), + new ConsoleKeyInfo ('m', 0, false, false, false) + }; + EscSeqUtils.GetMouse (cki, out mouseFlags, out pos, ProcessContinuousButtonPressed); + Assert.Equal (new List () { MouseFlags.Button1Released }, mouseFlags); + Assert.Equal (new Point (1, 2), pos); + } + + [Fact] + public void GetParentProcess_Tests () + { + if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) { + Assert.NotNull (EscSeqUtils.GetParentProcess (Process.GetCurrentProcess ())); + } else { + Assert.Null (EscSeqUtils.GetParentProcess (Process.GetCurrentProcess ())); + } + } + } +} diff --git a/UnitTests/Drivers/ConsoleDriverTests.cs b/UnitTests/Drivers/ConsoleDriverTests.cs index 8289e9737..6444b8f1c 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.HeightAsBuffer = true; + Application.EnableConsoleScrolling = 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 HeightAsBuffer_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) + public void EnableConsoleScrolling_Is_False_Left_And_Top_Is_Always_Zero (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Assert.False (Application.HeightAsBuffer); + Assert.False (Application.EnableConsoleScrolling); Assert.Equal (0, Console.WindowLeft); Assert.Equal (0, Console.WindowTop); @@ -204,13 +204,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void HeightAsBuffer_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) + public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_WindowWidth (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.HeightAsBuffer = true; - Assert.True (Application.HeightAsBuffer); + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); driver.SetWindowPosition (81, 25); Assert.Equal (0, Console.WindowLeft); @@ -221,13 +221,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void HeightAsBuffer_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) + public void EnableConsoleScrolling_Is_True_Left_Cannot_Be_Greater_Than_BufferWidth_Minus_WindowWidth (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.HeightAsBuffer = true; - Assert.True (Application.HeightAsBuffer); + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); driver.SetWindowPosition (81, 25); Assert.Equal (0, Console.WindowLeft); @@ -261,13 +261,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void HeightAsBuffer_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) + public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_WindowHeight (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.HeightAsBuffer = true; - Assert.True (Application.HeightAsBuffer); + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); driver.SetWindowPosition (80, 26); Assert.Equal (0, Console.WindowLeft); @@ -278,13 +278,13 @@ namespace Terminal.Gui.DriverTests { [Theory] [InlineData (typeof (FakeDriver))] - public void HeightAsBuffer_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) + public void EnableConsoleScrolling_Is_True_Top_Cannot_Be_Greater_Than_BufferHeight_Minus_WindowHeight (Type driverType) { var driver = (FakeDriver)Activator.CreateInstance (driverType); Application.Init (driver); - Application.HeightAsBuffer = true; - Assert.True (Application.HeightAsBuffer); + Application.EnableConsoleScrolling = true; + Assert.True (Application.EnableConsoleScrolling); driver.SetWindowPosition (80, 26); Assert.Equal (0, Console.WindowLeft); diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index ae3766244..bd8677ca0 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -21,8 +21,8 @@ TRACE;DEBUG_IDISPOSABLE - - + + From 5bb350b7f1eb27bacc43d0c99f9ed7bea3d403eb Mon Sep 17 00:00:00 2001 From: Tigger Kindel Date: Sat, 25 Feb 2023 17:22:45 -0700 Subject: [PATCH 03/88] re-merged changes lost from #2345 --- Terminal.Gui/Core/View.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index fa446f720..e303bb343 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1521,14 +1521,12 @@ namespace Terminal.Gui { Driver.SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ()); } - var boundsAdjustedForBorder = Bounds; if (!IgnoreBorderPropertyOnRedraw && Border != null) { Border.DrawContent (this); - boundsAdjustedForBorder = Bounds;// new Rect (bounds.X + 1, bounds.Y + 1, Math.Max (bounds.Width, bounds.Width - 2), Math.Max (bounds.Height, bounds.Height - 2)); } else if (ustring.IsNullOrEmpty (TextFormatter.Text) && (GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") && (!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) { - + Clear (); SetChildNeedsDisplay (); } @@ -1541,8 +1539,8 @@ namespace Terminal.Gui { if (TextFormatter != null) { TextFormatter.NeedsFormat = true; } - TextFormatter?.Draw (ViewToScreen (boundsAdjustedForBorder), HasFocus ? ColorScheme.Focus : GetNormalColor (), - HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled, + TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (), + HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (), containerBounds); } @@ -1552,7 +1550,7 @@ namespace Terminal.Gui { if (subviews != null) { foreach (var view in subviews) { if (!view.NeedDisplay.IsEmpty || view.ChildNeedsDisplay || view.LayoutNeeded) { - if (view.Frame.IntersectsWith (clipRect) && (view.Frame.IntersectsWith (boundsAdjustedForBorder) || boundsAdjustedForBorder.X < 0 || bounds.Y < 0)) { + if (view.Frame.IntersectsWith (clipRect) && (view.Frame.IntersectsWith (bounds) || bounds.X < 0 || bounds.Y < 0)) { if (view.LayoutNeeded) { view.LayoutSubviews (); } @@ -2268,12 +2266,12 @@ namespace Terminal.Gui { } newDimension = AutoSize && autosize > newDimension ? autosize : newDimension; break; - + case Dim.DimFactor factor when !factor.IsFromRemaining (): newDimension = d.Anchor (dimension); newDimension = AutoSize && autosize > newDimension ? autosize : newDimension; break; - + case Dim.DimFill: default: newDimension = Math.Max (d.Anchor (dimension - location), 0); @@ -2448,8 +2446,8 @@ namespace Terminal.Gui { // 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. From 0e8cd6332aecaf47a9769001b3068a352aa7f890 Mon Sep 17 00:00:00 2001 From: Tigger Kindel Date: Sat, 25 Feb 2023 17:32:38 -0700 Subject: [PATCH 04/88] Fixed Border Comparsion Pos.Center bugs --- UICatalog/Scenarios/BordersComparisons.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UICatalog/Scenarios/BordersComparisons.cs b/UICatalog/Scenarios/BordersComparisons.cs index 46c363c12..dd17e2261 100644 --- a/UICatalog/Scenarios/BordersComparisons.cs +++ b/UICatalog/Scenarios/BordersComparisons.cs @@ -38,7 +38,7 @@ namespace UICatalog.Scenarios { button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Window?", "Yes", "No"); var label = new Label ("I'm a Window") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button) - 1 }; var tv = new TextView () { Y = Pos.AnchorEnd (2), @@ -77,7 +77,7 @@ namespace UICatalog.Scenarios { button2.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Toplevel?", "Yes", "No"); var label2 = new Label ("I'm a Toplevel") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button2) - 1 }; var tv2 = new TextView () { Y = Pos.AnchorEnd (2), @@ -113,7 +113,7 @@ namespace UICatalog.Scenarios { button3.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a FrameView?", "Yes", "No"); var label3 = new Label ("I'm a FrameView") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button3) - 1 }; var tv3 = new TextView () { Y = Pos.AnchorEnd (2), From a9cd9ba2e735a4a852ad610aaf5711705398bf37 Mon Sep 17 00:00:00 2001 From: Tigger Kindel Date: Sat, 25 Feb 2023 17:37:57 -0700 Subject: [PATCH 05/88] Fixed Borders on XXX Pos.Center bugs --- UICatalog/Scenarios/BordersOnFrameView.cs | 2 +- UICatalog/Scenarios/BordersOnToplevel.cs | 2 +- UICatalog/Scenarios/BordersOnWindow.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/UICatalog/Scenarios/BordersOnFrameView.cs b/UICatalog/Scenarios/BordersOnFrameView.cs index 3412179ba..5b0740e50 100644 --- a/UICatalog/Scenarios/BordersOnFrameView.cs +++ b/UICatalog/Scenarios/BordersOnFrameView.cs @@ -45,7 +45,7 @@ namespace UICatalog.Scenarios { button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a FrameView?", "Yes", "No"); var label = new Label ("I'm a FrameView") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button) - 1, }; var tf2 = new TextField ("1234567890") { X = Pos.AnchorEnd (10), diff --git a/UICatalog/Scenarios/BordersOnToplevel.cs b/UICatalog/Scenarios/BordersOnToplevel.cs index 9b6f2c72b..7ef109b19 100644 --- a/UICatalog/Scenarios/BordersOnToplevel.cs +++ b/UICatalog/Scenarios/BordersOnToplevel.cs @@ -45,7 +45,7 @@ namespace UICatalog.Scenarios { button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Toplevel?", "Yes", "No"); var label = new Label ("I'm a Toplevel") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button) - 1, }; var tf2 = new TextField ("1234567890") { X = Pos.AnchorEnd (10), diff --git a/UICatalog/Scenarios/BordersOnWindow.cs b/UICatalog/Scenarios/BordersOnWindow.cs index 7075af63b..d0c171b46 100644 --- a/UICatalog/Scenarios/BordersOnWindow.cs +++ b/UICatalog/Scenarios/BordersOnWindow.cs @@ -44,7 +44,7 @@ namespace UICatalog.Scenarios { button.Clicked += () => MessageBox.Query (20, 7, "Hi", "I'm a Window?", "Yes", "No"); var label = new Label ("I'm a Window") { X = Pos.Center (), - Y = Pos.Center () - 3, + Y = Pos.Top (button) - 1, }; var tf2 = new TextField ("1234567890") { X = Pos.AnchorEnd (10), From 28d7be721cbf2a48aa72f23c736d1e9649b60951 Mon Sep 17 00:00:00 2001 From: Tig Kindel Date: Tue, 21 Feb 2023 11:53:10 +1300 Subject: [PATCH 06/88] Revert "Illustrates #2331 (Scrollview not respecting clip) does not reproduce (#2332)" This reverts commit c85ff954aa8cebf0e0eb934d9d283551a6f63db8. --- Terminal.Gui/Core/View.cs | 25 +- UICatalog/Scenarios/ASCIICustomButton.cs | 313 ----------------------- UnitTests/Core/BorderTests.cs | 80 +----- UnitTests/Views/ScrollViewTests.cs | 228 +---------------- 4 files changed, 29 insertions(+), 617 deletions(-) delete mode 100644 UICatalog/Scenarios/ASCIICustomButton.cs diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 018cf1384..19f086715 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1109,8 +1109,15 @@ namespace Terminal.Gui { /// public void Clear () { - var h = Frame.Height; - var w = Frame.Width; + Rect containerBounds = GetContainerBounds (); + Rect viewBounds = Bounds; + if (!containerBounds.IsEmpty) { + viewBounds.Width = Math.Min (viewBounds.Width, containerBounds.Width); + viewBounds.Height = Math.Min (viewBounds.Height, containerBounds.Height); + } + + var h = viewBounds.Height; + var w = viewBounds.Width; for (var line = 0; line < h; line++) { Move (0, line); for (var col = 0; col < w; col++) @@ -1524,8 +1531,7 @@ namespace Terminal.Gui { } if (!ustring.IsNullOrEmpty (TextFormatter.Text)) { - Rect containerBounds = GetContainerBounds (); - Clear (ViewToScreen (GetNeedDisplay (containerBounds))); + Clear (); SetChildNeedsDisplay (); // Draw any Text if (TextFormatter != null) { @@ -1568,17 +1574,6 @@ namespace Terminal.Gui { ClearNeedsDisplay (); } - Rect GetNeedDisplay (Rect containerBounds) - { - Rect rect = NeedDisplay; - if (!containerBounds.IsEmpty) { - rect.Width = Math.Min (NeedDisplay.Width, containerBounds.Width); - rect.Height = Math.Min (NeedDisplay.Height, containerBounds.Height); - } - - return rect; - } - Rect GetContainerBounds () { var containerBounds = SuperView == null ? default : SuperView.ViewToScreen (SuperView.Bounds); diff --git a/UICatalog/Scenarios/ASCIICustomButton.cs b/UICatalog/Scenarios/ASCIICustomButton.cs deleted file mode 100644 index 77cacf8b9..000000000 --- a/UICatalog/Scenarios/ASCIICustomButton.cs +++ /dev/null @@ -1,313 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Terminal.Gui; - -namespace UICatalog.Scenarios { - [ScenarioMetadata (Name: "ASCIICustomButtonTest", Description: "ASCIICustomButton sample")] - [ScenarioCategory ("Controls")] - public class ASCIICustomButtonTest : Scenario { - private static bool smallerWindow; - private ScrollViewTestWindow scrollViewTestWindow; - private MenuItem miSmallerWindow; - - public override void Init (ColorScheme colorScheme) - { - Application.Init (); - scrollViewTestWindow = new ScrollViewTestWindow (); - var menu = new MenuBar (new MenuBarItem [] { - new MenuBarItem("Window Size", new MenuItem [] { - miSmallerWindow = new MenuItem ("Smaller Window", "", ChangeWindowSize) { - CheckType = MenuItemCheckStyle.Checked - }, - null, - new MenuItem("Quit", "",() => Application.RequestStop(),null,null, Key.Q | Key.CtrlMask) - }) - }); - Application.Top.Add (menu, scrollViewTestWindow); - Application.Run (); - } - - private void ChangeWindowSize () - { - smallerWindow = miSmallerWindow.Checked = !miSmallerWindow.Checked; - scrollViewTestWindow.Dispose (); - Application.Top.Remove (scrollViewTestWindow); - scrollViewTestWindow = new ScrollViewTestWindow (); - Application.Top.Add (scrollViewTestWindow); - } - - public override void Run () - { - } - - public class ASCIICustomButton : Button { - public string Description => $"Description of: {id}"; - - public event Action PointerEnter; - - private Label fill; - private FrameView border; - private string id; - - public ASCIICustomButton (string text, Pos x, Pos y, int width, int height) : base (text) - { - CustomInitialize ("", text, x, y, width, height); - } - - public ASCIICustomButton (string id, string text, Pos x, Pos y, int width, int height) : base (text) - { - CustomInitialize (id, text, x, y, width, height); - } - - private void CustomInitialize (string id, string text, Pos x, Pos y, int width, int height) - { - this.id = id; - X = x; - Y = y; - - Frame = new Rect { - Width = width, - Height = height - }; - - border = new FrameView () { - Width = width, - Height = height - }; - - AutoSize = false; - - var fillText = new System.Text.StringBuilder (); - for (int i = 0; i < Bounds.Height; i++) { - if (i > 0) { - fillText.AppendLine (""); - } - for (int j = 0; j < Bounds.Width; j++) { - fillText.Append ("█"); - } - } - - fill = new Label (fillText.ToString ()) { - Visible = false, - CanFocus = false - }; - - var title = new Label (text) { - X = Pos.Center (), - Y = Pos.Center (), - }; - - border.MouseClick += This_MouseClick; - border.Subviews [0].MouseClick += This_MouseClick; - fill.MouseClick += This_MouseClick; - title.MouseClick += This_MouseClick; - - Add (border, fill, title); - } - - private void This_MouseClick (MouseEventArgs obj) - { - OnMouseEvent (obj.MouseEvent); - } - - public override bool OnMouseEvent (MouseEvent mouseEvent) - { - Debug.WriteLine ($"{mouseEvent.Flags}"); - if (mouseEvent.Flags == MouseFlags.Button1Clicked) { - if (!HasFocus && SuperView != null) { - if (!SuperView.HasFocus) { - SuperView.SetFocus (); - } - SetFocus (); - SetNeedsDisplay (); - } - - OnClicked (); - return true; - } - return base.OnMouseEvent (mouseEvent); - } - - public override bool OnEnter (View view) - { - border.Visible = false; - fill.Visible = true; - PointerEnter.Invoke (this); - view = this; - return base.OnEnter (view); - } - - public override bool OnLeave (View view) - { - border.Visible = true; - fill.Visible = false; - if (view == null) - view = this; - return base.OnLeave (view); - } - } - - public class ScrollViewTestWindow : Window { - private List public static ThemeManager Instance { get { return _instance; } } - private static string theme = string.Empty; + private static string _theme = string.Empty; /// /// The currently selected theme. This is the internal version; see . /// [JsonInclude, SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true), JsonPropertyName ("Theme")] internal static string SelectedTheme { - get => theme; + get => _theme; set { - var oldTheme = theme; - theme = value; - if (oldTheme != theme && + var oldTheme = _theme; + _theme = value; + if (oldTheme != _theme && ConfigurationManager.Settings! ["Themes"]?.PropertyValue is Dictionary themes && - themes.ContainsKey (theme)) { - ConfigurationManager.Settings! ["Theme"].PropertyValue = theme; + themes.ContainsKey (_theme)) { + ConfigurationManager.Settings! ["Theme"].PropertyValue = _theme; Instance.OnThemeChanged (oldTheme); } } diff --git a/UnitTests/Configuration/ConfigurationMangerTests.cs b/UnitTests/Configuration/ConfigurationMangerTests.cs index 7c050ef7f..5e5c34b3d 100644 --- a/UnitTests/Configuration/ConfigurationMangerTests.cs +++ b/UnitTests/Configuration/ConfigurationMangerTests.cs @@ -182,12 +182,13 @@ namespace Terminal.Gui.ConfigurationTests { /// Save the `config.json` file; this can be used to update the file in `Terminal.Gui.Resources.config.json'. /// /// - /// IMPORTANT: For the file generated to be valid, this must be the ONLY test run. Conifg Properties - /// are all satic and thus can be overwritten by other tests. + /// IMPORTANT: For the file generated to be valid, this must be the ONLY test run. Config Properties + /// are all static and thus can be overwritten by other tests. [Fact] public void SaveDefaults () { ConfigurationManager.Initialize (); + ConfigurationManager.Reset (); // Get the hard coded settings ConfigurationManager.GetHardCodedDefaults (); @@ -316,12 +317,11 @@ namespace Terminal.Gui.ConfigurationTests { [Fact, AutoInitShutdown] public void TestConfigurationManagerToJson () { + ConfigurationManager.Reset (); ConfigurationManager.GetHardCodedDefaults (); var stream = ConfigurationManager.ToStream (); - ConfigurationManager.Settings.Update (stream, "TestConfigurationManagerToJson"); - } [Fact, AutoInitShutdown (configLocation: ConfigLocations.None)] From 29af067e01082d7e55c3fc7d398ca523f0740df8 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 18:28:38 +0000 Subject: [PATCH 70/88] Fixes merge errors. --- Terminal.Gui/Core/Border.cs | 14 ++++++++------ Terminal.Gui/Views/FrameView.cs | 5 +---- UICatalog/UICatalog.cs | 6 +++--- UnitTests/Core/BorderTests.cs | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index fee09be37..3dff2ce7d 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -331,6 +331,7 @@ 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. @@ -650,7 +651,7 @@ namespace Terminal.Gui { Child.Clear (borderRect); } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw margin frame if (DrawMarginFrame) { @@ -674,6 +675,7 @@ 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) @@ -786,7 +788,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw the MarginFrame if (DrawMarginFrame) { @@ -983,7 +985,7 @@ namespace Terminal.Gui { } } - driver.SetAttribute (savedAttribute); + driver.SetAttribute (new Attribute (BorderBrush, Background)); // Draw the MarginFrame if (DrawMarginFrame) { @@ -1077,7 +1079,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, Title, + driver.DrawWindowTitle (scrRect, Parent.Border.Title, padding.Left, padding.Top, padding.Right, padding.Bottom); } } @@ -1093,9 +1095,9 @@ namespace Terminal.Gui { { var driver = Application.Driver; if (DrawMarginFrame) { - driver.SetAttribute (view.GetNormalColor ()); + driver.SetAttribute (new Attribute (BorderBrush, Background)); if (view.HasFocus) { - driver.SetAttribute (view.ColorScheme.HotNormal); + driver.SetAttribute (new Attribute (view.ColorScheme.HotNormal.Foreground, Background)); } var padding = Parent.Border.GetSumThickness (); var scrRect = Parent.ViewToScreen (new Rect (0, 0, rect.Width, rect.Height)); diff --git a/Terminal.Gui/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs index 1264d4159..8b1865108 100644 --- a/Terminal.Gui/Views/FrameView.cs +++ b/Terminal.Gui/Views/FrameView.cs @@ -268,12 +268,8 @@ 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 (); } @@ -281,6 +277,7 @@ namespace Terminal.Gui { contentView.Redraw (!NeedDisplay.IsEmpty ? contentView.Bounds : bounds); Driver.Clip = savedClip; + ClearLayoutNeeded (); ClearNeedsDisplay (); if (!IgnoreBorderPropertyOnRedraw) { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index e7f577eee..49faf0ddd 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -195,9 +195,9 @@ 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.EnableConsoleScrolling = _enableConsoleScrolling; + Application.Run (); Application.Shutdown (); diff --git a/UnitTests/Core/BorderTests.cs b/UnitTests/Core/BorderTests.cs index a23c9a1b6..c59b085ce 100644 --- a/UnitTests/Core/BorderTests.cs +++ b/UnitTests/Core/BorderTests.cs @@ -230,7 +230,7 @@ namespace Terminal.Gui.CoreTests { 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.Black, color.Background); // because of #2345 - Border: can't change border color in window by Border.BorderBrush. + Assert.Equal (Color.BrightGreen, color.Background); } else { Assert.Equal (Color.Black, color.Background); } @@ -464,7 +464,7 @@ namespace Terminal.Gui.CoreTests { 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.Black, color.Background); // because of #2345 - Border: can't change border color in window by Border.BorderBrush. + Assert.Equal (Color.BrightGreen, color.Background); } else { Assert.Equal (Color.Black, color.Background); } From 53e3e703cf0949b09c60e249f369dad8f4894c2b Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 18:32:46 +0000 Subject: [PATCH 71/88] Revert "Removing ToString() because they aren't View class and did a reformat." This reverts commit d15732e9102757a19727aeadea3cb50911444f3a. --- Terminal.Gui/Core/PosDim.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/Core/PosDim.cs index 0c9278359..6334682d6 100644 --- a/Terminal.Gui/Core/PosDim.cs +++ b/Terminal.Gui/Core/PosDim.cs @@ -264,7 +264,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosCombine({left}{(add ? '+' : '-')}{right})"; + return $"PosCombine({left.ToString ()}{(add ? '+' : '-')}{right.ToString ()})"; } } @@ -345,7 +345,7 @@ namespace Terminal.Gui { case 3: tside = "bottom"; break; default: tside = "unknown"; break; } - return $"PosView({tside},{Target.ToString ()})"; + return $"PosView({tside},{Target.ToString()})"; } public override int GetHashCode () => Target.GetHashCode (); @@ -613,7 +613,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimCombine({left}{(add ? '+' : '-')}{right})"; + return $"DimCombine({left}{(add ? '+' : '-')}{right.ToString ()})"; } } From c99b35578d252bdc1e00c903eed6d2ca93b56a5a Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 18:35:10 +0000 Subject: [PATCH 72/88] Revert "Fixes unit tests to support Pos/Dim changes." This reverts commit ad426ff261782e207f213f1bf427d406b1bd61bd. --- UnitTests/Core/LayoutTests.cs | 240 +++++++++++++------------- UnitTests/TopLevels/ToplevelTests.cs | 4 +- UnitTests/Types/DimTests.cs | 132 +++++++------- UnitTests/Types/PosTests.cs | 94 +++++----- UnitTests/Views/ScrollBarViewTests.cs | 40 ++--- UnitTests/Views/StatusBarTests.cs | 2 +- UnitTests/Views/TextViewTests.cs | 12 +- 7 files changed, 262 insertions(+), 262 deletions(-) diff --git a/UnitTests/Core/LayoutTests.cs b/UnitTests/Core/LayoutTests.cs index df5963dc4..de0c94065 100644 --- a/UnitTests/Core/LayoutTests.cs +++ b/UnitTests/Core/LayoutTests.cs @@ -645,10 +645,10 @@ Y Assert.False (view.AutoSize); Assert.Equal (TextDirection.LeftRight_TopBottom, view.TextDirection); Assert.Equal (Rect.Empty, view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(0)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(0)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(0)", view.Width.ToString ()); + Assert.Equal ("Absolute(0)", view.Height.ToString ()); var expected = @" ┌────────────────────┐ │ │ @@ -682,10 +682,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 11, 1), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(0)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(11)", view.Width.ToString ()); + Assert.Equal ("Absolute(0)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │Hello World │ @@ -719,10 +719,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 12, 1), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(0)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(11)", view.Width.ToString ()); + Assert.Equal ("Absolute(0)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │Hello Worlds │ @@ -755,10 +755,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 11, 12), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(0)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(11)", view.Width.ToString ()); + Assert.Equal ("Absolute(0)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │H │ @@ -792,10 +792,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 11, 1), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(11)", view.Width.ToString ()); + Assert.Equal ("Absolute(1)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │HelloWorlds │ @@ -828,10 +828,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 11, 1), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(11)", view.Width.ToString ()); + Assert.Equal ("Absolute(1)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │Hello World │ @@ -868,10 +868,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 1, 11), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(1)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(1)", view.Width.ToString ()); + Assert.Equal ("Absolute(11)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │H │ @@ -904,10 +904,10 @@ Y Application.Refresh (); Assert.Equal (new Rect (0, 0, 1, 12), view.Frame); - Assert.Equal ("PosAbsolute(0)", view.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view.Y.ToString ()); - Assert.Equal ("DimAbsolute(1)", view.Width.ToString ()); - Assert.Equal ("DimAbsolute(11)", view.Height.ToString ()); + Assert.Equal ("Absolute(0)", view.X.ToString ()); + Assert.Equal ("Absolute(0)", view.Y.ToString ()); + Assert.Equal ("Absolute(1)", view.Width.ToString ()); + Assert.Equal ("Absolute(11)", view.Height.ToString ()); expected = @" ┌────────────────────┐ │H │ @@ -968,15 +968,15 @@ Y Assert.Equal (new Size (10, 1), horizontalView.TextFormatter.Size); Assert.Equal (new Size (2, 9), verticalView.TextFormatter.Size); Assert.Equal (new Rect (0, 0, 9, 1), horizontalView.Frame); - Assert.Equal ("PosAbsolute(0)", horizontalView.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", horizontalView.Y.ToString ()); - Assert.Equal ("DimAbsolute(9)", horizontalView.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", horizontalView.Height.ToString ()); + Assert.Equal ("Absolute(0)", horizontalView.X.ToString ()); + Assert.Equal ("Absolute(0)", horizontalView.Y.ToString ()); + Assert.Equal ("Absolute(9)", horizontalView.Width.ToString ()); + Assert.Equal ("Absolute(1)", horizontalView.Height.ToString ()); Assert.Equal (new Rect (0, 3, 2, 8), verticalView.Frame); - Assert.Equal ("PosAbsolute(0)", verticalView.X.ToString ()); - Assert.Equal ("PosAbsolute(3)", verticalView.Y.ToString ()); - Assert.Equal ("DimAbsolute(2)", verticalView.Width.ToString ()); - Assert.Equal ("DimAbsolute(8)", verticalView.Height.ToString ()); + Assert.Equal ("Absolute(0)", verticalView.X.ToString ()); + Assert.Equal ("Absolute(3)", verticalView.Y.ToString ()); + Assert.Equal ("Absolute(2)", verticalView.Width.ToString ()); + Assert.Equal ("Absolute(8)", verticalView.Height.ToString ()); var expected = @" ┌────────────────────┐ │Finish 終 │ @@ -1011,10 +1011,10 @@ Y Assert.True (verticalView.AutoSize); // height was initialized with 8 and is kept as minimum Assert.Equal (new Rect (0, 3, 2, 8), verticalView.Frame); - Assert.Equal ("PosAbsolute(0)", verticalView.X.ToString ()); - Assert.Equal ("PosAbsolute(3)", verticalView.Y.ToString ()); - Assert.Equal ("DimAbsolute(2)", verticalView.Width.ToString ()); - Assert.Equal ("DimAbsolute(8)", verticalView.Height.ToString ()); + Assert.Equal ("Absolute(0)", verticalView.X.ToString ()); + Assert.Equal ("Absolute(3)", verticalView.Y.ToString ()); + Assert.Equal ("Absolute(2)", verticalView.Width.ToString ()); + Assert.Equal ("Absolute(8)", verticalView.Height.ToString ()); expected = @" ┌────────────────────┐ │Finish 終 │ @@ -1126,28 +1126,28 @@ Y Assert.False (view5.IsInitialized); Assert.False (view1.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame); - Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ()); + Assert.Equal ("Absolute(10)", view1.Width.ToString ()); + Assert.Equal ("Absolute(5)", view1.Height.ToString ()); Assert.False (view2.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame); - Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ()); + Assert.Equal ("Absolute(10)", view2.Width.ToString ()); + Assert.Equal ("Absolute(5)", view2.Height.ToString ()); Assert.False (view3.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame); - Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ()); + Assert.Equal ("Absolute(10)", view3.Width.ToString ()); + Assert.Equal ("Absolute(5)", view3.Height.ToString ()); Assert.False (view4.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame); - Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ()); + Assert.Equal ("Absolute(10)", view4.Width.ToString ()); + Assert.Equal ("Absolute(5)", view4.Height.ToString ()); Assert.False (view5.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame); - Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ()); + Assert.Equal ("Absolute(10)", view5.Width.ToString ()); + Assert.Equal ("Absolute(5)", view5.Height.ToString ()); Assert.False (view6.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame); - Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ()); + Assert.Equal ("Absolute(10)", view6.Width.ToString ()); + Assert.Equal ("Absolute(5)", view6.Height.ToString ()); Application.Begin (Application.Top); @@ -1158,28 +1158,28 @@ Y Assert.True (view5.IsInitialized); Assert.False (view1.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view1.Frame); - Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ()); + Assert.Equal ("Absolute(10)", view1.Width.ToString ()); + Assert.Equal ("Absolute(5)", view1.Height.ToString ()); Assert.False (view2.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view2.Frame); - Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ()); + Assert.Equal ("Absolute(10)", view2.Width.ToString ()); + Assert.Equal ("Absolute(5)", view2.Height.ToString ()); Assert.False (view3.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view3.Frame); - Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ()); + Assert.Equal ("Absolute(10)", view3.Width.ToString ()); + Assert.Equal ("Absolute(5)", view3.Height.ToString ()); Assert.False (view4.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view4.Frame); - Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ()); + Assert.Equal ("Absolute(10)", view4.Width.ToString ()); + Assert.Equal ("Absolute(5)", view4.Height.ToString ()); Assert.False (view5.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view5.Frame); - Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ()); + Assert.Equal ("Absolute(10)", view5.Width.ToString ()); + Assert.Equal ("Absolute(5)", view5.Height.ToString ()); Assert.False (view6.AutoSize); Assert.Equal (new Rect (0, 0, 10, 5), view6.Frame); - Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ()); + Assert.Equal ("Absolute(10)", view6.Width.ToString ()); + Assert.Equal ("Absolute(5)", view6.Height.ToString ()); } [Fact, AutoInitShutdown] @@ -1218,28 +1218,28 @@ Y Assert.False (view5.IsInitialized); Assert.True (view1.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view1.Frame); - Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ()); + Assert.Equal ("Absolute(10)", view1.Width.ToString ()); + Assert.Equal ("Absolute(5)", view1.Height.ToString ()); Assert.True (view2.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view2.Frame); - Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ()); + Assert.Equal ("Absolute(10)", view2.Width.ToString ()); + Assert.Equal ("Absolute(5)", view2.Height.ToString ()); Assert.True (view3.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view3.Frame); - Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ()); + Assert.Equal ("Absolute(10)", view3.Width.ToString ()); + Assert.Equal ("Absolute(5)", view3.Height.ToString ()); Assert.True (view4.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view4.Frame); - Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ()); + Assert.Equal ("Absolute(10)", view4.Width.ToString ()); + Assert.Equal ("Absolute(5)", view4.Height.ToString ()); Assert.True (view5.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view5.Frame); - Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ()); + Assert.Equal ("Absolute(10)", view5.Width.ToString ()); + Assert.Equal ("Absolute(5)", view5.Height.ToString ()); Assert.True (view6.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view6.Frame); - Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ()); + Assert.Equal ("Absolute(10)", view6.Width.ToString ()); + Assert.Equal ("Absolute(5)", view6.Height.ToString ()); Application.Begin (Application.Top); @@ -1250,28 +1250,28 @@ Y Assert.True (view5.IsInitialized); Assert.True (view1.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view1.Frame); - Assert.Equal ("DimAbsolute(10)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view1.Height.ToString ()); + Assert.Equal ("Absolute(10)", view1.Width.ToString ()); + Assert.Equal ("Absolute(5)", view1.Height.ToString ()); Assert.True (view2.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view2.Frame); - Assert.Equal ("DimAbsolute(10)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view2.Height.ToString ()); + Assert.Equal ("Absolute(10)", view2.Width.ToString ()); + Assert.Equal ("Absolute(5)", view2.Height.ToString ()); Assert.True (view3.AutoSize); Assert.Equal (new Rect (0, 0, 18, 5), view3.Frame); - Assert.Equal ("DimAbsolute(10)", view3.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view3.Height.ToString ()); + Assert.Equal ("Absolute(10)", view3.Width.ToString ()); + Assert.Equal ("Absolute(5)", view3.Height.ToString ()); Assert.True (view4.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view4.Frame); - Assert.Equal ("DimAbsolute(10)", view4.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view4.Height.ToString ()); + Assert.Equal ("Absolute(10)", view4.Width.ToString ()); + Assert.Equal ("Absolute(5)", view4.Height.ToString ()); Assert.True (view5.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view5.Frame); - Assert.Equal ("DimAbsolute(10)", view5.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view5.Height.ToString ()); + Assert.Equal ("Absolute(10)", view5.Width.ToString ()); + Assert.Equal ("Absolute(5)", view5.Height.ToString ()); Assert.True (view6.AutoSize); Assert.Equal (new Rect (0, 0, 10, 17), view6.Frame); - Assert.Equal ("DimAbsolute(10)", view6.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", view6.Height.ToString ()); + Assert.Equal ("Absolute(10)", view6.Width.ToString ()); + Assert.Equal ("Absolute(5)", view6.Height.ToString ()); } [Fact, AutoInitShutdown] @@ -1290,17 +1290,17 @@ Y Assert.True (view1.AutoSize); Assert.Equal (LayoutStyle.Absolute, view1.LayoutStyle); Assert.Equal (new Rect (0, 0, 18, 1), view1.Frame); - Assert.Equal ("PosAbsolute(0)", view1.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ()); - Assert.Equal ("DimAbsolute(18)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", view1.Height.ToString ()); + Assert.Equal ("Absolute(0)", view1.X.ToString ()); + Assert.Equal ("Absolute(0)", view1.Y.ToString ()); + Assert.Equal ("Absolute(18)", view1.Width.ToString ()); + Assert.Equal ("Absolute(1)", view1.Height.ToString ()); Assert.True (view2.AutoSize); Assert.Equal (LayoutStyle.Absolute, view2.LayoutStyle); Assert.Equal (new Rect (0, 0, 2, 17), view2.Frame); - Assert.Equal ("PosAbsolute(0)", view2.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view2.Y.ToString ()); - Assert.Equal ("DimAbsolute(2)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(17)", view2.Height.ToString ()); + Assert.Equal ("Absolute(0)", view2.X.ToString ()); + Assert.Equal ("Absolute(0)", view2.Y.ToString ()); + Assert.Equal ("Absolute(2)", view2.Width.ToString ()); + Assert.Equal ("Absolute(17)", view2.Height.ToString ()); view1.Frame = new Rect (0, 0, 25, 4); bool firstIteration = false; @@ -1309,10 +1309,10 @@ Y Assert.True (view1.AutoSize); Assert.Equal (LayoutStyle.Absolute, view1.LayoutStyle); Assert.Equal (new Rect (0, 0, 25, 4), view1.Frame); - Assert.Equal ("PosAbsolute(0)", view1.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ()); - Assert.Equal ("DimAbsolute(18)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", view1.Height.ToString ()); + Assert.Equal ("Absolute(0)", view1.X.ToString ()); + Assert.Equal ("Absolute(0)", view1.Y.ToString ()); + Assert.Equal ("Absolute(18)", view1.Width.ToString ()); + Assert.Equal ("Absolute(1)", view1.Height.ToString ()); view2.Frame = new Rect (0, 0, 1, 25); Application.RunMainLoopIteration (ref rs, true, ref firstIteration); @@ -1320,10 +1320,10 @@ Y Assert.True (view2.AutoSize); Assert.Equal (LayoutStyle.Absolute, view2.LayoutStyle); Assert.Equal (new Rect (0, 0, 1, 25), view2.Frame); - Assert.Equal ("PosAbsolute(0)", view2.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view2.Y.ToString ()); - Assert.Equal ("DimAbsolute(2)", view2.Width.ToString ()); - Assert.Equal ("DimAbsolute(17)", view2.Height.ToString ()); + Assert.Equal ("Absolute(0)", view2.X.ToString ()); + Assert.Equal ("Absolute(0)", view2.Y.ToString ()); + Assert.Equal ("Absolute(2)", view2.Width.ToString ()); + Assert.Equal ("Absolute(17)", view2.Height.ToString ()); } [Fact, AutoInitShutdown] @@ -1338,10 +1338,10 @@ Y Assert.Null (view1.Height); top.Add (view1); Assert.True (view1.IsAdded); - Assert.Equal ("PosAbsolute(0)", view1.X.ToString ()); - Assert.Equal ("PosAbsolute(0)", view1.Y.ToString ()); - Assert.Equal ("DimAbsolute(0)", view1.Width.ToString ()); - Assert.Equal ("DimAbsolute(0)", view1.Height.ToString ()); + Assert.Equal ("Absolute(0)", view1.X.ToString ()); + Assert.Equal ("Absolute(0)", view1.Y.ToString ()); + Assert.Equal ("Absolute(0)", view1.Width.ToString ()); + Assert.Equal ("Absolute(0)", view1.Height.ToString ()); var view2 = new View () { X = Pos.Center (), @@ -1350,16 +1350,16 @@ Y Height = Dim.Fill () }; Assert.False (view2.IsAdded); - Assert.Equal ("PosCenter", view2.X.ToString ()); - Assert.Equal ("PosCenter", view2.Y.ToString ()); - Assert.Equal ("DimFill(0)", view2.Width.ToString ()); - Assert.Equal ("DimFill(0)", view2.Height.ToString ()); + Assert.Equal ("Center", view2.X.ToString ()); + Assert.Equal ("Center", view2.Y.ToString ()); + Assert.Equal ("Fill(0)", view2.Width.ToString ()); + Assert.Equal ("Fill(0)", view2.Height.ToString ()); top.Add (view2); Assert.True (view2.IsAdded); - Assert.Equal ("PosCenter", view2.X.ToString ()); - Assert.Equal ("PosCenter", view2.Y.ToString ()); - Assert.Equal ("DimFill(0)", view2.Width.ToString ()); - Assert.Equal ("DimFill(0)", view2.Height.ToString ()); + Assert.Equal ("Center", view2.X.ToString ()); + Assert.Equal ("Center", view2.Y.ToString ()); + Assert.Equal ("Fill(0)", view2.Width.ToString ()); + Assert.Equal ("Fill(0)", view2.Height.ToString ()); } [Fact] diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs index 3686ee71c..1f4382813 100644 --- a/UnitTests/TopLevels/ToplevelTests.cs +++ b/UnitTests/TopLevels/ToplevelTests.cs @@ -19,8 +19,8 @@ namespace Terminal.Gui.TopLevelTests { var top = new Toplevel (); Assert.Equal (Colors.TopLevel, top.ColorScheme); - Assert.Equal ("DimFill(0)", top.Width.ToString ()); - Assert.Equal ("DimFill(0)", top.Height.ToString ()); + Assert.Equal ("Fill(0)", top.Width.ToString ()); + Assert.Equal ("Fill(0)", top.Height.ToString ()); Assert.False (top.Running); Assert.False (top.Modal); Assert.Null (top.MenuBar); diff --git a/UnitTests/Types/DimTests.cs b/UnitTests/Types/DimTests.cs index 5062fe83c..5a98d5db9 100644 --- a/UnitTests/Types/DimTests.cs +++ b/UnitTests/Types/DimTests.cs @@ -37,15 +37,15 @@ namespace Terminal.Gui.TypeTests { public void Sized_SetsValue () { var dim = Dim.Sized (0); - Assert.Equal ("DimAbsolute(0)", dim.ToString ()); + Assert.Equal ("Absolute(0)", dim.ToString ()); int testVal = 5; dim = Dim.Sized (testVal); - Assert.Equal ($"DimAbsolute({testVal})", dim.ToString ()); + Assert.Equal ($"Absolute({testVal})", dim.ToString ()); testVal = -1; dim = Dim.Sized (testVal); - Assert.Equal ($"DimAbsolute({testVal})", dim.ToString ()); + Assert.Equal ($"Absolute({testVal})", dim.ToString ()); } [Fact] @@ -155,15 +155,15 @@ namespace Terminal.Gui.TypeTests { { var testMargin = 0; var dim = Dim.Fill (); - Assert.Equal ($"DimFill({testMargin})", dim.ToString ()); + Assert.Equal ($"Fill({testMargin})", dim.ToString ()); testMargin = 0; dim = Dim.Fill (testMargin); - Assert.Equal ($"DimFill({testMargin})", dim.ToString ()); + Assert.Equal ($"Fill({testMargin})", dim.ToString ()); testMargin = 5; dim = Dim.Fill (testMargin); - Assert.Equal ($"DimFill({testMargin})", dim.ToString ()); + Assert.Equal ($"Fill({testMargin})", dim.ToString ()); } @@ -182,13 +182,13 @@ namespace Terminal.Gui.TypeTests { { float f = 0; var dim = Dim.Percent (f); - Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ()); f = 0.5F; dim = Dim.Percent (f); - Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ()); f = 100; dim = Dim.Percent (f); - Assert.Equal ($"DimFactor({f / 100:0.###},{false})", dim.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###},{false})", dim.ToString ()); } [Fact] @@ -420,48 +420,48 @@ namespace Terminal.Gui.TypeTests { t.Add (w); t.Ready += () => { - Assert.Equal ("DimAbsolute(100)", w.Width.ToString ()); - Assert.Equal ("DimAbsolute(100)", w.Height.ToString ()); + Assert.Equal ("Absolute(100)", w.Width.ToString ()); + Assert.Equal ("Absolute(100)", w.Height.ToString ()); Assert.Equal (100, w.Frame.Width); Assert.Equal (100, w.Frame.Height); - Assert.Equal ("DimFactor(0.5,False)", f1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", f1.Height.ToString ()); + Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ()); + Assert.Equal ("Absolute(5)", f1.Height.ToString ()); Assert.Equal (49, f1.Frame.Width); // 50-1=49 Assert.Equal (5, f1.Frame.Height); - Assert.Equal ("DimFill(0)", f2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", f2.Height.ToString ()); + Assert.Equal ("Fill(0)", f2.Width.ToString ()); + Assert.Equal ("Absolute(5)", f2.Height.ToString ()); Assert.Equal (49, f2.Frame.Width); // 50-1=49 Assert.Equal (5, f2.Frame.Height); - Assert.Equal ("DimCombine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-DimAbsolute(2))", v1.Width.ToString ()); - Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(2))", v1.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.ToString ()); + Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ()); Assert.Equal (47, v1.Frame.Width); // 49-2=47 Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89 - Assert.Equal ("DimCombine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-DimAbsolute(2))", v2.Width.ToString ()); - Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(2))", v2.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.ToString ()); + Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ()); Assert.Equal (47, v2.Frame.Width); // 49-2=47 Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89 - Assert.Equal ("DimFactor(0.1,False)", v3.Width.ToString ()); - Assert.Equal ("DimFactor(0.1,False)", v3.Height.ToString ()); + Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ()); + Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ()); Assert.Equal (9, v3.Frame.Width); // 98*10%=9 Assert.Equal (9, v3.Frame.Height); // 98*10%=9 - Assert.Equal ("DimAbsolute(50)", v4.Width.ToString ()); - Assert.Equal ("DimAbsolute(50)", v4.Height.ToString ()); + Assert.Equal ("Absolute(50)", v4.Width.ToString ()); + Assert.Equal ("Absolute(50)", v4.Height.ToString ()); Assert.Equal (50, v4.Frame.Width); Assert.Equal (50, v4.Frame.Height); - Assert.Equal ("DimCombine(DimView(Width,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ()); - Assert.Equal ("DimCombine(DimView(Height,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ()); + Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ()); Assert.Equal (38, v5.Frame.Width); // 47-9=38 Assert.Equal (80, v5.Frame.Height); // 89-9=80 - Assert.Equal ("DimFactor(0.2,True)", v6.Width.ToString ()); - Assert.Equal ("DimFactor(0.2,True)", v6.Height.ToString ()); + Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ()); + Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ()); Assert.Equal (9, v6.Frame.Width); // 47*20%=9 Assert.Equal (18, v6.Frame.Height); // 89*20%=18 @@ -469,62 +469,62 @@ namespace Terminal.Gui.TypeTests { w.Height = 200; t.LayoutSubviews (); - Assert.Equal ("DimAbsolute(200)", w.Width.ToString ()); - Assert.Equal ("DimAbsolute(200)", w.Height.ToString ()); + Assert.Equal ("Absolute(200)", w.Width.ToString ()); + Assert.Equal ("Absolute(200)", w.Height.ToString ()); Assert.Equal (200, w.Frame.Width); Assert.Equal (200, w.Frame.Height); f1.Text = "Frame1"; - Assert.Equal ("DimFactor(0.5,False)", f1.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", f1.Height.ToString ()); + Assert.Equal ("Factor(0.5,False)", f1.Width.ToString ()); + Assert.Equal ("Absolute(5)", f1.Height.ToString ()); Assert.Equal (99, f1.Frame.Width); // 100-1=99 Assert.Equal (5, f1.Frame.Height); f2.Text = "Frame2"; - Assert.Equal ("DimFill(0)", f2.Width.ToString ()); - Assert.Equal ("DimAbsolute(5)", f2.Height.ToString ()); + Assert.Equal ("Fill(0)", f2.Width.ToString ()); + Assert.Equal ("Absolute(5)", f2.Height.ToString ()); Assert.Equal (99, f2.Frame.Width); // 100-1=99 Assert.Equal (5, f2.Frame.Height); v1.Text = "Button1"; - Assert.Equal ("DimCombine(DimView(Width,FrameView()({X=0,Y=0,Width=99,Height=5}))-DimAbsolute(2))", v1.Width.ToString ()); - Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(2))", v1.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=99,Height=5}))-Absolute(2))", v1.Width.ToString ()); + Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ()); Assert.Equal (97, v1.Frame.Width); // 99-2=97 Assert.Equal (189, v1.Frame.Height); // 198-2-7=189 v2.Text = "Button2"; - Assert.Equal ("DimCombine(DimView(Width,FrameView()({X=99,Y=0,Width=99,Height=5}))-DimAbsolute(2))", v2.Width.ToString ()); - Assert.Equal ("DimCombine(DimFill(0)-DimAbsolute(2))", v2.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,FrameView()({X=99,Y=0,Width=99,Height=5}))-Absolute(2))", v2.Width.ToString ()); + Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ()); Assert.Equal (97, v2.Frame.Width); // 99-2=97 Assert.Equal (189, v2.Frame.Height); // 198-2-7=189 v3.Text = "Button3"; - Assert.Equal ("DimFactor(0.1,False)", v3.Width.ToString ()); - Assert.Equal ("DimFactor(0.1,False)", v3.Height.ToString ()); + Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ()); + Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ()); Assert.Equal (19, v3.Frame.Width); // 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width Assert.Equal (19, v3.Frame.Height); // 199*10%=19 v4.Text = "Button4"; v4.AutoSize = false; - Assert.Equal ("DimAbsolute(50)", v4.Width.ToString ()); - Assert.Equal ("DimAbsolute(50)", v4.Height.ToString ()); + Assert.Equal ("Absolute(50)", v4.Width.ToString ()); + Assert.Equal ("Absolute(50)", v4.Height.ToString ()); Assert.Equal (50, v4.Frame.Width); Assert.Equal (50, v4.Frame.Height); v4.AutoSize = true; - Assert.Equal ("DimAbsolute(11)", v4.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", v4.Height.ToString ()); + Assert.Equal ("Absolute(11)", v4.Width.ToString ()); + Assert.Equal ("Absolute(1)", v4.Height.ToString ()); Assert.Equal (11, v4.Frame.Width); // 11 is the text length and because is Dim.DimAbsolute Assert.Equal (1, v4.Frame.Height); // 1 because is Dim.DimAbsolute v5.Text = "Button5"; - Assert.Equal ("DimCombine(DimView(Width,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ()); - Assert.Equal ("DimCombine(DimView(Height,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ()); + Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ()); + Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ()); Assert.Equal (78, v5.Frame.Width); // 97-19=78 Assert.Equal (170, v5.Frame.Height); // 189-19=170 v6.Text = "Button6"; - Assert.Equal ("DimFactor(0.2,True)", v6.Width.ToString ()); - Assert.Equal ("DimFactor(0.2,True)", v6.Height.ToString ()); + Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ()); + Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ()); Assert.Equal (19, v6.Frame.Width); // 99*20%=19 Assert.Equal (38, v6.Frame.Height); // 198-7*20=38 }; @@ -634,12 +634,12 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 }; view.Add (label); Assert.Equal ($"Label {count}", label.Text); - Assert.Equal ($"PosAbsolute({count})", label.Y.ToString ()); + Assert.Equal ($"Absolute({count})", label.Y.ToString ()); - Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count})", view.Height.ToString ()); view.Height += 1; count++; - Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count})", view.Height.ToString ()); } }; @@ -1006,18 +1006,18 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 10 }; view.Add (label); Assert.Equal ($"Label {count}", label.Text); - Assert.Equal ($"PosAbsolute({count + 1})", label.Y.ToString ()); + Assert.Equal ($"Absolute({count + 1})", label.Y.ToString ()); listLabels.Add (label); if (count == 0) { - Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count})", view.Height.ToString ()); view.Height += 2; } else { - Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ()); view.Height += 1; } count++; } - Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ()); } }; @@ -1066,12 +1066,12 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 20 }; view.Add (label); Assert.Equal ($"Label {i}", label.Text); - Assert.Equal ($"PosAbsolute({i})", label.Y.ToString ()); + Assert.Equal ($"Absolute({i})", label.Y.ToString ()); listLabels.Add (label); - Assert.Equal ($"DimAbsolute({i})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i})", view.Height.ToString ()); view.Height += 1; - Assert.Equal ($"DimAbsolute({i + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ()); } field.KeyDown += (k) => { @@ -1079,10 +1079,10 @@ namespace Terminal.Gui.TypeTests { Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text); view.Remove (listLabels [count - 1]); - Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count})", view.Height.ToString ()); view.Height -= 1; count--; - Assert.Equal ($"DimAbsolute({count})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count})", view.Height.ToString ()); } }; @@ -1125,17 +1125,17 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = view.Bounds.Height, Width = 10 }; view.Add (label); Assert.Equal ($"Label {i}", label.Text); - Assert.Equal ($"PosAbsolute({i + 1})", label.Y.ToString ()); + Assert.Equal ($"Absolute({i + 1})", label.Y.ToString ()); listLabels.Add (label); if (i == 0) { - Assert.Equal ($"DimAbsolute({i})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i})", view.Height.ToString ()); view.Height += 2; - Assert.Equal ($"DimAbsolute({i + 2})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ()); } else { - Assert.Equal ($"DimAbsolute({i + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i + 1})", view.Height.ToString ()); view.Height += 1; - Assert.Equal ($"DimAbsolute({i + 2})", view.Height.ToString ()); + Assert.Equal ($"Absolute({i + 2})", view.Height.ToString ()); } } @@ -1149,7 +1149,7 @@ namespace Terminal.Gui.TypeTests { Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text); view.Remove (listLabels [count - 1]); listLabels.RemoveAt (count - 1); - Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ()); view.Height -= 1; count--; if (listLabels.Count > 0) @@ -1157,7 +1157,7 @@ namespace Terminal.Gui.TypeTests { else field.Text = NStack.ustring.Empty; } - Assert.Equal ($"DimAbsolute({count + 1})", view.Height.ToString ()); + Assert.Equal ($"Absolute({count + 1})", view.Height.ToString ()); } }; diff --git a/UnitTests/Types/PosTests.cs b/UnitTests/Types/PosTests.cs index 1a63dc854..44b43dd7d 100644 --- a/UnitTests/Types/PosTests.cs +++ b/UnitTests/Types/PosTests.cs @@ -32,11 +32,11 @@ namespace Terminal.Gui.TypeTests { { var n = 0; var pos = Pos.AnchorEnd (); - Assert.Equal ($"PosAnchorEnd({n})", pos.ToString ()); + Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); n = 5; pos = Pos.AnchorEnd (n); - Assert.Equal ($"PosAnchorEnd({n})", pos.ToString ()); + Assert.Equal ($"AnchorEnd({n})", pos.ToString ()); } [Fact] @@ -351,13 +351,13 @@ namespace Terminal.Gui.TypeTests { public void At_SetsValue () { var pos = Pos.At (0); - Assert.Equal ("PosAbsolute(0)", pos.ToString ()); + Assert.Equal ("Absolute(0)", pos.ToString ()); pos = Pos.At (5); - Assert.Equal ("PosAbsolute(5)", pos.ToString ()); + Assert.Equal ("Absolute(5)", pos.ToString ()); pos = Pos.At (-1); - Assert.Equal ("PosAbsolute(-1)", pos.ToString ()); + Assert.Equal ("Absolute(-1)", pos.ToString ()); } [Fact] @@ -411,140 +411,140 @@ namespace Terminal.Gui.TypeTests { testInt = 0; testRect = Rect.Empty; pos = Pos.Left (new View ()); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); pos = Pos.Left (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testRect = new Rect (1, 2, 3, 4); pos = Pos.Left (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Left(win) + 0 pos = Pos.Left (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = 1; // Pos.Left(win) +1 pos = Pos.Left (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = -1; // Pos.Left(win) -1 pos = Pos.Left (new View (testRect)) - testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.X side = "x"; testInt = 0; testRect = Rect.Empty; pos = Pos.X (new View ()); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); pos = Pos.X (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testRect = new Rect (1, 2, 3, 4); pos = Pos.X (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.X(win) + 0 pos = Pos.X (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = 1; // Pos.X(win) +1 pos = Pos.X (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = -1; // Pos.X(win) -1 pos = Pos.X (new View (testRect)) - testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Top side = "y"; testInt = 0; testRect = Rect.Empty; pos = Pos.Top (new View ()); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); pos = Pos.Top (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testRect = new Rect (1, 2, 3, 4); pos = Pos.Top (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Top(win) + 0 pos = Pos.Top (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = 1; // Pos.Top(win) +1 pos = Pos.Top (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = -1; // Pos.Top(win) -1 pos = Pos.Top (new View (testRect)) - testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Y side = "y"; testInt = 0; testRect = Rect.Empty; pos = Pos.Y (new View ()); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); pos = Pos.Y (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testRect = new Rect (1, 2, 3, 4); pos = Pos.Y (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Y(win) + 0 pos = Pos.Y (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = 1; // Pos.Y(win) +1 pos = Pos.Y (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = -1; // Pos.Y(win) -1 pos = Pos.Y (new View (testRect)) - testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Bottom side = "bottom"; testRect = Rect.Empty; testInt = 0; pos = Pos.Bottom (new View ()); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); pos = Pos.Bottom (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testRect = new Rect (1, 2, 3, 4); pos = Pos.Bottom (new View (testRect)); - Assert.Equal ($"PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}})){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); // Pos.Bottom(win) + 0 pos = Pos.Bottom (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = 1; // Pos.Bottom(win) +1 pos = Pos.Bottom (new View (testRect)) + testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); testInt = -1; // Pos.Bottom(win) -1 pos = Pos.Bottom (new View (testRect)) - testInt; - Assert.Equal ($"PosCombine(PosCombine(PosView({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+PosAbsolute(0)){(testInt < 0 ? '-' : '+')}PosAbsolute({testInt}))", pos.ToString ()); + Assert.Equal ($"Combine(Combine(View({side},View()({{X={testRect.X},Y={testRect.Y},Width={testRect.Width},Height={testRect.Height}}}))+Absolute(0)){(testInt < 0 ? '-' : '+')}Absolute({testInt}))", pos.ToString ()); } // See: https://github.com/gui-cs/Terminal.Gui/issues/504 @@ -632,7 +632,7 @@ namespace Terminal.Gui.TypeTests { public void Center_SetsValue () { var pos = Pos.Center (); - Assert.Equal ("PosCenter", pos.ToString ()); + Assert.Equal ("Center", pos.ToString ()); } [Fact] @@ -640,13 +640,13 @@ namespace Terminal.Gui.TypeTests { { float f = 0; var pos = Pos.Percent (f); - Assert.Equal ($"PosFactor({f / 100:0.###})", pos.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ()); f = 0.5F; pos = Pos.Percent (f); - Assert.Equal ($"PosFactor({f / 100:0.###})", pos.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ()); f = 100; pos = Pos.Percent (f); - Assert.Equal ($"PosFactor({f / 100:0.###})", pos.ToString ()); + Assert.Equal ($"Factor({f / 100:0.###})", pos.ToString ()); } [Fact] @@ -881,12 +881,12 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 }; view.Add (label); Assert.Equal ($"Label {count}", label.Text); - Assert.Equal ($"PosAbsolute({count})", label.Y.ToString ()); + Assert.Equal ($"Absolute({count})", label.Y.ToString ()); - Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ()); + Assert.Equal ($"Absolute({count})", field.Y.ToString ()); field.Y += 1; count++; - Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ()); + Assert.Equal ($"Absolute({count})", field.Y.ToString ()); } }; @@ -928,12 +928,12 @@ namespace Terminal.Gui.TypeTests { var label = new Label (field.Text) { X = 0, Y = field.Y, Width = 20 }; view.Add (label); Assert.Equal ($"Label {i}", label.Text); - Assert.Equal ($"PosAbsolute({i})", field.Y.ToString ()); + Assert.Equal ($"Absolute({i})", field.Y.ToString ()); listLabels.Add (label); - Assert.Equal ($"PosAbsolute({i})", field.Y.ToString ()); + Assert.Equal ($"Absolute({i})", field.Y.ToString ()); field.Y += 1; - Assert.Equal ($"PosAbsolute({i + 1})", field.Y.ToString ()); + Assert.Equal ($"Absolute({i + 1})", field.Y.ToString ()); } field.KeyDown += (k) => { @@ -941,10 +941,10 @@ namespace Terminal.Gui.TypeTests { Assert.Equal ($"Label {count - 1}", listLabels [count - 1].Text); view.Remove (listLabels [count - 1]); - Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ()); + Assert.Equal ($"Absolute({count})", field.Y.ToString ()); field.Y -= 1; count--; - Assert.Equal ($"PosAbsolute({count})", field.Y.ToString ()); + Assert.Equal ($"Absolute({count})", field.Y.ToString ()); } }; diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs index 39ccd3bf9..8a22ca13c 100644 --- a/UnitTests/Views/ScrollBarViewTests.cs +++ b/UnitTests/Views/ScrollBarViewTests.cs @@ -362,85 +362,85 @@ namespace Terminal.Gui.ViewTests { _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); - Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width); - Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Lines = 10; _hostView.Redraw (_hostView.Bounds); Assert.False (_scrollBar.ShowScrollIndicator); Assert.False (_scrollBar.Visible); - Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))", + Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); - Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Cols = 60; _hostView.Redraw (_hostView.Bounds); Assert.False (_scrollBar.ShowScrollIndicator); Assert.False (_scrollBar.Visible); - Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.False (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))", + Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); - Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Lines = 40; _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); - Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))", + Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.Height.ToString ()); Assert.Equal (25, _scrollBar.Bounds.Height); Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.False (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(0))", + Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); - Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); _hostView.Cols = 120; _hostView.Redraw (_hostView.Bounds); Assert.True (_scrollBar.ShowScrollIndicator); Assert.True (_scrollBar.Visible); - Assert.Equal ("DimAbsolute(1)", _scrollBar.Width.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("DimCombine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("DimCombine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-DimAbsolute(1))", + Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width); - Assert.Equal ("DimAbsolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); + Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); Assert.Equal (1, _scrollBar.OtherScrollBarView.Bounds.Height); } diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index 0247f53bc..c90f9105f 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -31,7 +31,7 @@ namespace Terminal.Gui.ViewTests { Assert.False (sb.CanFocus); Assert.Equal (Colors.Menu, sb.ColorScheme); Assert.Equal (0, sb.X); - Assert.Equal ("PosAnchorEnd(1)", sb.Y.ToString ()); + Assert.Equal ("AnchorEnd(1)", sb.Y.ToString ()); Assert.Equal (Dim.Fill (), sb.Width); Assert.Equal (1, sb.Height); diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index 455296478..981ff2d14 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -1524,8 +1524,8 @@ namespace Terminal.Gui.ViewTests { Assert.True (_textView.AllowsReturn); Assert.Equal (4, _textView.TabWidth); Assert.True (_textView.AllowsTab); - Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ()); - Assert.Equal ("DimAbsolute(10)", _textView.Height.ToString ()); + Assert.Equal ("Absolute(30)", _textView.Width.ToString ()); + Assert.Equal ("Absolute(10)", _textView.Height.ToString ()); Assert.False (_textView.WordWrap); _textView.WordWrap = true; @@ -1535,8 +1535,8 @@ namespace Terminal.Gui.ViewTests { Assert.False (_textView.AllowsReturn); Assert.Equal (0, _textView.TabWidth); Assert.False (_textView.AllowsTab); - Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ()); - Assert.Equal ("DimAbsolute(1)", _textView.Height.ToString ()); + Assert.Equal ("Absolute(30)", _textView.Width.ToString ()); + Assert.Equal ("Absolute(1)", _textView.Height.ToString ()); Assert.False (_textView.WordWrap); _textView.WordWrap = true; @@ -1546,8 +1546,8 @@ namespace Terminal.Gui.ViewTests { Assert.True (_textView.AllowsReturn); Assert.Equal (4, _textView.TabWidth); Assert.True (_textView.AllowsTab); - Assert.Equal ("DimAbsolute(30)", _textView.Width.ToString ()); - Assert.Equal ("DimAbsolute(10)", _textView.Height.ToString ()); + Assert.Equal ("Absolute(30)", _textView.Width.ToString ()); + Assert.Equal ("Absolute(10)", _textView.Height.ToString ()); Assert.False (_textView.WordWrap); } From fac0d9a52efd0d3e300f7875aba791c8f3cf1085 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 18:36:02 +0000 Subject: [PATCH 73/88] Revert "ToString() is to force throw if View is null. Good catch." This reverts commit 19dbb41e711e4ec0a6ec084a227c211b402f4ca4. --- Terminal.Gui/Core/PosDim.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/Core/PosDim.cs index 6334682d6..54948bca9 100644 --- a/Terminal.Gui/Core/PosDim.cs +++ b/Terminal.Gui/Core/PosDim.cs @@ -264,7 +264,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosCombine({left.ToString ()}{(add ? '+' : '-')}{right.ToString ()})"; + return $"PosCombine({left}{(add ? '+' : '-')}{right})"; } } @@ -345,7 +345,7 @@ namespace Terminal.Gui { case 3: tside = "bottom"; break; default: tside = "unknown"; break; } - return $"PosView({tside},{Target.ToString()})"; + return $"PosView({tside},{Target})"; } public override int GetHashCode () => Target.GetHashCode (); @@ -613,7 +613,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimCombine({left}{(add ? '+' : '-')}{right.ToString ()})"; + return $"DimCombine({left}{(add ? '+' : '-')}{right})"; } } @@ -691,7 +691,7 @@ namespace Terminal.Gui { case 1: tside = "Width"; break; default: tside = "unknown"; break; } - return $"DimView({tside},{Target.ToString ()})"; + return $"DimView({tside},{Target})"; } public override int GetHashCode () => Target.GetHashCode (); From e09ddf3a5a280687d407a65fe42db1c85412f17a Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 18:36:48 +0000 Subject: [PATCH 74/88] Revert "ToString must return the Pos/Dim class name. Also Target.ToString() is not needed because they already overridden the ToString method." This reverts commit 47ca62d5f2de6936f4ecd46d84f0ed30eb26fa42. --- Terminal.Gui/Core/PosDim.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/Core/PosDim.cs index 54948bca9..696607696 100644 --- a/Terminal.Gui/Core/PosDim.cs +++ b/Terminal.Gui/Core/PosDim.cs @@ -85,7 +85,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosFactor({factor})"; + return $"Factor({factor})"; } public override int GetHashCode () => factor.GetHashCode (); @@ -135,7 +135,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosAnchorEnd({n})"; + return $"AnchorEnd({n})"; } } @@ -174,7 +174,7 @@ namespace Terminal.Gui { public override string ToString () { - return "PosCenter"; + return "Center"; } } @@ -209,7 +209,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosAbsolute({n})"; + return $"Absolute({n})"; } internal override int Anchor (int width) @@ -264,7 +264,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"PosCombine({left}{(add ? '+' : '-')}{right})"; + return $"Combine({left}{(add ? '+' : '-')}{right})"; } } @@ -345,7 +345,7 @@ namespace Terminal.Gui { case 3: tside = "bottom"; break; default: tside = "unknown"; break; } - return $"PosView({tside},{Target})"; + return $"View({tside},{Target.ToString()})"; } public override int GetHashCode () => Target.GetHashCode (); @@ -482,7 +482,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimFactor({factor},{remaining})"; + return $"Factor({factor},{remaining})"; } public override int GetHashCode () => factor.GetHashCode (); @@ -522,7 +522,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimAbsolute({n})"; + return $"Absolute({n})"; } internal override int Anchor (int width) @@ -541,7 +541,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimFill({margin})"; + return $"Fill({margin})"; } internal override int Anchor (int width) @@ -613,7 +613,7 @@ namespace Terminal.Gui { public override string ToString () { - return $"DimCombine({left}{(add ? '+' : '-')}{right})"; + return $"Combine({left}{(add ? '+' : '-')}{right})"; } } @@ -691,7 +691,7 @@ namespace Terminal.Gui { case 1: tside = "Width"; break; default: tside = "unknown"; break; } - return $"DimView({tside},{Target})"; + return $"DimView({tside},{Target.ToString ()})"; } public override int GetHashCode () => Target.GetHashCode (); From 2f8db4c9a0e831e5deb10d36011c600997b48800 Mon Sep 17 00:00:00 2001 From: Tigger Kindel Date: Fri, 3 Mar 2023 12:05:47 -0700 Subject: [PATCH 75/88] Added JsonIgnore to Border.Child; fixes unit test fail for config man --- Terminal.Gui/Configuration/Scope.cs | 6 +++++- Terminal.Gui/Core/Border.cs | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/Configuration/Scope.cs b/Terminal.Gui/Configuration/Scope.cs index 7e8aceb79..77a765e1b 100644 --- a/Terminal.Gui/Configuration/Scope.cs +++ b/Terminal.Gui/Configuration/Scope.cs @@ -129,7 +129,11 @@ namespace Terminal.Gui.Configuration { } } var readHelper = Activator.CreateInstance ((Type?)typeof (ReadHelper<>).MakeGenericType (typeof (scopeT), propertyType!)!, converter) as ReadHelper; - scope! [propertyName].PropertyValue = readHelper?.Read (ref reader, propertyType!, options); + try { + scope! [propertyName].PropertyValue = readHelper?.Read (ref reader, propertyType!, options); + } catch (NotSupportedException e) { + throw new JsonException ($"Error reading property \"{propertyName}\" of type \"{propertyType.Name}\".", e); + } } else { scope! [propertyName].PropertyValue = JsonSerializer.Deserialize (ref reader, propertyType!, options); } diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index 95a0f19f9..cce71b219 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -448,6 +448,7 @@ namespace Terminal.Gui { /// /// Gets or sets the single child element of a . /// + [JsonIgnore] public View Child { get => child; set { From 8ab01b084759107bd3cee424a0c26d8626ddcebe Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 3 Mar 2023 19:14:52 +0000 Subject: [PATCH 76/88] Renaming DimView to View. --- Terminal.Gui/Core/PosDim.cs | 4 ++-- UnitTests/Types/DimTests.cs | 24 ++++++++++++------------ UnitTests/Views/ScrollBarViewTests.cs | 20 ++++++++++---------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Terminal.Gui/Core/PosDim.cs b/Terminal.Gui/Core/PosDim.cs index 696607696..91787b434 100644 --- a/Terminal.Gui/Core/PosDim.cs +++ b/Terminal.Gui/Core/PosDim.cs @@ -345,7 +345,7 @@ namespace Terminal.Gui { case 3: tside = "bottom"; break; default: tside = "unknown"; break; } - return $"View({tside},{Target.ToString()})"; + return $"View({tside},{Target.ToString ()})"; } public override int GetHashCode () => Target.GetHashCode (); @@ -691,7 +691,7 @@ namespace Terminal.Gui { case 1: tside = "Width"; break; default: tside = "unknown"; break; } - return $"DimView({tside},{Target.ToString ()})"; + return $"View({tside},{Target.ToString ()})"; } public override int GetHashCode () => Target.GetHashCode (); diff --git a/UnitTests/Types/DimTests.cs b/UnitTests/Types/DimTests.cs index 5a98d5db9..04ba0ef4e 100644 --- a/UnitTests/Types/DimTests.cs +++ b/UnitTests/Types/DimTests.cs @@ -83,11 +83,11 @@ namespace Terminal.Gui.TypeTests { var testVal = Rect.Empty; testVal = Rect.Empty; dim = Dim.Width (new View (testVal)); - Assert.Equal ($"DimView(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); + Assert.Equal ($"View(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); testVal = new Rect (1, 2, 3, 4); dim = Dim.Width (new View (testVal)); - Assert.Equal ($"DimView(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); + Assert.Equal ($"View(Width,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); } [Fact] @@ -141,11 +141,11 @@ namespace Terminal.Gui.TypeTests { var testVal = Rect.Empty; testVal = Rect.Empty; dim = Dim.Height (new View (testVal)); - Assert.Equal ($"DimView(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); + Assert.Equal ($"View(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); testVal = new Rect (1, 2, 3, 4); dim = Dim.Height (new View (testVal)); - Assert.Equal ($"DimView(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); + Assert.Equal ($"View(Height,View()({{X={testVal.X},Y={testVal.Y},Width={testVal.Width},Height={testVal.Height}}}))", dim.ToString ()); } // TODO: Other Dim.Height tests (e.g. Equal?) @@ -435,12 +435,12 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (49, f2.Frame.Width); // 50-1=49 Assert.Equal (5, f2.Frame.Height); - Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.ToString ()); + Assert.Equal ("Combine(View(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.ToString ()); Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ()); Assert.Equal (47, v1.Frame.Width); // 49-2=47 Assert.Equal (89, v1.Frame.Height); // 98-5-2-2=89 - Assert.Equal ("Combine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.ToString ()); + Assert.Equal ("Combine(View(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.ToString ()); Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ()); Assert.Equal (47, v2.Frame.Width); // 49-2=47 Assert.Equal (89, v2.Frame.Height); // 98-5-2-2=89 @@ -455,8 +455,8 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (50, v4.Frame.Width); Assert.Equal (50, v4.Frame.Height); - Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ()); - Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ()); + Assert.Equal ("Combine(View(Width,Button()({X=2,Y=7,Width=47,Height=89}))-View(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ()); + Assert.Equal ("Combine(View(Height,Button()({X=2,Y=7,Width=47,Height=89}))-View(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ()); Assert.Equal (38, v5.Frame.Width); // 47-9=38 Assert.Equal (80, v5.Frame.Height); // 89-9=80 @@ -487,13 +487,13 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (5, f2.Frame.Height); v1.Text = "Button1"; - Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=99,Height=5}))-Absolute(2))", v1.Width.ToString ()); + Assert.Equal ("Combine(View(Width,FrameView()({X=0,Y=0,Width=99,Height=5}))-Absolute(2))", v1.Width.ToString ()); Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ()); Assert.Equal (97, v1.Frame.Width); // 99-2=97 Assert.Equal (189, v1.Frame.Height); // 198-2-7=189 v2.Text = "Button2"; - Assert.Equal ("Combine(DimView(Width,FrameView()({X=99,Y=0,Width=99,Height=5}))-Absolute(2))", v2.Width.ToString ()); + Assert.Equal ("Combine(View(Width,FrameView()({X=99,Y=0,Width=99,Height=5}))-Absolute(2))", v2.Width.ToString ()); Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ()); Assert.Equal (97, v2.Frame.Width); // 99-2=97 Assert.Equal (189, v2.Frame.Height); // 198-2-7=189 @@ -517,8 +517,8 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (1, v4.Frame.Height); // 1 because is Dim.DimAbsolute v5.Text = "Button5"; - Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ()); - Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=97,Height=189}))-DimView(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ()); + Assert.Equal ("Combine(View(Width,Button()({X=2,Y=7,Width=97,Height=189}))-View(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ()); + Assert.Equal ("Combine(View(Height,Button()({X=2,Y=7,Width=97,Height=189}))-View(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ()); Assert.Equal (78, v5.Frame.Width); // 97-19=78 Assert.Equal (170, v5.Frame.Height); // 189-19=170 diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs index 8a22ca13c..78b1c568b 100644 --- a/UnitTests/Views/ScrollBarViewTests.cs +++ b/UnitTests/Views/ScrollBarViewTests.cs @@ -364,12 +364,12 @@ namespace Terminal.Gui.ViewTests { Assert.True (_scrollBar.Visible); Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); @@ -381,12 +381,12 @@ namespace Terminal.Gui.ViewTests { Assert.False (_scrollBar.Visible); Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", + Assert.Equal ("Combine(View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); @@ -398,12 +398,12 @@ namespace Terminal.Gui.ViewTests { Assert.False (_scrollBar.Visible); Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.False (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", + Assert.Equal ("Combine(View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); @@ -415,12 +415,12 @@ namespace Terminal.Gui.ViewTests { Assert.True (_scrollBar.Visible); Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", + Assert.Equal ("Combine(View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.Height.ToString ()); Assert.Equal (25, _scrollBar.Bounds.Height); Assert.False (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.False (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", + Assert.Equal ("Combine(View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(0))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (80, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); @@ -432,12 +432,12 @@ namespace Terminal.Gui.ViewTests { Assert.True (_scrollBar.Visible); Assert.Equal ("Absolute(1)", _scrollBar.Width.ToString ()); Assert.Equal (1, _scrollBar.Bounds.Width); - Assert.Equal ("Combine(DimView(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Height,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.Height.ToString ()); Assert.Equal (24, _scrollBar.Bounds.Height); Assert.True (_scrollBar.OtherScrollBarView.ShowScrollIndicator); Assert.True (_scrollBar.OtherScrollBarView.Visible); - Assert.Equal ("Combine(DimView(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", + Assert.Equal ("Combine(View(Width,HostView()({X=0,Y=0,Width=80,Height=25}))-Absolute(1))", _scrollBar.OtherScrollBarView.Width.ToString ()); Assert.Equal (79, _scrollBar.OtherScrollBarView.Bounds.Width); Assert.Equal ("Absolute(1)", _scrollBar.OtherScrollBarView.Height.ToString ()); From 56ab04d5bd0f68ba4073600e1c367e6cedc27a00 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 01:48:37 +0000 Subject: [PATCH 77/88] Fixes Autocomplete broken with null references. --- Terminal.Gui/Core/Autocomplete/Autocomplete.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/Core/Autocomplete/Autocomplete.cs b/Terminal.Gui/Core/Autocomplete/Autocomplete.cs index 61ccc01ea..728332773 100644 --- a/Terminal.Gui/Core/Autocomplete/Autocomplete.cs +++ b/Terminal.Gui/Core/Autocomplete/Autocomplete.cs @@ -106,7 +106,7 @@ namespace Terminal.Gui { } if (!Visible && popup != null) { - top.Remove (popup); + top?.Remove (popup); popup.Dispose (); popup = null; } @@ -323,6 +323,7 @@ namespace Terminal.Gui { { if (IsWordChar ((char)kb.Key)) { Visible = true; + ManipulatePopup (); closed = false; return false; } From 2880247cbcf9d749249ff8c48d25e0b3f1872524 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 01:50:38 +0000 Subject: [PATCH 78/88] Fixes Toplevel which was broken with many unit tests fails. --- Terminal.Gui/Core/Toplevel.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 63e11e626..022addccc 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -749,15 +749,23 @@ namespace Terminal.Gui { if (view.Frame.IntersectsWith (bounds) && !OutsideTopFrame (this)) { view.SetNeedsLayout (); view.SetNeedsDisplay (view.Bounds); - //view.Redraw (view.Bounds); + if (SuperView == null && view.Visible && view.Frame.Width > 0 && view.Frame.Height > 0) { + view.OnDrawContent (view.Bounds); + view.Redraw (view.Bounds); + view.OnDrawContentComplete (view.Bounds); + } } } - ClearLayoutNeeded (); - ClearNeedsDisplay (); + if (SuperView != null) { + ClearLayoutNeeded (); + ClearNeedsDisplay (); + } } - base.Redraw (Bounds); + if (SuperView != null) { + base.Redraw (Bounds); + } } bool OutsideTopFrame (Toplevel top) From 6c44b0413dabdbac7e53e0b56fbc9d5763dc1a8d Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 01:57:44 +0000 Subject: [PATCH 79/88] Removing GetMaxNeedDisplay that was causing false changed values. --- Terminal.Gui/Core/View.cs | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 045a8a53a..04c3dc9ad 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -447,11 +447,10 @@ namespace Terminal.Gui { public virtual Rect Frame { get => frame; set { - var rect = GetMaxNeedDisplay (frame, value); frame = new Rect (value.X, value.Y, Math.Max (value.Width, 0), Math.Max (value.Height, 0)); TextFormatter.Size = GetBoundsTextFormatterSize (); SetNeedsLayout (); - SetNeedsDisplay (rect); + SetNeedsDisplay (); } } @@ -824,26 +823,7 @@ namespace Terminal.Gui { } TextFormatter.Size = GetBoundsTextFormatterSize (); SetNeedsLayout (); - SetNeedsDisplay (GetMaxNeedDisplay (oldFrame, frame)); - } - - Rect GetMaxNeedDisplay (Rect oldFrame, Rect newFrame) - { - var topSuperView = GetTopSuperView (); - if (topSuperView == null || topSuperView is not Toplevel || ((Toplevel)topSuperView)?.IsLoaded == false) { - return newFrame; - } - - var rect = new Rect () { - X = Math.Min (oldFrame.X, newFrame.X), - Y = Math.Min (oldFrame.Y, newFrame.Y), - Width = Math.Max (oldFrame.Width, newFrame.Width), - Height = Math.Max (oldFrame.Height, newFrame.Height) - }; - rect.Width += Math.Max (oldFrame.X - newFrame.X, 0); - rect.Height += Math.Max (oldFrame.Y - newFrame.Y, 0); - - return rect; + SetNeedsDisplay (); } void TextFormatter_HotKeyChanged (Key obj) From 25e1b16c07fd72f2ff4c64e37914857f6950eaf8 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 01:59:39 +0000 Subject: [PATCH 80/88] Removed Title from the Redraw and typo fices. --- Terminal.Gui/Core/Window.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs index 5d08d608f..795d360ec 100644 --- a/Terminal.Gui/Core/Window.cs +++ b/Terminal.Gui/Core/Window.cs @@ -7,7 +7,7 @@ // - FrameView Does not support padding (but should) // - FrameView Does not support mouse dragging // - FrameView Does not support IEnumerable -// Any udpates done here should probably be done in FrameView as well; TODO: Merge these classes +// Any updates done here should probably be done in FrameView as well; TODO: Merge these classes using System; using System.Collections; @@ -308,7 +308,6 @@ namespace Terminal.Gui { ClearNeedsDisplay (); Driver.SetAttribute (GetNormalColor ()); - Border.Title = Title; // not sure why Title is getting un-set Border.DrawContent (this, false); } @@ -346,7 +345,7 @@ namespace Terminal.Gui { } /// - /// Event arguments for chane events. + /// Event arguments for change events. /// public class TitleEventArgs : EventArgs { /// @@ -360,7 +359,7 @@ namespace Terminal.Gui { public ustring OldTitle { get; set; } /// - /// Flag which allows cancelling the Title change. + /// Flag which allows canceling the Title change. /// public bool Cancel { get; set; } @@ -380,7 +379,7 @@ namespace Terminal.Gui { /// /// The that is/has been replaced. /// The new to be replaced. - /// `true` if an event handler cancelled the Title change. + /// `true` if an event handler canceled the Title change. public virtual bool OnTitleChanging (ustring oldTitle, ustring newTitle) { var args = new TitleEventArgs (oldTitle, newTitle); From c7b5417f79a41cd52635b00ae147f5f22b361e89 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 02:02:02 +0000 Subject: [PATCH 81/88] Fixes unit tests. --- UnitTests/Core/LayoutTests.cs | 9 +-- UnitTests/Core/ViewTests.cs | 89 +++++++++++++------------- UnitTests/TopLevels/MessageBoxTests.cs | 12 ++-- UnitTests/TopLevels/ToplevelTests.cs | 22 +++---- UnitTests/Types/DimTests.cs | 1 + 5 files changed, 66 insertions(+), 67 deletions(-) diff --git a/UnitTests/Core/LayoutTests.cs b/UnitTests/Core/LayoutTests.cs index de0c94065..2df14ba13 100644 --- a/UnitTests/Core/LayoutTests.cs +++ b/UnitTests/Core/LayoutTests.cs @@ -382,7 +382,7 @@ namespace Terminal.Gui.CoreTests { // Here the AutoSize ensuring the right size Assert.True (label.AutoSize); - Assert.Equal ("{X=0,Y=0,Width=28,Height=2}", label.Bounds.ToString ()); + Assert.Equal ("{X=0,Y=0,Width=11,Height=2}", label.Bounds.ToString ()); label.AutoSize = false; Application.Refresh (); @@ -508,9 +508,10 @@ Y Assert.Equal ("123 ", GetContents ()); lbl.Text = "12"; - - lbl.SuperView.Redraw (lbl.SuperView.NeedDisplay); - + Assert.Equal (new Rect (0, 0, 3, 1), lbl.Frame); + Assert.Equal (new Rect (0, 0, 3, 1), lbl.NeedDisplay); + Assert.Equal (new Rect (0, 0, 80, 25), lbl.SuperView.NeedDisplay); + lbl.SuperView.Redraw (lbl.SuperView.Bounds); Assert.Equal ("12 ", GetContents ()); string GetContents () diff --git a/UnitTests/Core/ViewTests.cs b/UnitTests/Core/ViewTests.cs index 110f76bfe..db4d54299 100644 --- a/UnitTests/Core/ViewTests.cs +++ b/UnitTests/Core/ViewTests.cs @@ -2353,21 +2353,7 @@ This is a tes return true; } - public void CorrectRedraw (Rect bounds) - { - // Clear the old and new frame area - Clear (NeedDisplay); - DrawText (); - } - - public void IncorrectRedraw (Rect bounds) - { - // Clear only the new frame area - Clear (); - DrawText (); - } - - private void DrawText () + public override void Redraw (Rect bounds) { var idx = 0; for (int r = 0; r < Frame.Height; r++) { @@ -2501,7 +2487,7 @@ This is a tes [InlineData (false)] public void Clear_Does_Not_Spillover_Its_Parent (bool label) { - var root = new View () { Width = 20, Height = 10 }; + var root = new View () { Width = 20, Height = 10, ColorScheme = Colors.Base }; var v = label == true ? new Label (new string ('c', 100)) { @@ -2533,15 +2519,17 @@ cccccccccccccccccccc", output); var attributes = new Attribute [] { Colors.TopLevel.Normal, - Colors.TopLevel.Focus, - + Colors.Base.Normal, + Colors.Base.Focus }; if (label) { TestHelpers.AssertDriverColorsAre (@" -000000000000000000000", attributes); +111111111111111111110 +111111111111111111110", attributes); } else { TestHelpers.AssertDriverColorsAre (@" -111111111111111111110", attributes); +222222222222222222220 +222222222222222222220", attributes); } if (label) { @@ -2552,7 +2540,8 @@ cccccccccccccccccccc", output); Assert.True (v.HasFocus); Application.Refresh (); TestHelpers.AssertDriverColorsAre (@" -111111111111111111110", attributes); +222222222222222222220 +222222222222222222220", attributes); } } @@ -2571,7 +2560,7 @@ cccccccccccccccccccc", output); top.Add (label, view); Application.Begin (top); - view.CorrectRedraw (view.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2579,9 +2568,12 @@ At 0,0 and also with two lines. ", output); view.Frame = new Rect (1, 1, 10, 1); + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay); - view.CorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view.NeedDisplay); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 A text wit", output); @@ -2602,7 +2594,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.CorrectRedraw (view.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2615,8 +2607,8 @@ At 0,0 view.Height = 1; Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay); - view.CorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view.NeedDisplay); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 A text wit", output); @@ -2637,7 +2629,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.IncorrectRedraw (view.Bounds); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2645,9 +2637,12 @@ At 0,0 and also with two lines. ", output); view.Frame = new Rect (1, 1, 10, 1); + Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay); - view.IncorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view.NeedDisplay); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 A text wit @@ -2670,7 +2665,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.IncorrectRedraw (view.Bounds); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2683,8 +2678,8 @@ At 0,0 view.Height = 1; Assert.Equal (new Rect (1, 1, 10, 1), view.Frame); Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (1, 1, 31, 3), view.NeedDisplay); - view.IncorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view.NeedDisplay); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 A text wit @@ -2707,7 +2702,6 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.CorrectRedraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2715,9 +2709,12 @@ At 0,0 and also with two lines. ", output); view.Frame = new Rect (3, 3, 10, 1); + Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); + Assert.Equal (LayoutStyle.Computed, view.LayoutStyle); + view.LayoutStyle = LayoutStyle.Absolute; Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (2, 2, 30, 2), view.NeedDisplay); - view.CorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view.NeedDisplay); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2740,7 +2737,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.CorrectRedraw (view.Bounds); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2753,8 +2750,8 @@ At 0,0 view.Height = 1; Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (2, 2, 30, 2), view.NeedDisplay); - view.CorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view.NeedDisplay); + top.Redraw (top.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2777,7 +2774,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.IncorrectRedraw (view.Bounds); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2786,8 +2783,8 @@ At 0,0 view.Frame = new Rect (3, 3, 10, 1); Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (2, 2, 30, 2), view.NeedDisplay); - view.IncorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 10, 1), view.NeedDisplay); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2810,7 +2807,7 @@ At 0,0 top.Add (label, view); Application.Begin (top); - view.IncorrectRedraw (view.Bounds); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2823,8 +2820,8 @@ At 0,0 view.Height = 1; Assert.Equal (new Rect (3, 3, 10, 1), view.Frame); Assert.Equal (new Rect (0, 0, 10, 1), view.Bounds); - Assert.Equal (new Rect (2, 2, 30, 2), view.NeedDisplay); - view.IncorrectRedraw (view.Bounds); + Assert.Equal (new Rect (0, 0, 30, 2), view.NeedDisplay); + view.Redraw (view.Bounds); TestHelpers.AssertDriverContentsWithFrameAre (@" At 0,0 @@ -2919,7 +2916,7 @@ At 0,0 if (top.IsLoaded) { Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay); } else { - Assert.Equal (new Rect (1, 1, 38, 6), frame.Subviews [0].NeedDisplay); + Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay); } }; diff --git a/UnitTests/TopLevels/MessageBoxTests.cs b/UnitTests/TopLevels/MessageBoxTests.cs index 3847922ed..d6b7e1cc2 100644 --- a/UnitTests/TopLevels/MessageBoxTests.cs +++ b/UnitTests/TopLevels/MessageBoxTests.cs @@ -29,7 +29,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌ Title ───────────────────────────────────────┐ │ Message │ @@ -71,7 +71,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌ About UI Catalog ──────────────────────────────────────────┐ │ A comprehensive sample library for │ @@ -110,7 +110,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌─────┐ │Messa│ @@ -140,7 +140,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌ Title ──┐ │ Message │ @@ -170,7 +170,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌ mywindow ────────────────────────────────────────────────────────────────────┐ │ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff│ @@ -224,7 +224,7 @@ namespace Terminal.Gui.TopLevelTests { Application.RequestStop (); } else if (iterations == 1) { - Application.Top.Redraw (Application.Top.Bounds); + Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre (@" ┌ mywindow ────────────────────────────────────────────────────────────────────┐ │ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff │ diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs index 1f4382813..a6f803af0 100644 --- a/UnitTests/TopLevels/ToplevelTests.cs +++ b/UnitTests/TopLevels/ToplevelTests.cs @@ -900,9 +900,9 @@ namespace Terminal.Gui.TopLevelTests { TestHelpers.AssertDriverContentsWithFrameAre (@" File - ┌─────┐ - │ │ - └─────┘ + ┌────┐ + │ │ + └────┘ @@ -910,7 +910,7 @@ namespace Terminal.Gui.TopLevelTests { CTRL-N New", output); Assert.Equal (win, Application.MouseGrabView); - Assert.Equal (new Rect (4, 2, 7, 3), Application.MouseGrabView.Frame); + Assert.Equal (new Rect (4, 2, 6, 3), Application.MouseGrabView.Frame); } else if (iterations == 3) { Assert.Equal (win, Application.MouseGrabView); @@ -931,10 +931,10 @@ namespace Terminal.Gui.TopLevelTests { TestHelpers.AssertDriverContentsWithFrameAre (@" File - ┌─────┐ - │ │ - └─────┘ - + ┌────┐ + │ │ + │ │ + └────┘ @@ -942,7 +942,7 @@ namespace Terminal.Gui.TopLevelTests { CTRL-N New", output); Assert.Equal (win, Application.MouseGrabView); - Assert.Equal (new Rect (4, 1, 7, 3), Application.MouseGrabView.Frame); + Assert.Equal (new Rect (4, 1, 6, 4), Application.MouseGrabView.Frame); } else if (iterations == 5) { Assert.Equal (win, Application.MouseGrabView); @@ -1074,12 +1074,12 @@ namespace Terminal.Gui.TopLevelTests { view.Frame = new Rect (1, 3, 10, 5); Assert.Equal (new Rect (1, 3, 10, 5), view.Frame); - Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay); + Assert.Equal (new Rect (0, 0, 10, 5), view.NeedDisplay); view.Redraw (view.Bounds); view.Frame = new Rect (1, 3, 10, 5); Assert.Equal (new Rect (1, 3, 10, 5), view.Frame); - Assert.Equal (new Rect (1, 3, 10, 5), view.NeedDisplay); + Assert.Equal (new Rect (0, 0, 10, 5), view.NeedDisplay); } } } \ No newline at end of file diff --git a/UnitTests/Types/DimTests.cs b/UnitTests/Types/DimTests.cs index 04ba0ef4e..a56dcf818 100644 --- a/UnitTests/Types/DimTests.cs +++ b/UnitTests/Types/DimTests.cs @@ -466,6 +466,7 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (18, v6.Frame.Height); // 89*20%=18 w.Width = 200; + Assert.True (t.LayoutNeeded); w.Height = 200; t.LayoutSubviews (); From ffc06ea59fddbc2a5c4cc85ddee95688aa6bd308 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 02:19:40 +0000 Subject: [PATCH 82/88] Remove duplicates packages and updating. --- Terminal.Gui/Terminal.Gui.csproj | 6 ------ UnitTests/UnitTests.csproj | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index b9d912425..8a39d1591 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -60,12 +60,6 @@ Strings.Designer.cs - - - - - - net472;netstandard2.0;net6.0 9 diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index bd8677ca0..1d5885e17 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -22,7 +22,7 @@ - + From e66c3a0352c0faab5f711cc7a4753cf95216dc7a Mon Sep 17 00:00:00 2001 From: BDisp Date: Sat, 4 Mar 2023 16:08:28 +0000 Subject: [PATCH 83/88] Fixes configuration unit test fails. --- Terminal.Gui/Configuration/Scope.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Terminal.Gui/Configuration/Scope.cs b/Terminal.Gui/Configuration/Scope.cs index 7e8aceb79..9430b19d1 100644 --- a/Terminal.Gui/Configuration/Scope.cs +++ b/Terminal.Gui/Configuration/Scope.cs @@ -131,7 +131,11 @@ namespace Terminal.Gui.Configuration { var readHelper = Activator.CreateInstance ((Type?)typeof (ReadHelper<>).MakeGenericType (typeof (scopeT), propertyType!)!, converter) as ReadHelper; scope! [propertyName].PropertyValue = readHelper?.Read (ref reader, propertyType!, options); } else { - scope! [propertyName].PropertyValue = JsonSerializer.Deserialize (ref reader, propertyType!, options); + try { + scope! [propertyName].PropertyValue = JsonSerializer.Deserialize (ref reader, propertyType!, options); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine ($"scopeT Read: {ex}"); + } } } else { // It is not a config property. Maybe it's just a property on the Scope with [JsonInclude] From 4d7e23c77e451534ef36999a674bed492c8af1c7 Mon Sep 17 00:00:00 2001 From: Tigger Kindel Date: Sun, 5 Mar 2023 07:53:49 -0700 Subject: [PATCH 84/88] Fixed merge conflicts - readded DimTests.cs --- UnitTests/Types/DimTests.cs | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/UnitTests/Types/DimTests.cs b/UnitTests/Types/DimTests.cs index 0c659e5a8..e04a4b818 100644 --- a/UnitTests/Types/DimTests.cs +++ b/UnitTests/Types/DimTests.cs @@ -505,30 +505,6 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (19, v3.Frame.Width); // 198*10%=19 * Percent is related to the super-view if it isn't null otherwise the view width Assert.Equal (19, v3.Frame.Height); // 199*10%=19 - f2.Text = "Frame2"; - Assert.Equal ("Fill(0)", f2.Width.ToString ()); - Assert.Equal ("Absolute(5)", f2.Height.ToString ()); - Assert.Equal (49, f2.Frame.Width); // f2.X = Pos.Right(f1), thus 50-1=49 - Assert.Equal (5, f2.Frame.Height); - - v1.Text = "Button1"; - Assert.Equal ("Combine(DimView(Width,FrameView()({X=0,Y=0,Width=49,Height=5}))-Absolute(2))", v1.Width.ToString ()); - Assert.Equal ("Combine(Fill(0)-Absolute(2))", v1.Height.ToString ()); - Assert.Equal (47, v1.Frame.Width); // 49-2=47 - Assert.Equal (89, v1.Frame.Height); // 98-2-7=89 - - v2.Text = "Button2"; - Assert.Equal ("Combine(DimView(Width,FrameView()({X=49,Y=0,Width=49,Height=5}))-Absolute(2))", v2.Width.ToString ()); - Assert.Equal ("Combine(Fill(0)-Absolute(2))", v2.Height.ToString ()); - Assert.Equal (47, v2.Frame.Width); // 49-2=47 - Assert.Equal (89, v2.Frame.Height); // 98-2-7=89 - - v3.Text = "Button3"; - Assert.Equal ("Factor(0.1,False)", v3.Width.ToString ()); - Assert.Equal ("Factor(0.1,False)", v3.Height.ToString ()); - Assert.Equal (9, v3.Frame.Width); // 98*10%=9 * Percent is related to the super-view if it isn't null otherwise the view width - Assert.Equal (9, v3.Frame.Height); // 99*10%=9 - v4.Text = "Button4"; v4.AutoSize = false; Assert.Equal ("Absolute(50)", v4.Width.ToString ()); @@ -542,16 +518,16 @@ namespace Terminal.Gui.TypeTests { Assert.Equal (1, v4.Frame.Height); // 1 because is Dim.DimAbsolute v5.Text = "Button5"; - Assert.Equal ("Combine(DimView(Width,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Width,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Width.ToString ()); - Assert.Equal ("Combine(DimView(Height,Button()({X=2,Y=7,Width=47,Height=89}))-DimView(Height,Button()({X=0,Y=0,Width=9,Height=9})))", v5.Height.ToString ()); - Assert.Equal (38, v5.Frame.Width); // 47-9=38 - Assert.Equal (80, v5.Frame.Height); // 89-9=80 + Assert.Equal ("Combine(View(Width,Button()({X=2,Y=7,Width=97,Height=189}))-View(Width,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Width.ToString ()); + Assert.Equal ("Combine(View(Height,Button()({X=2,Y=7,Width=97,Height=189}))-View(Height,Button()({X=0,Y=0,Width=19,Height=19})))", v5.Height.ToString ()); + Assert.Equal (78, v5.Frame.Width); // 97-9=78 + Assert.Equal (170, v5.Frame.Height); // 189-19=170 v6.Text = "Button6"; Assert.Equal ("Factor(0.2,True)", v6.Width.ToString ()); Assert.Equal ("Factor(0.2,True)", v6.Height.ToString ()); - Assert.Equal (9, v6.Frame.Width); // 49*20%=9 - Assert.Equal (18, v6.Frame.Height); // 98-7*20=18 + Assert.Equal (19, v6.Frame.Width); // 99*20%=19 + Assert.Equal (38, v6.Frame.Height); // 198-7*20=18 }; Application.Iteration += () => Application.RequestStop (); From d59bc80ca4c697577436e3e3e6f442b3f8c209e8 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 5 Mar 2023 18:30:56 +0000 Subject: [PATCH 85/88] Undoing the changes because is causing continuous run loop. --- Terminal.Gui/Core/Toplevel.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs index 022addccc..08952f48b 100644 --- a/Terminal.Gui/Core/Toplevel.cs +++ b/Terminal.Gui/Core/Toplevel.cs @@ -749,23 +749,11 @@ namespace Terminal.Gui { if (view.Frame.IntersectsWith (bounds) && !OutsideTopFrame (this)) { view.SetNeedsLayout (); view.SetNeedsDisplay (view.Bounds); - if (SuperView == null && view.Visible && view.Frame.Width > 0 && view.Frame.Height > 0) { - view.OnDrawContent (view.Bounds); - view.Redraw (view.Bounds); - view.OnDrawContentComplete (view.Bounds); - } } } - - if (SuperView != null) { - ClearLayoutNeeded (); - ClearNeedsDisplay (); - } } - if (SuperView != null) { - base.Redraw (Bounds); - } + base.Redraw (Bounds); } bool OutsideTopFrame (Toplevel top) From f1e4e21456cbae60581e9205b3cac7cd212b956b Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 5 Mar 2023 18:32:14 +0000 Subject: [PATCH 86/88] Removing and refactoring code. --- Terminal.Gui/Core/View.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 04c3dc9ad..eb8907c3d 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -808,7 +808,6 @@ namespace Terminal.Gui { { var actX = x is Pos.PosAbsolute ? x.Anchor (0) : frame.X; var actY = y is Pos.PosAbsolute ? y.Anchor (0) : frame.Y; - Rect oldFrame = frame; if (AutoSize) { var s = GetAutoSize (); @@ -1359,10 +1358,10 @@ namespace Terminal.Gui { public virtual void OnAdded (View view) { view.IsAdded = true; - view.x = view.x ?? view.frame.X; - view.y = view.y ?? view.frame.Y; - view.width = view.width ?? view.frame.Width; - view.height = view.height ?? view.frame.Height; + view.x ??= view.frame.X; + view.y ??= view.frame.Y; + view.width ??= view.frame.Width; + view.height ??= view.frame.Height; view.Added?.Invoke (this); } From 2eb05113af34a565bafa2b517d9bb07c53dad2fc Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 5 Mar 2023 18:34:58 +0000 Subject: [PATCH 87/88] Fix negative bounds on draw text and thus fixes scrolling. --- Terminal.Gui/Core/TextFormatter.cs | 29 ++-- Terminal.Gui/Core/View.cs | 18 +-- UnitTests/Core/LayoutTests.cs | 17 ++- UnitTests/Text/TextFormatterTests.cs | 190 ++++++++++++++++++++++++++- 4 files changed, 228 insertions(+), 26 deletions(-) diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index e6e1592e3..5d71066e4 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -1176,22 +1176,29 @@ namespace Terminal.Gui { } var isVertical = IsVerticalDirection (textDirection); - var savedClip = Application.Driver?.Clip; var maxBounds = bounds; if (Application.Driver != null) { - Application.Driver.Clip = maxBounds = containerBounds == default + maxBounds = containerBounds == default ? bounds : new Rect (Math.Max (containerBounds.X, bounds.X), Math.Max (containerBounds.Y, bounds.Y), Math.Max (Math.Min (containerBounds.Width, containerBounds.Right - bounds.Left), 0), Math.Max (Math.Min (containerBounds.Height, containerBounds.Bottom - bounds.Top), 0)); } + if (maxBounds.Width == 0 || maxBounds.Height == 0) { + return; + } + var savedClip = Application.Driver?.Clip; + if (Application.Driver != null) { + Application.Driver.Clip = maxBounds; + } + var lineOffset = !isVertical && bounds.Y < 0 ? Math.Abs (bounds.Y) : 0; - for (int line = 0; line < linesFormated.Count; line++) { + for (int line = lineOffset; line < linesFormated.Count; line++) { if ((isVertical && line > bounds.Width) || (!isVertical && line > bounds.Height)) continue; if ((isVertical && line >= maxBounds.Left + maxBounds.Width) - || (!isVertical && line >= maxBounds.Top + maxBounds.Height)) + || (!isVertical && line >= maxBounds.Top + maxBounds.Height + lineOffset)) break; @@ -1267,18 +1274,21 @@ namespace Terminal.Gui { throw new ArgumentOutOfRangeException (); } + var colOffset = bounds.X < 0 ? Math.Abs (bounds.X) : 0; var start = isVertical ? bounds.Top : bounds.Left; var size = isVertical ? bounds.Height : bounds.Width; - var current = start; + var current = start + colOffset; - for (var idx = (isVertical ? start - y : start - x); current < start + size; idx++) { - if (!fillRemaining && idx < 0) { + for (var idx = (isVertical ? start - y : start - x) + colOffset; current < start + size; idx++) { + if (idx < 0 || x + current + colOffset < 0) { current++; continue; } else if (!fillRemaining && idx > runes.Length - 1) { break; } - if ((!isVertical && idx > maxBounds.Left + maxBounds.Width - bounds.X) || (isVertical && idx > maxBounds.Top + maxBounds.Height - bounds.Y)) + if ((!isVertical && idx > maxBounds.Left + maxBounds.Width - bounds.X + colOffset) + || (isVertical && idx > maxBounds.Top + maxBounds.Height - bounds.Y)) + break; var rune = (Rune)' '; @@ -1316,8 +1326,9 @@ namespace Terminal.Gui { } } } - if (Application.Driver != null) + if (Application.Driver != null) { Application.Driver.Clip = (Rect)savedClip; + } } } } diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index eb8907c3d..91755ff40 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1511,15 +1511,17 @@ namespace Terminal.Gui { if (!ustring.IsNullOrEmpty (TextFormatter.Text)) { Rect containerBounds = GetContainerBounds (); - Clear (GetNeedDisplay (containerBounds)); - SetChildNeedsDisplay (); - // Draw any Text - if (TextFormatter != null) { - TextFormatter.NeedsFormat = true; + if (!containerBounds.IsEmpty) { + Clear (GetNeedDisplay (containerBounds)); + SetChildNeedsDisplay (); + // Draw any Text + if (TextFormatter != null) { + TextFormatter.NeedsFormat = true; + } + TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (), + HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (), + containerBounds); } - TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (), - HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (), - containerBounds); } // Invoke DrawContentEvent diff --git a/UnitTests/Core/LayoutTests.cs b/UnitTests/Core/LayoutTests.cs index 8e5489cd9..68ea9577f 100644 --- a/UnitTests/Core/LayoutTests.cs +++ b/UnitTests/Core/LayoutTests.cs @@ -328,14 +328,17 @@ namespace Terminal.Gui.CoreTests { Application.Begin (Application.Top); Assert.True (label.AutoSize); + // Here the AutoSize ensuring the right size with width 28 (Dim.Fill) + // and height 0 because wasn't set and the text is empty Assert.Equal ("{X=0,Y=0,Width=28,Height=0}", label.Bounds.ToString ()); label.Text = "First line\nSecond line"; Application.Refresh (); - // Here the AutoSize ensuring the right size + // Here the AutoSize ensuring the right size with width 28 (Dim.Fill) + // and height 2 because wasn't set and the text has 2 lines Assert.True (label.AutoSize); - Assert.Equal ("{X=0,Y=0,Width=11,Height=2}", label.Bounds.ToString ()); + Assert.Equal ("{X=0,Y=0,Width=28,Height=2}", label.Bounds.ToString ()); label.AutoSize = false; Application.Refresh (); @@ -347,12 +350,16 @@ namespace Terminal.Gui.CoreTests { label.Text = "First changed line\nSecond changed line\nNew line"; Application.Refresh (); + // Here the AutoSize is false and the width 28 (Dim.Fill) and + // height 1 because wasn't set and SetMinWidthHeight ensuring the minimum height Assert.False (label.AutoSize); Assert.Equal ("{X=0,Y=0,Width=28,Height=1}", label.Bounds.ToString ()); label.AutoSize = true; Application.Refresh (); + // Here the AutoSize ensuring the right size with width 28 (Dim.Fill) + // and height 3 because wasn't set and the text has 3 lines Assert.True (label.AutoSize); Assert.Equal ("{X=0,Y=0,Width=28,Height=3}", label.Bounds.ToString ()); } @@ -461,9 +468,13 @@ Y Assert.Equal ("123 ", GetContents ()); lbl.Text = "12"; + // Here the AutoSize ensuring the right size with width 3 (Dim.Absolute) + // that was set on the OnAdded method with the text length of 3 + // and height 1 because wasn't set and the text has 1 line Assert.Equal (new Rect (0, 0, 3, 1), lbl.Frame); Assert.Equal (new Rect (0, 0, 3, 1), lbl.NeedDisplay); - Assert.Equal (new Rect (0, 0, 80, 25), lbl.SuperView.NeedDisplay); + Assert.Equal (new Rect (0, 0, 0, 0), lbl.SuperView.NeedDisplay); + Assert.True (lbl.SuperView.LayoutNeeded); lbl.SuperView.Redraw (lbl.SuperView.Bounds); Assert.Equal ("12 ", GetContents ()); diff --git a/UnitTests/Text/TextFormatterTests.cs b/UnitTests/Text/TextFormatterTests.cs index a791a6ffb..142035b21 100644 --- a/UnitTests/Text/TextFormatterTests.cs +++ b/UnitTests/Text/TextFormatterTests.cs @@ -2162,7 +2162,7 @@ namespace Terminal.Gui.TextTests { var height = 8; var wrappedLines = TextFormatter.WordWrap (text, width, true); var breakLines = ""; - foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}"; + foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}"; var label = new Label (breakLines) { Width = Dim.Fill (), Height = Dim.Fill () }; var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () }; @@ -2200,7 +2200,7 @@ namespace Terminal.Gui.TextTests { var height = 3; var wrappedLines = TextFormatter.WordWrap (text, height, true); var breakLines = ""; - for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}"; + for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}"; var label = new Label (breakLines) { TextDirection = TextDirection.TopBottom_LeftRight, Width = Dim.Fill (), @@ -2237,7 +2237,7 @@ namespace Terminal.Gui.TextTests { var height = 8; var wrappedLines = TextFormatter.WordWrap (text, width, true); var breakLines = ""; - foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}"; + foreach (var line in wrappedLines) breakLines += $"{line}{Environment.NewLine}"; var label = new Label (breakLines) { Width = Dim.Fill (), Height = Dim.Fill () }; var frame = new FrameView () { Width = Dim.Fill (), Height = Dim.Fill () }; @@ -2276,7 +2276,7 @@ namespace Terminal.Gui.TextTests { var height = 4; var wrappedLines = TextFormatter.WordWrap (text, width, true); var breakLines = ""; - for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}"; + for (int i = 0; i < wrappedLines.Count; i++) breakLines += $"{wrappedLines [i]}{(i < wrappedLines.Count - 1 ? Environment.NewLine : string.Empty)}"; var label = new Label (breakLines) { TextDirection = TextDirection.TopBottom_LeftRight, Width = Dim.Fill (), @@ -2888,7 +2888,7 @@ namespace Terminal.Gui.TextTests { Assert.Equal ("nd", list1 [10].ToString ()); Assert.Equal ("Line", list1 [11].ToString ()); Assert.Equal ("- 2.", list1 [^1].ToString ()); - foreach (var txt in list1) wrappedText1 += txt; + foreach (var txt in list1) wrappedText1 += txt; Assert.Equal (" Asentencehaswords. This isthesecondLine- 2.", wrappedText1); // With preserveTrailingSpaces = true. @@ -2910,7 +2910,7 @@ namespace Terminal.Gui.TextTests { Assert.Equal ("Line", list2 [13].ToString ()); Assert.Equal (" - ", list2 [14].ToString ()); Assert.Equal ("2. ", list2 [^1].ToString ()); - foreach (var txt in list2) wrappedText2 += txt; + foreach (var txt in list2) wrappedText2 += txt; Assert.Equal (" A sentence has words. This is the second Line - 2. ", wrappedText2); } @@ -4288,5 +4288,183 @@ t ", output); 0 0", new Attribute [] { Colors.Base.Normal }); } + + [Fact, AutoInitShutdown] + public void Draw_Negative_Bounds_Horizontal_Without_New_Lines () + { + var subView = new View () { Id = "subView", Y = 1, Width = 7, Text = "subView" }; + var view = new View () { Id = "view", Width = 20, Height = 2, Text = "01234567890123456789" }; + view.Add (subView); + var content = new View () { Id = "content", Width = 20, Height = 20 }; + content.Add (view); + var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 }; + container.Add (content); + var top = Application.Top; + top.Add (container); + Application.Driver.Clip = container.Frame; + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" + 01234 + subVi", output); + + content.X = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 12345 + ubVie", output); + + content.Y = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + ubVie", output); + + content.Y = -2; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + + content.X = -20; + content.Y = 0; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + } + + [Fact, AutoInitShutdown] + public void Draw_Negative_Bounds_Horizontal_With_New_Lines () + { + var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "s\nu\nb\nV\ni\ne\nw" }; + var view = new View () { Id = "view", Width = 2, Height = 20, Text = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9" }; + view.Add (subView); + var content = new View () { Id = "content", Width = 20, Height = 20 }; + content.Add (view); + var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 }; + container.Add (content); + var top = Application.Top; + top.Add (container); + Application.Driver.Clip = container.Frame; + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" + 0s + 1u + 2b + 3V + 4i", output); + + content.X = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + s + u + b + V + i", output); + + content.X = -2; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@"", output); + + content.X = 0; + content.Y = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 1u + 2b + 3V + 4i + 5e", output); + + content.Y = -6; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 6w + 7 + 8 + 9 + 0 ", output); + + content.Y = -19; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 9", output); + + content.Y = -20; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + + content.X = -2; + content.Y = 0; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + } + + [Fact, AutoInitShutdown] + public void Draw_Negative_Bounds_Vertical () + { + var subView = new View () { Id = "subView", X = 1, Width = 1, Height = 7, Text = "subView", TextDirection = TextDirection.TopBottom_LeftRight }; + var view = new View () { Id = "view", Width = 2, Height = 20, Text = "01234567890123456789", TextDirection = TextDirection.TopBottom_LeftRight }; + view.Add (subView); + var content = new View () { Id = "content", Width = 20, Height = 20 }; + content.Add (view); + var container = new View () { Id = "container", X = 1, Y = 1, Width = 5, Height = 5 }; + container.Add (content); + var top = Application.Top; + top.Add (container); + Application.Driver.Clip = container.Frame; + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" + 0s + 1u + 2b + 3V + 4i", output); + + content.X = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + s + u + b + V + i", output); + + content.X = -2; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@"", output); + + content.X = 0; + content.Y = -1; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 1u + 2b + 3V + 4i + 5e", output); + + content.Y = -6; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 6w + 7 + 8 + 9 + 0 ", output); + + content.Y = -19; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" + 9", output); + + content.Y = -20; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + + content.X = -2; + content.Y = 0; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre ("", output); + } } } \ No newline at end of file From 5ec653af2cc951d0cf02949ef46dd447e264fbb9 Mon Sep 17 00:00:00 2001 From: BDisp Date: Sun, 5 Mar 2023 19:29:05 +0000 Subject: [PATCH 88/88] Fix a dereference of a possibly null reference. --- Terminal.Gui/Configuration/Scope.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/Configuration/Scope.cs b/Terminal.Gui/Configuration/Scope.cs index 12eacf924..da4e5c43f 100644 --- a/Terminal.Gui/Configuration/Scope.cs +++ b/Terminal.Gui/Configuration/Scope.cs @@ -132,7 +132,7 @@ namespace Terminal.Gui.Configuration { try { scope! [propertyName].PropertyValue = readHelper?.Read (ref reader, propertyType!, options); } catch (NotSupportedException e) { - throw new JsonException ($"Error reading property \"{propertyName}\" of type \"{propertyType.Name}\".", e); + throw new JsonException ($"Error reading property \"{propertyName}\" of type \"{propertyType?.Name}\".", e); } } else { try {