diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
index 7c4c8ff44..ff5bfe4a9 100644
--- a/.github/workflows/dotnet-core.yml
+++ b/.github/workflows/dotnet-core.yml
@@ -2,9 +2,9 @@ name: Build & Test Terminal.Gui with .NET Core
on:
push:
- branches: [ main, develop ]
+ branches: [ main, develop, v2_develop ]
pull_request:
- branches: [ main, develop ]
+ branches: [ main, develop, v2_develop ]
jobs:
build:
diff --git a/Example/Example.csproj b/Example/Example.csproj
index 69d7bd305..845bf6d6a 100644
--- a/Example/Example.csproj
+++ b/Example/Example.csproj
@@ -5,10 +5,10 @@
- 1.0
- 1.0
- 1.0
- 1.0
+ 2.0
+ 2.0
+ 2.0
+ 2.0
diff --git a/README.md b/README.md
index 636aa542b..1fb484212 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,12 @@
[](LICENSE)

-# Terminal.Gui - Cross Platform Terminal UI toolkit for .NET
+# Terminal.Gui v2.x - Cross Platform Terminal UI toolkit for .NET
A toolkit for building rich console apps for .NET, .NET Core, and Mono that works on Windows, the Mac, and Linux/Unix.
+NOTE: This is the WORK IN PROGRESS `v2.x` branch. The `main` branch is the stable `v1.x` branch.
+

## Quick Start
diff --git a/ReactiveExample/ReactiveExample.csproj b/ReactiveExample/ReactiveExample.csproj
index 736cd84a0..6d2346f8f 100644
--- a/ReactiveExample/ReactiveExample.csproj
+++ b/ReactiveExample/ReactiveExample.csproj
@@ -5,14 +5,14 @@
- 1.0
- 1.0
- 1.0
- 1.0
+ 2.0
+ 2.0
+ 2.0
+ 2.0
-
-
+
+
diff --git a/Terminal.Gui/Configuration/ConfigurationManager.cs b/Terminal.Gui/Configuration/ConfigurationManager.cs
index 85e5c440f..fac2fa85b 100644
--- a/Terminal.Gui/Configuration/ConfigurationManager.cs
+++ b/Terminal.Gui/Configuration/ConfigurationManager.cs
@@ -44,7 +44,7 @@ namespace Terminal.Gui.Configuration {
/// 3. Application configuration found in the applications's resources (Resources/config.json).
///
///
- /// 4. Global configuration found in the the user's home directory (~/.tui/config.json).
+ /// 4. Global configuration found in the user's home directory (~/.tui/config.json).
///
///
/// 5. Global configuration found in the directory the app was launched from (./.tui/config.json).
@@ -63,7 +63,7 @@ namespace Terminal.Gui.Configuration {
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true,
Converters = {
- // No need to set converterss - the ConfigRootConverter uses property attributes apply the correct
+ // No need to set converters - the ConfigRootConverter uses property attributes apply the correct
// Converter.
},
};
@@ -196,7 +196,7 @@ namespace Terminal.Gui.Configuration {
///
///
/// Is until is called. Gets set to a new instance by
- /// deserializtion (see ).
+ /// deserialization (see ).
///
private static SettingsScope? _settings;
@@ -223,14 +223,14 @@ namespace Terminal.Gui.Configuration {
public static ThemeManager? Themes => ThemeManager.Instance;
///
- /// Aplication-specific configuration settings scope.
+ /// Application-specific configuration settings scope.
///
[SerializableConfigurationProperty (Scope = typeof (SettingsScope), OmitClassName = true), JsonPropertyName ("AppSettings")]
public static AppScope? AppSettings { get; set; }
///
- /// Initializes the internal state of ConfiguraitonManager. Nominally called once as part of application
- /// startup to initilaize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
+ /// Initializes the internal state of ConfigurationManager. Nominally called once as part of application
+ /// startup to initialize global state. Also called from some Unit Tests to ensure correctness (e.g. Reset()).
///
internal static void Initialize ()
{
@@ -260,7 +260,7 @@ namespace Terminal.Gui.Configuration {
select p) {
if (p.GetCustomAttribute (typeof (SerializableConfigurationProperty)) is SerializableConfigurationProperty scp) {
if (p.GetGetMethod (true)!.IsStatic) {
- // If the class name is ommited, JsonPropertyName is allowed.
+ // If the class name is omitted, JsonPropertyName is allowed.
_allConfigProperties!.Add (scp.OmitClassName ? ConfigProperty.GetJsonPropertyName (p) : $"{p.DeclaringType?.Name}.{p.Name}", new ConfigProperty {
PropertyInfo = p,
PropertyValue = null
@@ -357,7 +357,7 @@ namespace Terminal.Gui.Configuration {
}
///
- /// Event fired when the configuration has been upddated from a configuration source.
+ /// Event fired when the configuration has been updated from a configuration source.
/// application.
///
public static event Action? Updated;
@@ -378,7 +378,7 @@ namespace Terminal.Gui.Configuration {
}
ClearJsonErrors ();
-
+
Settings = new SettingsScope ();
ThemeManager.Reset ();
AppSettings = new AppScope ();
@@ -402,7 +402,7 @@ namespace Terminal.Gui.Configuration {
/// to generate the JSON doc that is embedded into Terminal.Gui (during development).
///
///
- /// WARNING: The Terminal.Gui.Resources.config.json resource has setting defintions (Themes)
+ /// WARNING: The Terminal.Gui.Resources.config.json resource has setting definitions (Themes)
/// that are NOT generated by this function. If you use this function to regenerate Terminal.Gui.Resources.config.json,
/// make sure you copy the Theme definitions from the existing Terminal.Gui.Resources.config.json file.
///
@@ -455,7 +455,7 @@ namespace Terminal.Gui.Configuration {
public static string AppName { get; set; } = Assembly.GetEntryAssembly ()?.FullName?.Split (',') [0]?.Trim ()!;
///
- /// Describes the location of the configuration files. The constancts can be
+ /// Describes the location of the configuration files. The constants can be
/// combined (bitwise) to specify multiple locations.
///
[Flags]
@@ -488,27 +488,26 @@ namespace Terminal.Gui.Configuration {
public static ConfigLocations Locations { get; set; } = ConfigLocations.All;
///
- /// Loads all settings found in the various configuraiton storage locations to
+ /// Loads all settings found in the various configuration storage locations to
/// the . Optionally,
- /// resets all settings attributed with to the defaults
- /// defined in .
+ /// resets all settings attributed with to the defaults.
///
///
/// Use to cause the loaded settings to be applied to the running application.
///
/// If the state of will
- /// be reset to the defaults defined in .
+ /// be reset to the defaults.
public static void Load (bool reset = false)
{
Debug.WriteLine ($"ConfigurationManager.Load()");
if (reset) Reset ();
- // LibraryResoruces is always loaded by Reset
+ // LibraryResources is always loaded by Reset
if (Locations == ConfigLocations.All) {
var embeddedStylesResourceName = Assembly.GetEntryAssembly ()?
.GetManifestResourceNames ().FirstOrDefault (x => x.EndsWith (_configFilename));
- if (string.IsNullOrEmpty(embeddedStylesResourceName)) {
+ if (string.IsNullOrEmpty (embeddedStylesResourceName)) {
embeddedStylesResourceName = _configFilename;
}
diff --git a/Terminal.Gui/Configuration/Scope.cs b/Terminal.Gui/Configuration/Scope.cs
index 7e8aceb79..da4e5c43f 100644
--- a/Terminal.Gui/Configuration/Scope.cs
+++ b/Terminal.Gui/Configuration/Scope.cs
@@ -129,9 +129,17 @@ 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);
+ 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]
diff --git a/Terminal.Gui/Configuration/SettingsScope.cs b/Terminal.Gui/Configuration/SettingsScope.cs
index f66a2bc4b..0c36af658 100644
--- a/Terminal.Gui/Configuration/SettingsScope.cs
+++ b/Terminal.Gui/Configuration/SettingsScope.cs
@@ -34,6 +34,9 @@ namespace Terminal.Gui.Configuration {
[JsonInclude, JsonPropertyName ("$schema")]
public string Schema { get; set; } = "https://gui-cs.github.io/Terminal.Gui/schemas/tui-config-schema.json";
+ ///
+ /// The list of paths to the configuration files.
+ ///
public List Sources = new List ();
///
diff --git a/Terminal.Gui/Configuration/ThemeScope.cs b/Terminal.Gui/Configuration/ThemeScope.cs
index aab8e0068..22da7e4f2 100644
--- a/Terminal.Gui/Configuration/ThemeScope.cs
+++ b/Terminal.Gui/Configuration/ThemeScope.cs
@@ -120,21 +120,21 @@ namespace Terminal.Gui.Configuration {
///
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/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index ec2220519..7a7b09402 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,7 @@ 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; }
public override IClipboard Clipboard { get => clipboard; }
CursorVisibility? initialCursorVisibility = null;
@@ -116,7 +113,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 +155,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 +305,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 +338,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 +385,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 +397,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 +458,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 +530,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 +582,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 +632,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 +752,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 +809,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 +873,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 +967,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 +977,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 3d6624ecb..1fb3580fb 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..30951dd73 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,7 @@ namespace Terminal.Gui {
// Only handling left here because not all terminals has a horizontal scroll bar.
public override int Left => 0;
public override int Top => 0;
- public override bool HeightAsBuffer { get; set; }
+ public override bool EnableConsoleScrolling { get; set; }
private IClipboard clipboard = null;
public override IClipboard Clipboard => clipboard;
@@ -245,8 +242,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 +532,7 @@ namespace Terminal.Gui {
FakeConsole.SetBufferSize (width, height);
cols = width;
rows = height;
- if (!HeightAsBuffer) {
+ if (!EnableConsoleScrolling) {
SetWindowSize (width, height);
}
ProcessResize ();
@@ -544,7 +541,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 +553,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 +572,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 +626,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..08e827683 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,13 @@ 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; }
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 +635,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 +715,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 +724,6 @@ namespace Terminal.Gui {
ccol++;
}
- //if (ccol == Cols) {
- // ccol = 0;
- // if (crow + 1 < Rows)
- // crow++;
- //}
if (sync) {
UpdateScreen ();
}
@@ -1310,25 +737,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 +774,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 +801,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 +892,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 +946,7 @@ namespace Terminal.Gui {
var attr = contents [row, col, 1];
if (attr != redrawAttr) {
+ redrawAttr = attr;
output.Append (WriteAttributes (attr));
}
outputWidth++;
@@ -1515,18 +961,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 +980,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 +1035,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 +1263,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 +1272,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 +1308,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 +1369,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 +1480,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 +1532,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..5de19fa85 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,7 @@ 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; }
public override IClipboard Clipboard => clipboard;
public override int [,,] Contents => contents;
@@ -774,7 +750,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 +891,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 +1439,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 +1460,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 +1481,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 +1656,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 +1703,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 +1795,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 +1912,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 9fb6ecbc9..a646cbddb 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -114,27 +114,39 @@ 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.
///
- ///
- [SerializableConfigurationProperty (Scope = typeof(SettingsScope))]
- 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.
+ ///
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+ 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;
}
}
@@ -143,7 +155,7 @@ namespace Terminal.Gui {
///
/// Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.
///
- [SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter(typeof(KeyJsonConverter))]
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
public static Key AlternateForwardKey {
get => alternateForwardKey;
set {
@@ -157,7 +169,7 @@ namespace Terminal.Gui {
static void OnAlternateForwardKeyChanged (Key oldKey)
{
- foreach (var top in toplevels.ToArray()) {
+ foreach (var top in toplevels.ToArray ()) {
top.OnAlternateForwardKeyChanged (oldKey);
}
}
@@ -167,7 +179,7 @@ namespace Terminal.Gui {
///
/// Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.
///
- [SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
public static Key AlternateBackwardKey {
get => alternateBackwardKey;
set {
@@ -181,7 +193,7 @@ namespace Terminal.Gui {
static void OnAlternateBackwardKeyChanged (Key oldKey)
{
- foreach (var top in toplevels.ToArray()) {
+ foreach (var top in toplevels.ToArray ()) {
top.OnAlternateBackwardKeyChanged (oldKey);
}
}
@@ -191,7 +203,7 @@ namespace Terminal.Gui {
///
/// Gets or sets the key to quit the application.
///
- [SerializableConfigurationProperty (Scope = typeof(SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
+ [SerializableConfigurationProperty (Scope = typeof (SettingsScope)), JsonConverter (typeof (KeyJsonConverter))]
public static Key QuitKey {
get => quitKey;
set {
@@ -213,7 +225,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);
}
}
@@ -445,7 +457,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.
@@ -1121,6 +1133,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/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;
}
diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs
index aa25bd41d..20e3aceed 100644
--- a/Terminal.Gui/Core/Border.cs
+++ b/Terminal.Gui/Core/Border.cs
@@ -513,6 +513,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.
@@ -628,7 +629,47 @@ namespace Terminal.Gui {
///// Gets or sets the single child element of a .
/////
//[JsonIgnore]
- //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.
@@ -791,7 +832,7 @@ namespace Terminal.Gui {
// Child.Clear (borderRect);
// }
- // driver.SetAttribute (savedAttribute);
+ // driver.SetAttribute (new Attribute (BorderBrush, Background));
// // Draw margin frame
// if (DrawMarginFrame) {
@@ -815,6 +856,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)
@@ -829,35 +871,47 @@ namespace Terminal.Gui {
// driver.SetAttribute (new Attribute (BorderBrush));
- // // Draw the upper BorderThickness
+ // Draw the upper BorderThickness
// for (int r = frame.Y - drawMarginFrame - sumThickness.Top;
// r < frame.Y - drawMarginFrame - padding.Top; r++) {
+
+ // if (r < 0) {
+ // continue;
+ // }
// for (int c = frame.X - drawMarginFrame - sumThickness.Left;
// c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the left BorderThickness
// for (int r = frame.Y - drawMarginFrame - padding.Top;
// r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+
+ // if (r < 0) {
+ // continue;
+ // }
// for (int c = frame.X - drawMarginFrame - sumThickness.Left;
// c < frame.X - drawMarginFrame - padding.Left; c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the right BorderThickness
// for (int r = frame.Y - drawMarginFrame - padding.Top;
// r < Math.Min (frame.Bottom + drawMarginFrame + padding.Bottom, driver.Rows); r++) {
+
+ // if (r < 0) {
+ // continue;
+ // }
// for (int c = frame.Right + drawMarginFrame + padding.Right;
// c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the lower BorderThickness
// for (int r = frame.Bottom + drawMarginFrame + padding.Bottom;
@@ -865,21 +919,25 @@ namespace Terminal.Gui {
// for (int c = frame.X - drawMarginFrame - sumThickness.Left;
// c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
- // driver.SetAttribute (new Attribute (Background));
+ //// driver.SetAttribute (new Attribute (Background));
// // Draw the upper Padding
// for (int r = frame.Y - drawMarginFrame - padding.Top;
// r < frame.Y - drawMarginFrame; r++) {
+
+ // if (r < 0) {
+ // continue;
+ // }
// for (int c = frame.X - drawMarginFrame - padding.Left;
// c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the left Padding
// for (int r = frame.Y - drawMarginFrame;
@@ -887,9 +945,9 @@ namespace Terminal.Gui {
// for (int c = frame.X - drawMarginFrame - padding.Left;
// c < frame.X - drawMarginFrame; c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the right Padding
// for (int r = frame.Y - drawMarginFrame;
@@ -897,9 +955,9 @@ namespace Terminal.Gui {
// for (int c = frame.Right + drawMarginFrame;
// c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
// // Draw the lower Padding
// for (int r = frame.Bottom + drawMarginFrame;
@@ -907,11 +965,11 @@ namespace Terminal.Gui {
// for (int c = frame.X - drawMarginFrame - padding.Left;
// c < Math.Min (frame.Right + drawMarginFrame + padding.Right, driver.Cols); c++) {
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
+ //// AddRuneAt (driver, c, r, ' ');
+ //// }
+ //// }
- // driver.SetAttribute (savedAttribute);
+ // driver.SetAttribute (new Attribute (BorderBrush, Background));
// // Draw the MarginFrame
// if (DrawMarginFrame) {
@@ -1003,148 +1061,7 @@ namespace Terminal.Gui {
// driver.SetAttribute (new Attribute (BorderBrush));
- // // Draw the upper BorderThickness
- // for (int r = frame.Y;
- // r < Math.Min (frame.Y + borderThickness.Top, frame.Bottom); r++) {
- // for (int c = frame.X;
- // c < Math.Min (frame.Right, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the left BorderThickness
- // for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
- // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
- // for (int c = frame.X;
- // c < Math.Min (frame.X + borderThickness.Left, frame.Right); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the right BorderThickness
- // for (int r = Math.Min (frame.Y + borderThickness.Top, frame.Bottom);
- // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
- // for (int c = Math.Max (frame.Right - borderThickness.Right, frame.X);
- // c < Math.Min (frame.Right, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the lower BorderThickness
- // for (int r = Math.Max (frame.Bottom - borderThickness.Bottom, frame.Y);
- // r < Math.Min (frame.Bottom, driver.Rows); r++) {
- // for (int c = frame.X;
- // c < Math.Min (frame.Right, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // driver.SetAttribute (new Attribute (Background));
-
- // // Draw the upper Padding
- // for (int r = frame.Y + borderThickness.Top;
- // r < Math.Min (frame.Y + sumThickness.Top, frame.Bottom - borderThickness.Bottom); r++) {
- // for (int c = frame.X + borderThickness.Left;
- // c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the left Padding
- // for (int r = frame.Y + sumThickness.Top;
- // r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
- // for (int c = frame.X + borderThickness.Left;
- // c < Math.Min (frame.X + sumThickness.Left, frame.Right - borderThickness.Right); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the right Padding
- // for (int r = frame.Y + sumThickness.Top;
- // r < Math.Min (frame.Bottom - sumThickness.Bottom, driver.Rows); r++) {
- // for (int c = Math.Max (frame.Right - sumThickness.Right, frame.X + sumThickness.Left);
- // c < Math.Max (frame.Right - borderThickness.Right, frame.X + sumThickness.Left); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // // Draw the lower Padding
- // for (int r = Math.Max (frame.Bottom - sumThickness.Bottom, frame.Y + borderThickness.Top);
- // r < Math.Min (frame.Bottom - borderThickness.Bottom, driver.Rows); r++) {
- // for (int c = frame.X + borderThickness.Left;
- // c < Math.Min (frame.Right - borderThickness.Right, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, ' ');
- // }
- // }
-
- // driver.SetAttribute (savedAttribute);
-
- // // Draw the MarginFrame
- // if (DrawMarginFrame) {
- // var rect = new Rect () {
- // X = frame.X + sumThickness.Left,
- // Y = frame.Y + sumThickness.Top,
- // Width = Math.Max (frame.Width - sumThickness.Right - sumThickness.Left, 0),
- // Height = Math.Max (frame.Height - sumThickness.Bottom - sumThickness.Top, 0)
- // };
- // if (rect.Width > 0 && rect.Height > 0) {
- // driver.DrawWindowFrame (rect, 1, 1, 1, 1, BorderStyle != BorderStyle.None, fill, this);
- // DrawTitle (Parent);
- // }
- // }
-
- // if (Effect3D) {
- // driver.SetAttribute ((Attribute)Effect3DBrush);
-
- // // Draw the upper Effect3D
- // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
- // r < frame.Y; r++) {
- // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
- // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
- // }
- // }
-
- // // Draw the left Effect3D
- // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
- // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
- // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
- // c < frame.X; c++) {
-
- // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
- // }
- // }
-
- // // Draw the right Effect3D
- // for (int r = Math.Max (frame.Y + effect3DOffset.Y, 0);
- // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
- // for (int c = frame.Right;
- // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
- // }
- // }
-
- // // Draw the lower Effect3D
- // for (int r = frame.Bottom;
- // r < Math.Min (frame.Bottom + effect3DOffset.Y, driver.Rows); r++) {
- // for (int c = Math.Max (frame.X + effect3DOffset.X, 0);
- // c < Math.Min (frame.Right + effect3DOffset.X, driver.Cols); c++) {
-
- // AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]);
- // }
- // }
- // }
- // driver.SetAttribute (savedAttribute);
+ // Draw the upper BorderThickness
//}
//private void AddRuneAt (ConsoleDriver driver, int col, int row, Rune ch)
@@ -1167,9 +1084,10 @@ 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) {
@@ -1178,7 +1096,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);
// }
// }
@@ -1194,9 +1112,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));
@@ -1214,4 +1132,4 @@ namespace Terminal.Gui {
BorderChanged?.Invoke (this);
}
}
-}
+}
\ No newline at end of file
diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs
index 46e1ce018..674c19477 100644
--- a/Terminal.Gui/Core/ConsoleDriver.cs
+++ b/Terminal.Gui/Core/ConsoleDriver.cs
@@ -89,7 +89,7 @@ namespace Terminal.Gui {
}
///
- ///
+ /// Indicates the RGB for true colors.
///
public class TrueColor {
///
@@ -119,7 +119,7 @@ namespace Terminal.Gui {
}
///
- ///
+ /// Converts true color to console color.
///
///
public Color ToConsoleColor ()
@@ -504,7 +504,7 @@ namespace Terminal.Gui {
public bool Equals (string x, string y)
{
if (x != null && y != null) {
- return x.ToLowerInvariant () == y.ToLowerInvariant ();
+ return string.Equals (x, y, StringComparison.InvariantCultureIgnoreCase);
}
return false;
}
@@ -659,72 +659,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.
@@ -761,10 +696,22 @@ 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.
+ ///
///
- public abstract bool HeightAsBuffer { get; set; }
+ ///
+ /// NOTE: This functionaliy is currently broken on Windows Terminal.
+ ///
+ public abstract bool EnableConsoleScrolling { get; set; }
///
/// The format is rows, columns and 3 values on the last column: Rune, Attribute and Dirty Flag
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..21a9aac59
--- /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;
+ }
+ }
+}
\ No newline at end of file
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/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/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/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index 02691b84f..08952f48b 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -167,6 +167,7 @@ namespace Terminal.Gui {
///
virtual public void OnLoaded ()
{
+ IsLoaded = true;
foreach (Toplevel tl in Subviews.Where (v => v is Toplevel)) {
tl.OnLoaded ();
}
@@ -367,6 +368,13 @@ namespace Terminal.Gui {
}
}
+ ///
+ /// if was already loaded by the
+ /// , otherwise. This is used to avoid the
+ /// having wrong values while this was not yet loaded.
+ ///
+ public bool IsLoaded { get; private set; }
+
///
public override bool OnKeyDown (KeyEvent keyEvent)
{
@@ -741,12 +749,8 @@ namespace Terminal.Gui {
if (view.Frame.IntersectsWith (bounds) && !OutsideTopFrame (this)) {
view.SetNeedsLayout ();
view.SetNeedsDisplay (view.Bounds);
- //view.Redraw (view.Bounds);
}
}
-
- ClearLayoutNeeded ();
- ClearNeedsDisplay ();
}
base.Redraw (Bounds);
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index cb647fc61..35dcf6f31 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -447,16 +447,34 @@ 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 ();
}
}
+ ///
+ /// The Thickness that separates a View from other SubViews of the same SuperView.
+ /// The Margin is not part of the View's content and is not clipped by the View's Clip Area.
+ ///
public Frame Margin { get; set; }
+
+ ///
+ /// Thickness where a visual border (drawn using line-drawing glyphs) and the Title are drawn.
+ /// The Border expands inward; in other words if `Border.Thickness.Top == 2` the border and
+ /// title will take up the first row and the second row will be filled with spaces.
+ /// The Border is not part of the View's content and is not clipped by the View's `ClipArea`.
+ ///
public Frame BorderFrame { get; set; }
+
+ ///
+ /// Means the Thickness inside of an element that offsets the `Content` from the Border.
+ /// Padding is `{0, 0, 0, 0}` by default. Padding is not part of the View's content and is not clipped by the View's `ClipArea`.
+ ///
+ ///
+ /// (NOTE: in v1 `Padding` is OUTSIDE of the `Border`).
+ ///
public Frame Padding { get; set; }
///
@@ -501,7 +519,7 @@ namespace Terminal.Gui {
ustring title;
///
- /// The title to be displayed for this .
+ /// The title to be displayed for this .
///
/// The title.
public ustring Title {
@@ -860,7 +878,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 ();
@@ -875,21 +892,7 @@ namespace Terminal.Gui {
}
TextFormatter.Size = GetBoundsTextFormatterSize ();
SetNeedsLayout ();
- SetNeedsDisplay (GetMaxNeedDisplay (oldFrame, frame));
- }
-
- Rect GetMaxNeedDisplay (Rect oldFrame, Rect 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)
@@ -1161,15 +1164,8 @@ namespace Terminal.Gui {
///
public void Clear ()
{
- 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;
+ var h = Frame.Height;
+ var w = Frame.Width;
for (var line = 0; line < h; line++) {
Move (0, line);
for (var col = 0; col < w; col++)
@@ -1432,10 +1428,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);
}
@@ -1573,9 +1569,10 @@ namespace Terminal.Gui {
}
var boundsAdjustedForBorder = Bounds;
- if (!IgnoreBorderPropertyOnRedraw && Border != null) {
- throw new InvalidOperationException("Don't use border!");
- } else if (ustring.IsNullOrEmpty (TextFormatter.Text) &&
+ //if (!IgnoreBorderPropertyOnRedraw && Border != null) {
+ // throw new InvalidOperationException("Don't use border!");
+ //} else
+ if (ustring.IsNullOrEmpty (TextFormatter.Text) &&
(GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") &&
(!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) {
@@ -1585,15 +1582,17 @@ namespace Terminal.Gui {
if (!ustring.IsNullOrEmpty (TextFormatter.Text)) {
Rect containerBounds = GetContainerBounds ();
- Clear (ViewToScreen (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 (boundsAdjustedForBorder), HasFocus ? ColorScheme.Focus : GetNormalColor (),
- HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
- containerBounds);
}
// Invoke DrawContentEvent
@@ -1602,7 +1601,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 ();
}
@@ -1631,7 +1630,7 @@ namespace Terminal.Gui {
Rect GetNeedDisplay (Rect containerBounds)
{
- Rect rect = NeedDisplay;
+ Rect rect = ViewToScreen (NeedDisplay);
if (!containerBounds.IsEmpty) {
rect.Width = Math.Min (NeedDisplay.Width, containerBounds.Width);
rect.Height = Math.Min (NeedDisplay.Height, containerBounds.Height);
@@ -2272,8 +2271,7 @@ namespace Terminal.Gui {
newLocation = pos.Anchor (superviewDimension - newDimension);
break;
- case Pos.PosCombine:
- var combine = pos as Pos.PosCombine;
+ case Pos.PosCombine combine:
int left, right;
(left, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.left, dim, autosizeDimension);
(right, newDimension) = GetNewLocationAndDimension (superviewLocation, superviewDimension, combine.right, dim, autosizeDimension);
@@ -2300,7 +2298,7 @@ namespace Terminal.Gui {
// Recursively calculates the new dimension (width or height) of the given Dim given:
// the current location (x or y)
- // the current dimennsion (width or height)
+ // the current dimension (width or height)
int CalculateNewDimension (Dim d, int location, int dimension, int autosize)
{
int newDimension;
@@ -2318,12 +2316,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);
@@ -2335,11 +2333,11 @@ namespace Terminal.Gui {
}
- // horiztonal
- (newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, Width, autosize.Width);
+ // horizontal
+ (newX, newW) = GetNewLocationAndDimension (superviewFrame.X, superviewFrame.Width, x, width, autosize.Width);
// vertical
- (newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, Height, autosize.Height);
+ (newY, newH) = GetNewLocationAndDimension (superviewFrame.Y, superviewFrame.Height, y, height, autosize.Height);
var r = new Rect (newX, newY, newW, newH);
if (Frame != r) {
@@ -2488,7 +2486,7 @@ namespace Terminal.Gui {
if (edges.Any ()) {
(var from, var to) = edges.First ();
- if (from != Application.Top) {
+ if (from != superView?.GetTopSuperView (to, from)) {
if (!ReferenceEquals (from, to)) {
throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {superView}?");
} else {
@@ -2499,8 +2497,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.
@@ -2525,20 +2523,16 @@ namespace Terminal.Gui {
CollectAll (this, ref nodes, ref edges);
var ordered = View.TopologicalSort (SuperView, nodes, edges);
foreach (var v in ordered) {
- if (v.LayoutStyle == LayoutStyle.Computed) {
- v.SetRelativeLayout (Frame);
- }
-
- v.LayoutSubviews ();
- v.LayoutNeeded = false;
+ LayoutSubview (v, Frame);
}
- // If our SuperView is Application.Top and the layoutstyle is Computed it's a special-cass.
- // Use SetRelativeaLayout with the Frame of the Application.Top
- if (SuperView != null && SuperView == Application.Top && LayoutNeeded
- && ordered.Count == 0 && LayoutStyle == LayoutStyle.Computed) {
- Debug.Assert (Application.Top.Frame.Location == Point.Empty);
- SetRelativeLayout (Application.Top.Frame);
+ // If the 'to' is rooted to 'from' and the layoutstyle is Computed it's a special-case.
+ // Use LayoutSubview with the Frame of the 'from'
+ if (SuperView != null && GetTopSuperView () != null && LayoutNeeded
+ && ordered.Count == 0 && edges.Count > 0 && LayoutStyle == LayoutStyle.Computed) {
+
+ (var from, var to) = edges.First ();
+ LayoutSubview (to, from.Frame);
}
LayoutNeeded = false;
@@ -2546,6 +2540,16 @@ namespace Terminal.Gui {
OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
}
+ private void LayoutSubview (View v, Rect hostFrame)
+ {
+ if (v.LayoutStyle == LayoutStyle.Computed) {
+ v.SetRelativeLayout (hostFrame);
+ }
+
+ v.LayoutSubviews ();
+ v.LayoutNeeded = false;
+ }
+
ustring text;
///
@@ -3211,11 +3215,14 @@ namespace Terminal.Gui {
/// Get the top superview of a given .
///
/// The superview view.
- public View GetTopSuperView ()
+ public View GetTopSuperView (View view = null, View superview = null)
{
- View top = Application.Top;
- for (var v = this?.SuperView; v != null; v = v.SuperView) {
+ View top = superview ?? Application.Top;
+ for (var v = view?.SuperView ?? (this?.SuperView); v != null; v = v.SuperView) {
top = v;
+ if (top == superview) {
+ break;
+ }
}
return top;
diff --git a/Terminal.Gui/Core/Window.cs b/Terminal.Gui/Core/Window.cs
index 46755114a..cba895495 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;
@@ -108,7 +108,7 @@ namespace Terminal.Gui {
Border = new Border () {
BorderStyle = DefaultBorderStyle,
Padding = new Thickness (padding),
- BorderBrush = ColorScheme.Normal.Background
+ //Title = title
};
} else {
Border = border;
@@ -136,10 +136,82 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
base.Remove (view);
RemoveMenuStatusBar (view);
+
}
+ /////
+ //public override void RemoveAll ()
+ //{
+ // contentView.RemoveAll ();
+ //}
+
+ /////
+ //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 ();
+ // contentView.SetNeedsDisplay ();
+ // }
+ // 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;
+
+ // ClearLayoutNeeded ();
+ // 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 ());
+ //}
+
+ /////
+ //public override void OnCanFocusChanged ()
+ //{
+ // if (contentView != null) {
+ // contentView.CanFocus = CanFocus;
+ // }
+ // base.OnCanFocusChanged ();
+ //}
+
+ /////
+ ///// The text displayed by the .
+ /////
+ //public override ustring Text {
+ // get => contentView?.Text;
+ // set {
+ // base.Text = value;
+ // if (contentView != null) {
+ // contentView.Text = value;
+ // }
+ // }
+ //}
+
+ /////
+ ///// Controls the text-alignment property of the label, changing it will redisplay the .
+ /////
+ ///// The text alignment.
+ //public override TextAlignment TextAlignment {
+ // get => contentView.TextAlignment;
+ // set {
+ // base.TextAlignment = contentView.TextAlignment = value;
+ // }
+ //}
+
///
- /// Event arguments for chane events.
+ /// Event arguments for change events.
///
public class TitleEventArgs : EventArgs {
///
@@ -153,15 +225,15 @@ 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; }
///
/// Initializes a new instance of
///
- /// The that is/has been replaced.
- /// The new to be replaced.
+ /// The that is/has been replaced.
+ /// The new to be replaced.
public TitleEventArgs (ustring oldTitle, ustring newTitle)
{
OldTitle = oldTitle;
@@ -169,11 +241,11 @@ namespace Terminal.Gui {
}
}
///
- /// Called before the changes. Invokes the event, which can be cancelled.
+ /// Called before the changes. Invokes the event, which can be cancelled.
///
- /// The that is/has been replaced.
- /// The new to be replaced.
- /// `true` if an event handler cancelled the Title change.
+ /// The that is/has been replaced.
+ /// The new to be replaced.
+ /// `true` if an event handler canceled the Title change.
public virtual bool OnTitleChanging (ustring oldTitle, ustring newTitle)
{
var args = new TitleEventArgs (oldTitle, newTitle);
@@ -182,16 +254,16 @@ namespace Terminal.Gui {
}
///
- /// Event fired when the is changing. Set to
+ /// Event fired when the is changing. Set to
/// `true` to cancel the Title change.
///
public event Action TitleChanging;
///
- /// Called when the has been changed. Invokes the event.
+ /// Called when the has been changed. Invokes the event.
///
- /// The that is/has been replaced.
- /// The new to be replaced.
+ /// The that is/has been replaced.
+ /// The new to be replaced.
public virtual void OnTitleChanged (ustring oldTitle, ustring newTitle)
{
var args = new TitleEventArgs (oldTitle, newTitle);
@@ -199,7 +271,7 @@ namespace Terminal.Gui {
}
///
- /// Event fired after the has been changed.
+ /// Event fired after the has been changed.
///
public event Action TitleChanged;
}
diff --git a/Terminal.Gui/Resources/config.json b/Terminal.Gui/Resources/config.json
index 7bb465f68..b59236606 100644
--- a/Terminal.Gui/Resources/config.json
+++ b/Terminal.Gui/Resources/config.json
@@ -23,7 +23,7 @@
"Ctrl"
]
},
- "Application.HeightAsBuffer": false,
+ "Application.EnableConsoleScrolling": false,
"Application.QuitKey": {
"Key": "Q",
"Modifiers": [
diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index 87ed2bcc7..a54bc1cac 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -10,10 +10,10 @@
- 1.0
- 1.0
- 1.0
- 1.0
+ 2.0
+ 2.0
+ 2.0
+ 2.0
@@ -22,11 +22,15 @@
+
+
+
+
-
+
@@ -56,11 +60,6 @@
Strings.Designer.cs
-
-
-
-
-
net7.0
9.0
diff --git a/Terminal.Gui/Views/FrameView.cs b/Terminal.Gui/Views/FrameView.cs
index 01bd8617e..2b0271f6e 100644
--- a/Terminal.Gui/Views/FrameView.cs
+++ b/Terminal.Gui/Views/FrameView.cs
@@ -11,6 +11,42 @@ namespace Terminal.Gui {
///
public class FrameView : View {
+ //internal class FrameViewConfig : Configuration.Config {
+
+ // ///
+ // ///
+ // ///
+ // ///
+ // [JsonConverter (typeof (JsonStringEnumConverter))]
+ // public BorderStyle? DefaultBorderStyle { get; set; }
+
+ // public override void Apply ()
+ // {
+ // if (DefaultBorderStyle.HasValue) {
+ // FrameView.DefaultBorderStyle = DefaultBorderStyle.Value;
+ // }
+ // }
+
+ // public override void CopyUpdatedProperitesFrom (FrameViewConfig changedConfig)
+ // {
+ // if (changedConfig.DefaultBorderStyle.HasValue) {
+ // DefaultBorderStyle = changedConfig.DefaultBorderStyle;
+ // }
+ // }
+
+ // public override void GetHardCodedDefaults ()
+ // {
+ // DefaultBorderStyle = FrameView.DefaultBorderStyle;
+ // }
+ //}
+
+ //[Configuration.ConfigProperty]
+ //internal static FrameViewConfig Config { get; set; } = new FrameViewConfig ();
+
+
+
+
+
///
/// Initializes a new instance of the class using layout.
///
@@ -49,17 +85,52 @@ namespace Terminal.Gui {
void Initialize (Rect frame, ustring title, View [] views = null, Border border = null)
{
- if (title == null) title = ustring.Empty;
this.Title = title;
if (border == null) {
Border = new Border () {
- BorderStyle = DefaultBorderStyle
+ BorderStyle = DefaultBorderStyle,
+ //Title = title
};
} else {
Border = border;
+ //if (ustring.IsNullOrEmpty (border.Title)) {
+ // border.Title = title;
+ //}
}
}
+
+
+ void DrawFrame ()
+ {
+ DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), 0, fill: true);
+ }
+
+ ///
+ /// Add the specified to this container.
+ ///
+ /// to add to this container
+ public override void Add (View view)
+ {
+ if (view.CanFocus)
+ CanFocus = true;
+ }
+
+
+ ///
+ /// Removes a from this container.
+ ///
+ ///
+ ///
+ public override void Remove (View view)
+ {
+ if (view == null)
+ return;
+
+ SetNeedsDisplay ();
+ }
+
+
///
public override bool OnEnter (View view)
{
diff --git a/Terminal.Gui/Views/TableView.cs b/Terminal.Gui/Views/TableView.cs
index 1a69dec07..c1647437b 100644
--- a/Terminal.Gui/Views/TableView.cs
+++ b/Terminal.Gui/Views/TableView.cs
@@ -99,7 +99,7 @@ namespace Terminal.Gui {
/// When is enabled this property contain all rectangles of selected cells. Rectangles describe column/rows selected in (not screen coordinates)
///
///
- public Stack MultiSelectedRegions { get; } = new Stack ();
+ public Stack MultiSelectedRegions { get; private set; } = new Stack ();
///
/// Horizontal scroll offset. The index of the first column in to display when when rendering the view.
@@ -109,7 +109,7 @@ namespace Terminal.Gui {
get => columnOffset;
//try to prevent this being set to an out of bounds column
- set => columnOffset = TableIsNullOrInvisible() ? 0 : Math.Max (0, Math.Min (Table.Columns.Count - 1, value));
+ set => columnOffset = TableIsNullOrInvisible () ? 0 : Math.Max (0, Math.Min (Table.Columns.Count - 1, value));
}
///
@@ -186,7 +186,7 @@ namespace Terminal.Gui {
set {
if (cellActivationKey != value) {
ReplaceKeyBinding (cellActivationKey, value);
-
+
// of API user is mixing and matching old and new methods of keybinding then they may have lost
// the old binding (e.g. with ClearKeybindings) so ReplaceKeyBinding alone will fail
AddKeyBinding (value, Command.Accept);
@@ -218,9 +218,9 @@ namespace Terminal.Gui {
AddCommand (Command.LineDown, () => { ChangeSelectionByOffset (0, 1, false); return true; });
AddCommand (Command.PageUp, () => { PageUp (false); return true; });
AddCommand (Command.PageDown, () => { PageDown (false); return true; });
- AddCommand (Command.LeftHome, () => { ChangeSelectionToStartOfRow (false); return true; });
+ AddCommand (Command.LeftHome, () => { ChangeSelectionToStartOfRow (false); return true; });
AddCommand (Command.RightEnd, () => { ChangeSelectionToEndOfRow (false); return true; });
- AddCommand (Command.TopHome, () => { ChangeSelectionToStartOfTable(false); return true; });
+ AddCommand (Command.TopHome, () => { ChangeSelectionToStartOfTable (false); return true; });
AddCommand (Command.BottomEnd, () => { ChangeSelectionToEndOfTable (false); return true; });
AddCommand (Command.RightExtend, () => { ChangeSelectionByOffset (1, 0, true); return true; });
@@ -234,8 +234,10 @@ namespace Terminal.Gui {
AddCommand (Command.TopHomeExtend, () => { ChangeSelectionToStartOfTable (true); return true; });
AddCommand (Command.BottomEndExtend, () => { ChangeSelectionToEndOfTable (true); return true; });
- AddCommand (Command.SelectAll, () => { SelectAll(); return true; });
- AddCommand (Command.Accept, () => { OnCellActivated(new CellActivatedEventArgs (Table, SelectedColumn, SelectedRow)); return true; });
+ AddCommand (Command.SelectAll, () => { SelectAll (); return true; });
+ AddCommand (Command.Accept, () => { OnCellActivated (new CellActivatedEventArgs (Table, SelectedColumn, SelectedRow)); return true; });
+
+ AddCommand (Command.ToggleChecked, () => { ToggleCurrentCellSelection (); return true; });
// Default keybindings for this view
AddKeyBinding (Key.CursorLeft, Command.Left);
@@ -252,7 +254,7 @@ namespace Terminal.Gui {
AddKeyBinding (Key.CursorLeft | Key.ShiftMask, Command.LeftExtend);
AddKeyBinding (Key.CursorRight | Key.ShiftMask, Command.RightExtend);
AddKeyBinding (Key.CursorUp | Key.ShiftMask, Command.LineUpExtend);
- AddKeyBinding (Key.CursorDown| Key.ShiftMask, Command.LineDownExtend);
+ AddKeyBinding (Key.CursorDown | Key.ShiftMask, Command.LineDownExtend);
AddKeyBinding (Key.PageUp | Key.ShiftMask, Command.PageUpExtend);
AddKeyBinding (Key.PageDown | Key.ShiftMask, Command.PageDownExtend);
AddKeyBinding (Key.Home | Key.ShiftMask, Command.LeftHomeExtend);
@@ -264,33 +266,34 @@ namespace Terminal.Gui {
AddKeyBinding (CellActivationKey, Command.Accept);
}
+
///
public override void Redraw (Rect bounds)
- {
- Move (0, 0);
- var frame = Frame;
+ {
+ Move (0, 0);
+ var frame = Frame;
- scrollRightPoint = null;
- scrollLeftPoint = null;
+ scrollRightPoint = null;
+ scrollLeftPoint = null;
- // What columns to render at what X offset in viewport
- var columnsToRender = CalculateViewport (bounds).ToArray ();
+ // What columns to render at what X offset in viewport
+ var columnsToRender = CalculateViewport (bounds).ToArray ();
- Driver.SetAttribute (GetNormalColor ());
+ Driver.SetAttribute (GetNormalColor ());
- //invalidate current row (prevents scrolling around leaving old characters in the frame
- Driver.AddStr (new string (' ', bounds.Width));
+ //invalidate current row (prevents scrolling around leaving old characters in the frame
+ Driver.AddStr (new string (' ', bounds.Width));
- int line = 0;
+ int line = 0;
- if (ShouldRenderHeaders ()) {
- // Render something like:
- /*
- ┌────────────────────┬──────────┬───────────┬──────────────┬─────────┐
- │ArithmeticComparator│chi │Healthboard│Interpretation│Labnumber│
- └────────────────────┴──────────┴───────────┴──────────────┴─────────┘
- */
- if (Style.ShowHorizontalHeaderOverline) {
+ if (ShouldRenderHeaders ()) {
+ // Render something like:
+ /*
+ ┌────────────────────┬──────────┬───────────┬──────────────┬─────────┐
+ │ArithmeticComparator│chi │Healthboard│Interpretation│Labnumber│
+ └────────────────────┴──────────┴───────────┴──────────────┴─────────┘
+ */
+ if (Style.ShowHorizontalHeaderOverline) {
RenderHeaderOverline (line, bounds.Width, columnsToRender);
line++;
}
@@ -436,19 +439,19 @@ namespace Terminal.Gui {
bool moreColumnsToLeft = ColumnOffset > 0;
// if we moved left would we find a new column (or are they all invisible?)
- if(!TryGetNearestVisibleColumn (ColumnOffset-1, false, false, out _)) {
+ if (!TryGetNearestVisibleColumn (ColumnOffset - 1, false, false, out _)) {
moreColumnsToLeft = false;
}
// are there visible columns to the right that have not yet been reached?
// lets find out, what is the column index of the last column we are rendering
int lastColumnIdxRendered = ColumnOffset + columnsToRender.Length - 1;
-
+
// are there more valid indexes?
bool moreColumnsToRight = lastColumnIdxRendered < Table.Columns.Count;
// if we went right from the last column would we find a new visible column?
- if(!TryGetNearestVisibleColumn (lastColumnIdxRendered + 1, true, false, out _)) {
+ if (!TryGetNearestVisibleColumn (lastColumnIdxRendered + 1, true, false, out _)) {
// no we would not
moreColumnsToRight = false;
}
@@ -466,7 +469,7 @@ namespace Terminal.Gui {
// whole way but update to instead draw a header indicator
// or scroll arrow etc
var rune = Driver.HLine;
-
+
if (Style.ShowVerticalHeaderLines) {
if (c == 0) {
// for first character render line
@@ -475,12 +478,11 @@ namespace Terminal.Gui {
// unless we have horizontally scrolled along
// in which case render an arrow, to indicate user
// can scroll left
- if(Style.ShowHorizontalScrollIndicators && moreColumnsToLeft)
- {
+ if (Style.ShowHorizontalScrollIndicators && moreColumnsToLeft) {
rune = Driver.LeftArrow;
- scrollLeftPoint = new Point(c,row);
+ scrollLeftPoint = new Point (c, row);
}
-
+
}
// if the next column is the start of a header
else if (columnsToRender.Any (r => r.X == c + 1)) {
@@ -495,10 +497,9 @@ namespace Terminal.Gui {
// unless there is more of the table we could horizontally
// scroll along to see. In which case render an arrow,
// to indicate user can scroll right
- if(Style.ShowHorizontalScrollIndicators && moreColumnsToRight)
- {
+ if (Style.ShowHorizontalScrollIndicators && moreColumnsToRight) {
rune = Driver.RightArrow;
- scrollRightPoint = new Point(c,row);
+ scrollRightPoint = new Point (c, row);
}
}
@@ -518,7 +519,7 @@ namespace Terminal.Gui {
var focused = HasFocus;
var rowScheme = (Style.RowColorGetter?.Invoke (
- new RowColorGetterArgs(Table,rowToRender))) ?? ColorScheme;
+ new RowColorGetterArgs (Table, rowToRender))) ?? ColorScheme;
//render start of line
if (style.ShowVerticalCellLines)
@@ -529,11 +530,9 @@ namespace Terminal.Gui {
Attribute color;
- if(FullRowSelect && IsSelected (0, rowToRender)) {
+ if (FullRowSelect && IsSelected (0, rowToRender)) {
color = focused ? rowScheme.HotFocus : rowScheme.HotNormal;
- }
- else
- {
+ } else {
color = Enabled ? rowScheme.Normal : rowScheme.Disabled;
}
@@ -562,17 +561,16 @@ namespace Terminal.Gui {
var colorSchemeGetter = colStyle?.ColorGetter;
ColorScheme scheme;
- if(colorSchemeGetter != null) {
+ if (colorSchemeGetter != null) {
// user has a delegate for defining row color per cell, call it
- scheme = colorSchemeGetter(
- new CellColorGetterArgs (Table, rowToRender, current.Column.Ordinal, val, representation,rowScheme));
+ scheme = colorSchemeGetter (
+ new CellColorGetterArgs (Table, rowToRender, current.Column.Ordinal, val, representation, rowScheme));
// if users custom color getter returned null, use the row scheme
- if(scheme == null) {
+ if (scheme == null) {
scheme = rowScheme;
}
- }
- else {
+ } else {
// There is no custom cell coloring delegate so use the scheme for the row
scheme = rowScheme;
}
@@ -588,16 +586,15 @@ namespace Terminal.Gui {
// While many cells can be selected (see MultiSelectedRegions) only one cell is the primary (drives navigation etc)
bool isPrimaryCell = current.Column.Ordinal == selectedColumn && rowToRender == selectedRow;
-
- RenderCell (cellColor,render,isPrimaryCell);
-
+
+ RenderCell (cellColor, render, isPrimaryCell);
+
// Reset color scheme to normal for drawing separators if we drew text with custom scheme
if (scheme != rowScheme) {
- if(isSelectedCell) {
+ if (isSelectedCell) {
color = focused ? rowScheme.HotFocus : rowScheme.HotNormal;
- }
- else {
+ } else {
color = Enabled ? rowScheme.Normal : rowScheme.Disabled;
}
Driver.SetAttribute (color);
@@ -629,7 +626,7 @@ namespace Terminal.Gui {
///
///
///
- protected virtual void RenderCell (Attribute cellColor, string render,bool isPrimaryCell)
+ protected virtual void RenderCell (Attribute cellColor, string render, bool isPrimaryCell)
{
// If the cell is the selected col/row then draw the first rune in inverted colors
// this allows the user to track which cell is the active one during a multi cell
@@ -740,12 +737,15 @@ namespace Terminal.Gui {
col = GetNearestVisibleColumn (col, lookRight, true);
- if (!MultiSelect || !extendExistingSelection)
- MultiSelectedRegions.Clear ();
+ if (!MultiSelect || !extendExistingSelection) {
+ ClearMultiSelectedRegions (true);
+ }
+
if (extendExistingSelection) {
+
// If we are extending current selection but there isn't one
- if (MultiSelectedRegions.Count == 0) {
+ if (MultiSelectedRegions.Count == 0 || MultiSelectedRegions.All(m=>m.IsToggled)) {
// Create a new region between the old active cell and the new cell
var rect = CreateTableSelection (SelectedColumn, SelectedRow, col, row);
MultiSelectedRegions.Push (rect);
@@ -761,6 +761,24 @@ namespace Terminal.Gui {
SelectedRow = row;
}
+ private void ClearMultiSelectedRegions (bool keepToggledSelections)
+ {
+ if (!keepToggledSelections) {
+ MultiSelectedRegions.Clear ();
+ return;
+ }
+
+ var oldRegions = MultiSelectedRegions.ToArray ().Reverse ();
+
+ MultiSelectedRegions.Clear ();
+
+ foreach (var region in oldRegions) {
+ if (region.IsToggled) {
+ MultiSelectedRegions.Push (region);
+ }
+ }
+ }
+
///
/// Unions the current selected cell (and/or regions) with the provided cell and makes
/// it the active one.
@@ -769,10 +787,10 @@ namespace Terminal.Gui {
///
private void UnionSelection (int col, int row)
{
- if (!MultiSelect || TableIsNullOrInvisible()) {
+ if (!MultiSelect || TableIsNullOrInvisible ()) {
return;
}
-
+
EnsureValidSelection ();
var oldColumn = SelectedColumn;
@@ -812,7 +830,7 @@ namespace Terminal.Gui {
/// Moves the selection up by one page
///
/// true to extend the current selection (if any) instead of replacing
- public void PageUp(bool extend)
+ public void PageUp (bool extend)
{
ChangeSelectionByOffset (0, -(Bounds.Height - GetHeaderHeightIfAny ()), extend);
Update ();
@@ -822,7 +840,7 @@ namespace Terminal.Gui {
/// Moves the selection down by one page
///
/// true to extend the current selection (if any) instead of replacing
- public void PageDown(bool extend)
+ public void PageDown (bool extend)
{
ChangeSelectionByOffset (0, Bounds.Height - GetHeaderHeightIfAny (), extend);
Update ();
@@ -846,7 +864,7 @@ namespace Terminal.Gui {
/// to (,nY) i.e. no horizontal scrolling.
///
/// true to extend the current selection (if any) instead of replacing
- public void ChangeSelectionToEndOfTable(bool extend)
+ public void ChangeSelectionToEndOfTable (bool extend)
{
var finalColumn = Table.Columns.Count - 1;
@@ -880,10 +898,10 @@ namespace Terminal.Gui {
///
public void SelectAll ()
{
- if (TableIsNullOrInvisible() || !MultiSelect || Table.Rows.Count == 0)
+ if (TableIsNullOrInvisible () || !MultiSelect || Table.Rows.Count == 0)
return;
- MultiSelectedRegions.Clear ();
+ ClearMultiSelectedRegions (true);
// Create a single region over entire table, set the origin of the selection to the active cell so that a followup spread selection e.g. shift-right behaves properly
MultiSelectedRegions.Push (new TableSelection (new Point (SelectedColumn, SelectedRow), new Rect (0, 0, Table.Columns.Count, table.Rows.Count)));
@@ -893,16 +911,18 @@ namespace Terminal.Gui {
///
/// Returns all cells in any (if is enabled) and the selected cell
///
- /// Return value is not affected by (i.e. returned s are not expanded to
- /// include all points on row).
///
public IEnumerable GetAllSelectedCells ()
{
if (TableIsNullOrInvisible () || Table.Rows.Count == 0)
- yield break;
+ {
+ return Enumerable.Empty();
+ }
EnsureValidSelection ();
+ var toReturn = new HashSet();
+
// If there are one or more rectangular selections
if (MultiSelect && MultiSelectedRegions.Any ()) {
@@ -916,25 +936,27 @@ namespace Terminal.Gui {
for (int y = yMin; y < yMax; y++) {
for (int x = xMin; x < xMax; x++) {
if (IsSelected (x, y)) {
- yield return new Point (x, y);
+ toReturn.Add(new Point (x, y));
}
}
}
- } else {
+ }
- // if there are no region selections then it is just the active cell
- // if we are selecting the full row
- if (FullRowSelect) {
- // all cells in active row are selected
- for (int x = 0; x < Table.Columns.Count; x++) {
- yield return new Point (x, SelectedRow);
- }
- } else {
- // Not full row select and no multi selections
- yield return new Point (SelectedColumn, SelectedRow);
+ // if there are no region selections then it is just the active cell
+
+ // if we are selecting the full row
+ if (FullRowSelect) {
+ // all cells in active row are selected
+ for (int x = 0; x < Table.Columns.Count; x++) {
+ toReturn.Add(new Point (x, SelectedRow));
}
+ } else {
+ // Not full row select and no multi selections
+ toReturn.Add(new Point (SelectedColumn, SelectedRow));
}
+
+ return toReturn;
}
///
@@ -944,17 +966,60 @@ namespace Terminal.Gui {
/// Origin point for the selection in Y
/// End point for the selection in X
/// End point for the selection in Y
+ /// True if selection is result of
///
- private TableSelection CreateTableSelection (int pt1X, int pt1Y, int pt2X, int pt2Y)
+ private TableSelection CreateTableSelection (int pt1X, int pt1Y, int pt2X, int pt2Y, bool toggle = false)
{
- var top = Math.Max(Math.Min (pt1Y, pt2Y), 0);
- var bot = Math.Max(Math.Max (pt1Y, pt2Y), 0);
+ var top = Math.Max (Math.Min (pt1Y, pt2Y), 0);
+ var bot = Math.Max (Math.Max (pt1Y, pt2Y), 0);
- var left = Math.Max(Math.Min (pt1X, pt2X), 0);
- var right = Math.Max(Math.Max (pt1X, pt2X), 0);
+ var left = Math.Max (Math.Min (pt1X, pt2X), 0);
+ var right = Math.Max (Math.Max (pt1X, pt2X), 0);
// Rect class is inclusive of Top Left but exclusive of Bottom Right so extend by 1
- return new TableSelection (new Point (pt1X, pt1Y), new Rect (left, top, right - left + 1, bot - top + 1));
+ return new TableSelection (new Point (pt1X, pt1Y), new Rect (left, top, right - left + 1, bot - top + 1)) {
+ IsToggled = toggle
+ };
+ }
+
+ private void ToggleCurrentCellSelection ()
+ {
+ if (!MultiSelect) {
+ return;
+ }
+
+ var regions = GetMultiSelectedRegionsContaining(selectedColumn, selectedRow).ToArray();
+ var toggles = regions.Where(s=>s.IsToggled).ToArray ();
+
+ // Toggle it off
+ if (toggles.Any ()) {
+
+ var oldRegions = MultiSelectedRegions.ToArray ().Reverse ();
+ MultiSelectedRegions.Clear ();
+
+ foreach (var region in oldRegions) {
+ if (!toggles.Contains (region))
+ MultiSelectedRegions.Push (region);
+ }
+ } else {
+
+ // user is toggling selection within a rectangular
+ // select. So toggle the full region
+ if(regions.Any())
+ {
+ foreach(var r in regions)
+ {
+ r.IsToggled = true;
+ }
+ }
+ else{
+ // Toggle on a single cell selection
+ MultiSelectedRegions.Push (
+ CreateTableSelection (selectedColumn, SelectedRow, selectedColumn, selectedRow, true)
+ );
+ }
+
+ }
}
///
@@ -978,22 +1043,36 @@ namespace Terminal.Gui {
///
public bool IsSelected (int col, int row)
{
- if(!IsColumnVisible(col)) {
+ if (!IsColumnVisible (col)) {
return false;
- }
+ }
- // Cell is also selected if in any multi selection region
- if (MultiSelect && MultiSelectedRegions.Any (r => r.Rect.Contains (col, row)))
- return true;
-
- // Cell is also selected if Y axis appears in any region (when FullRowSelect is enabled)
- if (FullRowSelect && MultiSelect && MultiSelectedRegions.Any (r => r.Rect.Bottom > row && r.Rect.Top <= row))
+ if(GetMultiSelectedRegionsContaining(col,row).Any())
+ {
return true;
+ }
return row == SelectedRow &&
(col == SelectedColumn || FullRowSelect);
}
+ private IEnumerable GetMultiSelectedRegionsContaining(int col, int row)
+ {
+ if(!MultiSelect)
+ {
+ return Enumerable.Empty();
+ }
+
+ if(FullRowSelect)
+ {
+ return MultiSelectedRegions.Where (r => r.Rect.Bottom > row && r.Rect.Top <= row);
+ }
+ else
+ {
+ return MultiSelectedRegions.Where (r => r.Rect.Contains (col, row));
+ }
+ }
+
///
/// Returns true if the given indexes a visible
/// column otherwise false. Returns false for indexes that are out of bounds.
@@ -1071,19 +1150,17 @@ namespace Terminal.Gui {
if (me.Flags.HasFlag (MouseFlags.Button1Clicked)) {
- if (scrollLeftPoint != null
+ if (scrollLeftPoint != null
&& scrollLeftPoint.Value.X == me.X
- && scrollLeftPoint.Value.Y == me.Y)
- {
+ && scrollLeftPoint.Value.Y == me.Y) {
ColumnOffset--;
EnsureValidScrollOffsets ();
SetNeedsDisplay ();
}
- if (scrollRightPoint != null
+ if (scrollRightPoint != null
&& scrollRightPoint.Value.X == me.X
- && scrollRightPoint.Value.Y == me.Y)
- {
+ && scrollRightPoint.Value.Y == me.Y) {
ColumnOffset++;
EnsureValidScrollOffsets ();
SetNeedsDisplay ();
@@ -1092,8 +1169,8 @@ namespace Terminal.Gui {
var hit = ScreenToCell (me.X, me.Y);
if (hit != null) {
- if(MultiSelect && HasControlOrAlt(me)) {
- UnionSelection(hit.Value.X, hit.Value.Y);
+ if (MultiSelect && HasControlOrAlt (me)) {
+ UnionSelection (hit.Value.X, hit.Value.Y);
} else {
SetSelection (hit.Value.X, hit.Value.Y, me.Flags.HasFlag (MouseFlags.ButtonShift));
}
@@ -1128,7 +1205,7 @@ namespace Terminal.Gui {
/// Cell clicked or null.
public Point? ScreenToCell (int clientX, int clientY)
{
- return ScreenToCell(clientX, clientY, out _);
+ return ScreenToCell (clientX, clientY, out _);
}
///
@@ -1153,7 +1230,7 @@ namespace Terminal.Gui {
headerIfAny = col?.Column;
return null;
}
-
+
var rowIdx = RowOffset - headerHeight + clientY;
@@ -1161,7 +1238,7 @@ namespace Terminal.Gui {
// invalid index back to user!
if (rowIdx >= Table.Rows.Count) {
return null;
- }
+ }
if (col != null && rowIdx >= 0) {
@@ -1242,10 +1319,10 @@ namespace Terminal.Gui {
/// Changes will not be immediately visible in the display until you call
public void EnsureValidSelection ()
{
- if (TableIsNullOrInvisible()) {
+ if (TableIsNullOrInvisible ()) {
// Table doesn't exist, we should probably clear those selections
- MultiSelectedRegions.Clear ();
+ ClearMultiSelectedRegions (false);
return;
}
@@ -1315,8 +1392,7 @@ namespace Terminal.Gui {
/// Use false if you are primarily interested in learning about directional column visibility.
private int GetNearestVisibleColumn (int columnIndex, bool lookRight, bool allowBumpingInOppositeDirection)
{
- if(TryGetNearestVisibleColumn(columnIndex,lookRight,allowBumpingInOppositeDirection, out var answer))
- {
+ if (TryGetNearestVisibleColumn (columnIndex, lookRight, allowBumpingInOppositeDirection, out var answer)) {
return answer;
}
@@ -1335,7 +1411,7 @@ namespace Terminal.Gui {
// get the column visibility by index (if no style visible is true)
bool [] columnVisibility = Table.Columns.Cast ()
.Select (c => this.Style.GetColumnStyleIfAny (c)?.Visible ?? true)
- .ToArray();
+ .ToArray ();
// column is visible
if (columnVisibility [columnIndex]) {
@@ -1346,10 +1422,9 @@ namespace Terminal.Gui {
int increment = lookRight ? 1 : -1;
// move in that direction
- for (int i = columnIndex; i >=0 && i < columnVisibility.Length; i += increment) {
+ for (int i = columnIndex; i >= 0 && i < columnVisibility.Length; i += increment) {
// if we find a visible column
- if(columnVisibility [i])
- {
+ if (columnVisibility [i]) {
idx = i;
return true;
}
@@ -1357,7 +1432,7 @@ namespace Terminal.Gui {
// Caller only wants to look in one direction and we did not find any
// visible columns in that direction
- if(!allowBumpingInOppositeDirection) {
+ if (!allowBumpingInOppositeDirection) {
idx = columnIndex;
return false;
}
@@ -1400,10 +1475,10 @@ namespace Terminal.Gui {
//if we have scrolled too far to the right
if (SelectedColumn > columnsToRender.Max (r => r.Column.Ordinal)) {
- if(Style.SmoothHorizontalScrolling) {
+ if (Style.SmoothHorizontalScrolling) {
// Scroll right 1 column at a time until the users selected column is visible
- while(SelectedColumn > columnsToRender.Max (r => r.Column.Ordinal)) {
+ while (SelectedColumn > columnsToRender.Max (r => r.Column.Ordinal)) {
ColumnOffset++;
columnsToRender = CalculateViewport (Bounds).ToArray ();
@@ -1414,11 +1489,10 @@ namespace Terminal.Gui {
break;
}
- }
- else {
+ } else {
ColumnOffset = SelectedColumn;
}
-
+
}
//if we have scrolled too far down
@@ -1482,7 +1556,7 @@ namespace Terminal.Gui {
int colWidth;
// if column is not being rendered
- if(colStyle?.Visible == false) {
+ if (colStyle?.Visible == false) {
// do not add it to the returned columns
continue;
}
@@ -1492,16 +1566,14 @@ namespace Terminal.Gui {
// there is not enough space for this columns
// visible content
- if (usedSpace + colWidth > availableHorizontalSpace)
- {
+ if (usedSpace + colWidth > availableHorizontalSpace) {
bool showColumn = false;
// if this column accepts flexible width rendering and
// is therefore happy rendering into less space
- if ( colStyle != null && colStyle.MinAcceptableWidth > 0 &&
+ if (colStyle != null && colStyle.MinAcceptableWidth > 0 &&
// is there enough space to meet the MinAcceptableWidth
- (availableHorizontalSpace - usedSpace) >= colStyle.MinAcceptableWidth)
- {
+ (availableHorizontalSpace - usedSpace) >= colStyle.MinAcceptableWidth) {
// show column and use use whatever space is
// left for rendering it
showColumn = true;
@@ -1510,14 +1582,13 @@ namespace Terminal.Gui {
// If its the only column we are able to render then
// accept it anyway (that must be one massively wide column!)
- if (first)
- {
+ if (first) {
showColumn = true;
}
// no special exceptions and we are out of space
// so stop accepting new columns for the render area
- if(!showColumn)
+ if (!showColumn)
break;
}
@@ -1771,7 +1842,7 @@ namespace Terminal.Gui {
/// Delegate for coloring specific rows in a different color. For cell color
///
///
- public RowColorGetterDelegate RowColorGetter {get;set;}
+ public RowColorGetterDelegate RowColorGetter { get; set; }
///
/// Determines rendering when the last column in the table is visible but it's
@@ -1781,7 +1852,7 @@ namespace Terminal.Gui {
/// and leave a blank column that cannot be selected in the remaining space.
///
///
- public bool ExpandLastColumn {get;set;} = true;
+ public bool ExpandLastColumn { get; set; } = true;
///
///
@@ -1798,7 +1869,7 @@ namespace Terminal.Gui {
///
///
public bool SmoothHorizontalScrolling { get; set; } = true;
-
+
///
/// Returns the entry from for the given or null if no custom styling is defined for it
///
@@ -2003,6 +2074,12 @@ namespace Terminal.Gui {
///
public Rect Rect { get; set; }
+ ///
+ /// True if the selection was made through
+ /// and therefore should persist even through keyboard navigation.
+ ///
+ public bool IsToggled { get; set; }
+
///
/// Creates a new selected area starting at the origin corner and covering the provided rectangular area
///
diff --git a/Terminal.Gui/Views/TileView.cs b/Terminal.Gui/Views/TileView.cs
index c45401abe..d5a431721 100644
--- a/Terminal.Gui/Views/TileView.cs
+++ b/Terminal.Gui/Views/TileView.cs
@@ -13,6 +13,12 @@ namespace Terminal.Gui {
public class TileView : View {
TileView parentTileView;
+ ///
+ /// The keyboard key that the user can press to toggle resizing
+ /// of splitter lines. Mouse drag splitting is always enabled.
+ ///
+ public Key ToggleResizable { get; set; } = Key.CtrlMask | Key.F10;
+
///
/// A single presented in a . To create
/// new instances use
@@ -167,7 +173,6 @@ namespace Terminal.Gui {
///
public TileView (int tiles)
{
- CanFocus = true;
RebuildForTileCount (tiles);
IgnoreBorderPropertyOnRedraw = true;
Border = new Border () {
@@ -403,15 +408,6 @@ namespace Terminal.Gui {
return true;
}
- ///
- public override bool OnEnter (View view)
- {
- Driver.SetCursorVisibility (CursorVisibility.Invisible);
- if (!Tiles.Where (t => t.ContentView.HasFocus).Any ()) {
- Tiles.FirstOrDefault ()?.ContentView.SetFocus ();
- }
- return base.OnEnter (view);
- }
///
public override void Redraw (Rect bounds)
@@ -550,6 +546,30 @@ namespace Terminal.Gui {
return true;
}
+ ///
+ public override bool ProcessHotKey (KeyEvent keyEvent)
+ {
+ bool focusMoved = false;
+
+ if(keyEvent.Key == ToggleResizable) {
+ foreach(var l in splitterLines) {
+
+ var iniBefore = l.IsInitialized;
+ l.IsInitialized = false;
+ l.CanFocus = !l.CanFocus;
+ l.IsInitialized = iniBefore;
+
+ if (l.CanFocus && !focusMoved) {
+ l.SetFocus ();
+ focusMoved = true;
+ }
+ }
+ return true;
+ }
+
+ return base.ProcessHotKey (keyEvent);
+ }
+
private bool IsValidNewSplitterPos (int idx, Pos value, int fullSpace)
{
int newSize = value.Anchor (fullSpace);
@@ -750,7 +770,7 @@ namespace Terminal.Gui {
tile.ContentView.Width = GetTileWidthOrHeight (i, Bounds.Width, visibleTiles, visibleSplitterLines);
} else {
tile.ContentView.X = bounds.X;
- tile.ContentView.Y = i == 0 ? 0 : Pos.Bottom (visibleSplitterLines [i - 1]);
+ tile.ContentView.Y = i == 0 ? bounds.Y : Pos.Bottom (visibleSplitterLines [i - 1]);
tile.ContentView.Width = bounds.Width;
tile.ContentView.Height = GetTileWidthOrHeight (i, Bounds.Height, visibleTiles, visibleSplitterLines);
}
@@ -864,7 +884,7 @@ namespace Terminal.Gui {
public TileViewLineView (TileView parent, int idx)
{
- CanFocus = true;
+ CanFocus = false;
TabStop = true;
this.Parent = parent;
@@ -929,7 +949,7 @@ namespace Terminal.Gui {
public void DrawSplitterSymbol ()
{
- if (CanFocus && HasFocus) {
+ if (dragPosition != null || CanFocus) {
var location = moveRuneRenderLocation ??
new Point (Bounds.Width / 2, Bounds.Height / 2);
@@ -939,10 +959,6 @@ namespace Terminal.Gui {
public override bool MouseEvent (MouseEvent mouseEvent)
{
- if (!CanFocus) {
- return true;
- }
-
if (!dragPosition.HasValue && (mouseEvent.Flags == MouseFlags.Button1Pressed)) {
// Start a Drag
diff --git a/Terminal.Gui/Windows/Dialog.cs b/Terminal.Gui/Windows/Dialog.cs
index 66327ac5a..74d1c3fd8 100644
--- a/Terminal.Gui/Windows/Dialog.cs
+++ b/Terminal.Gui/Windows/Dialog.cs
@@ -79,6 +79,7 @@ namespace Terminal.Gui {
Modal = true;
ButtonAlignment = DefaultButtonAlignment;
Border = DefaultBorder;
+ //Border.Title = title;
if (buttons != null) {
foreach (var b in buttons) {
diff --git a/UICatalog/Properties/launchSettings.json b/UICatalog/Properties/launchSettings.json
index 80329d78d..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,16 +50,6 @@
"Windows & FrameViews": {
"commandName": "Project",
"commandLineArgs": "\"Windows & FrameViews\""
- },
- "WSL : UICatalog": {
- "commandName": "Executable",
- "executablePath": "wsl",
- "commandLineArgs": "dotnet UICatalog.dll",
- "distributionName": ""
- },
- "Tile View Experiments": {
- "commandName": "Project",
- "commandLineArgs": "\"Tile View Experiments\""
}
}
}
\ No newline at end of file
diff --git a/UICatalog/Scenarios/ASCIICustomButton.cs b/UICatalog/Scenarios/ASCIICustomButton.cs
new file mode 100644
index 000000000..a58b2200c
--- /dev/null
+++ b/UICatalog/Scenarios/ASCIICustomButton.cs
@@ -0,0 +1,313 @@
+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 = (bool)(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 class UICatalogTopLevel : Toplevel {
public MenuItem miIsMouseDisabled;
- public MenuItem miHeightAsBuffer;
+ public MenuItem miEnableConsoleScrolling;
public TileView ContentPane;
public ListView CategoryListView;
@@ -349,6 +356,8 @@ namespace UICatalog {
{
ConfigChanged ();
+ miIsMouseDisabled.Checked = Application.IsMouseDisabled;
+ miEnableConsoleScrolling.Checked = Application.EnableConsoleScrolling;
DriverName.Title = $"Driver: {Driver.GetType ().Name}";
OS.Title = $"OS: {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystem} {Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.OperatingSystemVersion}";
@@ -403,13 +412,12 @@ namespace UICatalog {
List
TRACE
@@ -28,7 +28,7 @@
-
+
diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs
index eaa15848f..637174d17 100644
--- a/UnitTests/Application/ApplicationTests.cs
+++ b/UnitTests/Application/ApplicationTests.cs
@@ -24,8 +24,7 @@ namespace Terminal.Gui.ApplicationTests {
Assert.Null (Application.Driver);
Assert.Null (Application.Top);
Assert.Null (Application.Current);
- // removed below as HeightAsBuffer now works without a driver loaded
- //Assert.Throws (() => Application.HeightAsBuffer == true);
+ Assert.False (Application.EnableConsoleScrolling);
Assert.Null (Application.MainLoop);
Assert.Null (Application.Iteration);
Assert.Null (Application.RootMouseEvent);
@@ -37,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);
@@ -314,7 +313,7 @@ namespace Terminal.Gui.ApplicationTests {
public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws ()
{
Init ();
-
+
Application.Driver = null;
Application.Iteration = () => {
@@ -334,8 +333,8 @@ namespace Terminal.Gui.ApplicationTests {
[Fact]
public void Run_T_NoInit_DoesNotThrow ()
{
- Application.ForceFakeConsole = true;
-
+ Application.ForceFakeConsole = true;
+
Application.Iteration = () => {
Application.RequestStop ();
};
@@ -431,7 +430,7 @@ namespace Terminal.Gui.ApplicationTests {
}
// TODO: Add tests for Run that test errorHandler
-
+
#endregion
#region ShutdownTests
diff --git a/UnitTests/Configuration/ConfigurationMangerTests.cs b/UnitTests/Configuration/ConfigurationMangerTests.cs
index be039028f..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 ();
@@ -226,7 +227,7 @@ namespace Terminal.Gui.ConfigurationTests {
ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue = Key.B;
ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue = true;
ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue = true;
- ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue = true;
+ ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Settings.Apply ();
// assert apply worked
@@ -235,7 +236,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.B, Application.AlternateBackwardKey);
Assert.True (Application.UseSystemConsole);
Assert.True (Application.IsMouseDisabled);
- Assert.True (Application.HeightAsBuffer);
+ Assert.True (Application.EnableConsoleScrolling);
//act
ConfigurationManager.Reset ();
@@ -248,7 +249,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.PageUp | Key.CtrlMask, Application.AlternateBackwardKey);
Assert.False (Application.UseSystemConsole);
Assert.False (Application.IsMouseDisabled);
- Assert.False (Application.HeightAsBuffer);
+ Assert.False (Application.EnableConsoleScrolling);
// arrange
ConfigurationManager.Settings ["Application.QuitKey"].PropertyValue = Key.Q;
@@ -256,7 +257,7 @@ namespace Terminal.Gui.ConfigurationTests {
ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue = Key.B;
ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue = true;
ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue = true;
- ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue = true;
+ ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Settings.Apply ();
@@ -274,7 +275,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.PageUp | Key.CtrlMask, Application.AlternateBackwardKey);
Assert.False (Application.UseSystemConsole);
Assert.False (Application.IsMouseDisabled);
- Assert.False (Application.HeightAsBuffer);
+ Assert.False (Application.EnableConsoleScrolling);
}
@@ -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)]
@@ -771,7 +771,7 @@ namespace Terminal.Gui.ConfigurationTests {
ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue = Key.B;
ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue = true;
ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue = true;
- ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue = true;
+ ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Updated += ConfigurationManager_Updated;
bool fired = false;
@@ -784,7 +784,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.PageUp | Key.CtrlMask, ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue);
Assert.False ((bool)ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue);
Assert.False ((bool)ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue);
- Assert.False ((bool)ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue);
+ Assert.False ((bool)ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue);
}
ConfigurationManager.Load (true);
@@ -810,7 +810,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.B, Application.AlternateBackwardKey);
Assert.True (Application.UseSystemConsole);
Assert.True (Application.IsMouseDisabled);
- Assert.True (Application.HeightAsBuffer);
+ Assert.True (Application.EnableConsoleScrolling);
}
// act
@@ -819,7 +819,7 @@ namespace Terminal.Gui.ConfigurationTests {
ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue = Key.B;
ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue = true;
ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue = true;
- ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue = true;
+ ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Apply ();
diff --git a/UnitTests/Configuration/SettingsScopeTests.cs b/UnitTests/Configuration/SettingsScopeTests.cs
index 09b048491..040c564bd 100644
--- a/UnitTests/Configuration/SettingsScopeTests.cs
+++ b/UnitTests/Configuration/SettingsScopeTests.cs
@@ -26,7 +26,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.True (ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue is Key);
Assert.True (ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue is bool);
Assert.True (ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue is bool);
- Assert.True (ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue is bool);
+ Assert.True (ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue is bool);
Assert.True (ConfigurationManager.Settings ["Theme"].PropertyValue is string);
Assert.Equal ("Default", ConfigurationManager.Settings ["Theme"].PropertyValue as string);
@@ -45,7 +45,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.PageUp | Key.CtrlMask, (Key)ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue);
Assert.False ((bool)ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue);
Assert.False ((bool)ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue);
- Assert.False ((bool)ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue);
+ Assert.False ((bool)ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue);
// act
ConfigurationManager.Settings ["Application.QuitKey"].PropertyValue = Key.Q;
@@ -53,7 +53,7 @@ namespace Terminal.Gui.ConfigurationTests {
ConfigurationManager.Settings ["Application.AlternateBackwardKey"].PropertyValue = Key.B;
ConfigurationManager.Settings ["Application.UseSystemConsole"].PropertyValue = true;
ConfigurationManager.Settings ["Application.IsMouseDisabled"].PropertyValue = true;
- ConfigurationManager.Settings ["Application.HeightAsBuffer"].PropertyValue = true;
+ ConfigurationManager.Settings ["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Settings.Apply ();
@@ -63,7 +63,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.B, Application.AlternateBackwardKey);
Assert.True (Application.UseSystemConsole);
Assert.True (Application.IsMouseDisabled);
- Assert.True (Application.HeightAsBuffer);
+ Assert.True (Application.EnableConsoleScrolling);
}
[Fact, AutoInitShutdown]
@@ -78,7 +78,7 @@ namespace Terminal.Gui.ConfigurationTests {
updatedSettings["Application.AlternateBackwardKey"].PropertyValue = Key.B;
updatedSettings["Application.UseSystemConsole"].PropertyValue = true;
updatedSettings["Application.IsMouseDisabled"].PropertyValue = true;
- updatedSettings["Application.HeightAsBuffer"].PropertyValue = true;
+ updatedSettings["Application.EnableConsoleScrolling"].PropertyValue = true;
ConfigurationManager.Settings.Update (updatedSettings);
Assert.Equal (Key.End, ConfigurationManager.Settings ["Application.QuitKey"].PropertyValue);
@@ -86,7 +86,7 @@ namespace Terminal.Gui.ConfigurationTests {
Assert.Equal (Key.B, updatedSettings ["Application.AlternateBackwardKey"].PropertyValue);
Assert.True ((bool)updatedSettings ["Application.UseSystemConsole"].PropertyValue);
Assert.True ((bool)updatedSettings ["Application.IsMouseDisabled"].PropertyValue);
- Assert.True ((bool)updatedSettings ["Application.HeightAsBuffer"].PropertyValue);
+ Assert.True ((bool)updatedSettings ["Application.EnableConsoleScrolling"].PropertyValue);
}
}
}
\ No newline at end of file
diff --git a/UnitTests/Core/BorderTests.cs b/UnitTests/Core/BorderTests.cs
index 1b98e579c..db3504aa4 100644
--- a/UnitTests/Core/BorderTests.cs
+++ b/UnitTests/Core/BorderTests.cs
@@ -1,15 +1,19 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Reflection.Emit;
using Xunit;
+using Xunit.Abstractions;
using Rune = System.Rune;
namespace Terminal.Gui.CoreTests {
public class BorderTests {
- [Fact]
- [AutoInitShutdown]
+ readonly ITestOutputHelper output;
+
+ public BorderTests (ITestOutputHelper output)
+ {
+ this.output = output;
+ }
+
+ [Fact, AutoInitShutdown]
public void Constructor_Defaults ()
{
var b = new Border ();
@@ -40,15 +44,10 @@ namespace Terminal.Gui.CoreTests {
Assert.False (b.DrawMarginFrame);
}
- //[Fact]
- //[AutoInitShutdown]
- //public void ActualWidth_ActualHeight ()
- //{
- // var v = new View (new Rect (5, 10, 60, 20), "", new Border ());
-
- // Assert.Equal (60, v.Border.ActualWidth);
- // Assert.Equal (20, v.Border.ActualHeight);
- //}
+ //[Fact, AutoInitShutdown]
+ // public void ActualWidth_ActualHeight ()
+ // {
+ // var v = new View (new Rect (5, 10, 60, 20), "", new Border ());
//[Fact]
//public void ToplevelContainer_LayoutStyle_Computed_Constuctor_ ()
@@ -83,23 +82,12 @@ namespace Terminal.Gui.CoreTests {
// var top = Application.Top;
// var driver = (FakeDriver)Application.Driver;
- // var label = new Label () {
- // X = Pos.Center (),
- // Y = Pos.Center (),
- // Border = new Border () {
- // BorderStyle = BorderStyle.Single,
- // Padding = new Thickness (2),
- // BorderThickness = new Thickness (2),
- // BorderBrush = Color.Red,
- // Background = Color.BrightGreen,
- // Effect3D = true,
- // Effect3DOffset = new Point (2, -3)
- // },
- // ColorScheme = Colors.TopLevel,
- // Text = "This is a test"
- // };
- // label.Border.Child = label;
- // top.Add (label);
+ // [Fact]
+ // [AutoInitShutdown]
+ // public void DrawContent_With_Child_Border ()
+ // {
+ // var top = Application.Top;
+ // var driver = (FakeDriver)Application.Driver;
// top.LayoutSubviews ();
// label.Redraw (label.Bounds);
@@ -243,11 +231,34 @@ namespace Terminal.Gui.CoreTests {
// }
// Assert.Equal ("This is a test", text.Trim ());
- // // Check the upper Effect3D
- // for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y;
- // r < frame.Y - drawMarginFrame - sumThickness.Top; r++) {
- // for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X;
- // c < frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X; c++) {
+ // var color = (Attribute)driver.Contents [r, c, 1];
+ // var rune = (Rune)driver.Contents [r, c, 0];
+ // if (r == frame.Y - drawMarginFrame || r == frame.Bottom + drawMarginFrame - 1
+ // || c == frame.X - drawMarginFrame || c == frame.Right + drawMarginFrame - 1) {
+ // Assert.Equal (Color.BrightGreen, color.Background);
+ // } else {
+ // Assert.Equal (Color.Black, color.Background);
+ // }
+ // if (c == frame.X - drawMarginFrame && r == frame.Y - drawMarginFrame) {
+ // Assert.Equal (uLCorner, rune);
+ // } else if (c == frame.Right && r == frame.Y - drawMarginFrame) {
+ // Assert.Equal (uRCorner, rune);
+ // } else if (c == frame.X - drawMarginFrame && r == frame.Bottom) {
+ // Assert.Equal (lLCorner, rune);
+ // } else if (c == frame.Right && r == frame.Bottom) {
+ // Assert.Equal (lRCorner, rune);
+ // } else if (c >= frame.X && (r == frame.Y - drawMarginFrame
+ // || r == frame.Bottom)) {
+ // Assert.Equal (hLine, rune);
+ // } else if ((c == frame.X - drawMarginFrame || c == frame.Right)
+ // && r >= frame.Y && r <= frame.Bottom - drawMarginFrame) {
+ // Assert.Equal (vLine, rune);
+ // } else {
+ // text += rune.ToString ();
+ // }
+ // }
+ // }
+ // Assert.Equal ("This is a test", text.Trim ());
// var color = (Attribute)driver.Contents [r, c, 1];
// Assert.Equal (Color.DarkGray, color.Background);
@@ -305,27 +316,12 @@ namespace Terminal.Gui.CoreTests {
// var top = Application.Top;
// var driver = (FakeDriver)Application.Driver;
- // var frameView = new FrameView () {
- // X = Pos.Center (),
- // Y = Pos.Center (),
- // Width = 24,
- // Height = 13,
- // Border = new Border () {
- // BorderStyle = BorderStyle.Single,
- // Padding = new Thickness (2),
- // BorderThickness = new Thickness (2),
- // BorderBrush = Color.Red,
- // Background = Color.BrightGreen,
- // Effect3D = true,
- // Effect3DOffset = new Point (2, -3)
- // }
- // };
- // frameView.Add (new Label () {
- // ColorScheme = Colors.TopLevel,
- // Text = "This is a test"
- // });
- // //frameView.Border.Child = frameView;
- // top.Add (frameView);
+ // [Fact]
+ // [AutoInitShutdown]
+ // public void DrawContent_With_Parent_Border ()
+ // {
+ // var top = Application.Top;
+ // var driver = (FakeDriver)Application.Driver;
// top.LayoutSubviews ();
// frameView.Redraw (frameView.Bounds);
@@ -481,13 +477,40 @@ namespace Terminal.Gui.CoreTests {
// //}
// //Assert.Equal ("This is a test", text.Trim ());
- // // TODO: Re-enable 3deffect
-
- // //// Check the upper Effect3D
- // //for (int r = frame.Y + effect3DOffset.Y;
- // // r < frame.Y; r++) {
- // // for (int c = frame.X + effect3DOffset.X;
- // // c < frame.Right + effect3DOffset.X; c++) {
+ // var color = (Attribute)driver.Contents [r, c, 1];
+ // var rune = (Rune)driver.Contents [r, c, 0];
+ // 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
+ // && r == frame.Y + sumThickness.Top) {
+ // Assert.Equal (uRCorner, rune);
+ // } else if (c == frame.X + sumThickness.Left
+ // && r == frame.Bottom - drawMarginFrame - sumThickness.Bottom) {
+ // Assert.Equal (lLCorner, rune);
+ // } else if (c == frame.Right - drawMarginFrame - sumThickness.Right
+ // && r == frame.Bottom - drawMarginFrame - sumThickness.Bottom) {
+ // Assert.Equal (lRCorner, rune);
+ // } else if (c > frame.X + sumThickness.Left
+ // && (r == frame.Y + sumThickness.Top
+ // || r == frame.Bottom - drawMarginFrame - sumThickness.Bottom)) {
+ // Assert.Equal (hLine, rune);
+ // } else if ((c == frame.X + sumThickness.Left
+ // || c == frame.Right - drawMarginFrame - sumThickness.Right)
+ // && r >= frame.Y + drawMarginFrame + sumThickness.Top) {
+ // Assert.Equal (vLine, rune);
+ // } else {
+ // text += rune.ToString ();
+ // }
+ // }
+ // }
+ // Assert.Equal ("This is a test", text.Trim ());
+
+ // // Check the upper Effect3D
+ // for (int r = frame.Y + effect3DOffset.Y;
+ // r < frame.Y; r++) {
+ // for (int c = frame.X + effect3DOffset.X;
+ // c < frame.Right + effect3DOffset.X; c++) {
// // var color = (Attribute)driver.Contents [r, c, 1];
// // Assert.Equal (Color.DarkGray, color.Background);
@@ -540,8 +563,7 @@ namespace Terminal.Gui.CoreTests {
// //}
//}
- [Fact]
- [AutoInitShutdown]
+ [Fact, AutoInitShutdown]
public void BorderOnControlWithNoChildren ()
{
var label = new TextField ("Loading...") {
@@ -557,5 +579,57 @@ namespace Terminal.Gui.CoreTests {
Assert.Null (Record.Exception (() => label.Redraw (label.Bounds)));
}
+
+ [Fact, AutoInitShutdown]
+ public void BorderStyle_And_DrawMarginFrame_Gets_Sets ()
+ {
+ var lblTop = new Label ("At 0,0");
+ var lblFrame = new Label ("Centered") { X = Pos.Center (), Y = Pos.Center () };
+ var frame = new FrameView () { Y = 1, Width = 20, Height = 3 };
+ var lblFill = new Label () { Width = Dim.Fill(),Height = Dim.Fill(), Visible = false };
+ var fillText = new System.Text.StringBuilder ();
+ for (int i = 0; i < frame.Bounds.Height; i++) {
+ if (i > 0) {
+ fillText.AppendLine ("");
+ }
+ for (int j = 0; j < frame.Bounds.Width; j++) {
+ fillText.Append ("█");
+ }
+ }
+ lblFill.Text = fillText.ToString ();
+ frame.Add (lblFill, lblFrame);
+ var lblBottom = new Label ("At 0,4") { Y = 4 };
+ Application.Top.Add (lblTop, frame, lblBottom);
+ Application.Begin (Application.Top);
+
+ Assert.Equal (BorderStyle.Single, frame.Border.BorderStyle);
+ Assert.True (frame.Border.DrawMarginFrame);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0
+┌──────────────────┐
+│ Centered │
+└──────────────────┘
+At 0,4 ", output);
+
+ frame.Border.BorderStyle = BorderStyle.None;
+ Application.Refresh ();
+ Assert.True (frame.Border.DrawMarginFrame);
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0
+
+ Centered
+
+At 0,4 ", output);
+
+ frame.Border.DrawMarginFrame = false;
+ lblFill.Visible = true;
+ Application.Refresh ();
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+At 0,0
+████████████████████
+██████Centered██████
+████████████████████
+At 0,4 ", output);
+ }
}
}
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/Core/LayoutTests.cs b/UnitTests/Core/LayoutTests.cs
index cf6cffe6c..68ea9577f 100644
--- a/UnitTests/Core/LayoutTests.cs
+++ b/UnitTests/Core/LayoutTests.cs
@@ -328,12 +328,15 @@ 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=28,Height=2}", label.Bounds.ToString ());
@@ -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,14 @@ Y
Assert.Equal ("123 ", GetContents ());
lbl.Text = "12";
-
- lbl.SuperView.Redraw (lbl.SuperView.NeedDisplay);
-
+ // 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, 0, 0), lbl.SuperView.NeedDisplay);
+ Assert.True (lbl.SuperView.LayoutNeeded);
+ 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 13fd93e88..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
@@ -2857,5 +2854,104 @@ At 0,0
222";
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
+
+ [Fact]
+ [AutoInitShutdown]
+ public void Frame_Set_After_Initialze_Update_NeededDisplay ()
+ {
+ var frame = new FrameView ();
+
+ var label = new Label ("This should be the first line.") {
+ TextAlignment = Terminal.Gui.TextAlignment.Centered,
+ ColorScheme = Colors.Menu,
+ Width = Dim.Fill (),
+ X = Pos.Center (),
+ Y = Pos.Center () - 2 // center minus 2 minus two lines top and bottom borders equal to zero (4-2-2=0)
+ };
+
+ var button = new Button ("Press me!") {
+ X = Pos.Center (),
+ Y = Pos.Center ()
+ };
+
+ frame.Add (label, button);
+
+ frame.X = Pos.Center ();
+ frame.Y = Pos.Center ();
+ frame.Width = 40;
+ frame.Height = 8;
+
+ var top = Application.Top;
+
+ top.Add (frame);
+
+ Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
+ Assert.Equal (new Rect (0, 0, 40, 8), frame.Frame);
+ Assert.Equal (new Rect (1, 1, 0, 0), frame.Subviews [0].Frame);
+ Assert.Equal ("ContentView()({X=1,Y=1,Width=0,Height=0})", frame.Subviews [0].ToString ());
+ Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+ frame.Frame.Left, frame.Frame.Top,
+ frame.Frame.Right, frame.Frame.Bottom));
+ Assert.Equal (new Rect (0, 0, 30, 1), label.Frame);
+ Assert.Equal (new Rect (0, 0, 13, 1), button.Frame);
+
+ Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+ Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+ Assert.Equal (Rect.Empty, frame.Subviews [0].NeedDisplay);
+ Assert.Equal (new Rect (0, 0, 40, 8), new Rect (
+ frame.NeedDisplay.Left, frame.NeedDisplay.Top,
+ frame.NeedDisplay.Right, frame.NeedDisplay.Bottom));
+ Assert.Equal (new Rect (0, 0, 30, 1), label.NeedDisplay);
+ Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+
+ top.LayoutComplete += e => {
+ Assert.Equal (new Rect (0, 0, 80, 25), top.NeedDisplay);
+ };
+
+ frame.LayoutComplete += e => {
+ Assert.Equal (new Rect (0, 0, 40, 8), frame.NeedDisplay);
+ };
+
+ frame.Subviews [0].LayoutComplete += e => {
+ if (top.IsLoaded) {
+ Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay);
+ } else {
+ Assert.Equal (new Rect (0, 0, 38, 6), frame.Subviews [0].NeedDisplay);
+ }
+ };
+
+ label.LayoutComplete += e => {
+ Assert.Equal (new Rect (0, 0, 38, 1), label.NeedDisplay);
+ };
+
+ button.LayoutComplete += e => {
+ Assert.Equal (new Rect (0, 0, 13, 1), button.NeedDisplay);
+ };
+
+ Application.Begin (top);
+
+ Assert.True (label.AutoSize);
+ Assert.Equal (new Rect (0, 0, 80, 25), top.Frame);
+ Assert.Equal (new Rect (20, 8, 40, 8), frame.Frame);
+ Assert.Equal (new Rect (1, 1, 38, 6), frame.Subviews [0].Frame);
+ Assert.Equal ("ContentView()({X=1,Y=1,Width=38,Height=6})", frame.Subviews [0].ToString ());
+ Assert.Equal (new Rect (20, 8, 60, 16), new Rect (
+ frame.Frame.Left, frame.Frame.Top,
+ frame.Frame.Right, frame.Frame.Bottom));
+ Assert.Equal (new Rect (0, 0, 38, 1), label.Frame);
+ Assert.Equal (new Rect (12, 2, 13, 1), button.Frame);
+ var expected = @"
+ ┌──────────────────────────────────────┐
+ │ This should be the first line. │
+ │ │
+ │ [ Press me! ] │
+ │ │
+ │ │
+ │ │
+ └──────────────────────────────────────┘
+";
+
+ TestHelpers.AssertDriverContentsWithFrameAre (expected, output);
+ }
}
}
diff --git a/UnitTests/Drivers/ClipboardTests.cs b/UnitTests/Drivers/ClipboardTests.cs
index 03e023ea1..90f30bdbd 100644
--- a/UnitTests/Drivers/ClipboardTests.cs
+++ b/UnitTests/Drivers/ClipboardTests.cs
@@ -102,8 +102,8 @@ namespace Terminal.Gui.DriverTests {
[Fact, AutoInitShutdown (useFakeClipboard: false)]
public void IsSupported_Get ()
{
- if (Clipboard.IsSupported) Assert.True (Clipboard.IsSupported);
-else Assert.False (Clipboard.IsSupported);
+ if (Clipboard.IsSupported) Assert.True (Clipboard.IsSupported);
+ else Assert.False (Clipboard.IsSupported);
}
[Fact, AutoInitShutdown (useFakeClipboard: false)]
@@ -129,18 +129,19 @@ else Assert.False (Clipboard.IsSupported);
public void TrySetClipboardData_Sets_The_OS_Clipboard ()
{
var clipText = "The TrySetClipboardData_Sets_The_OS_Clipboard unit test pasted this to the OS clipboard.";
- if (Clipboard.IsSupported) Assert.True (Clipboard.TrySetClipboardData (clipText));
-else Assert.False (Clipboard.TrySetClipboardData (clipText));
+ if (Clipboard.IsSupported) Assert.True (Clipboard.TrySetClipboardData (clipText));
+ else Assert.False (Clipboard.TrySetClipboardData (clipText));
Application.Iteration += () => Application.RequestStop ();
Application.Run ();
- if (Clipboard.IsSupported) Assert.Equal (clipText, Clipboard.Contents);
-else Assert.NotEqual (clipText, Clipboard.Contents);
+ if (Clipboard.IsSupported) Assert.Equal (clipText, Clipboard.Contents);
+ else Assert.NotEqual (clipText, Clipboard.Contents);
}
-
+ // Disabling this test for now because it is not reliable
+#if false
[Fact, AutoInitShutdown (useFakeClipboard: false)]
public void Contents_Copies_From_OS_Clipboard ()
{
@@ -262,12 +263,13 @@ else Assert.NotEqual (clipText, Clipboard.Contents);
Application.RequestStop ();
};
-
+
Application.Run ();
if (!failed) Assert.Equal (clipText, clipReadText.TrimEnd ());
}
+#endif
bool Is_WSL_Platform ()
{
@@ -284,5 +286,6 @@ else Assert.NotEqual (clipText, Clipboard.Contents);
return false;
}
}
+
}
}
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/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
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 1be120dea..a6f803af0 100644
--- a/UnitTests/TopLevels/ToplevelTests.cs
+++ b/UnitTests/TopLevels/ToplevelTests.cs
@@ -149,7 +149,9 @@ namespace Terminal.Gui.TopLevelTests {
[AutoInitShutdown]
public void Internal_Tests ()
{
+ Toplevel.dragPosition = null; // dragPosition is `static` and must be reset for each instance or unit tests will fail?
var top = new Toplevel ();
+
var eventInvoked = "";
top.ChildUnloaded += (e) => eventInvoked = "ChildUnloaded";
@@ -1031,5 +1033,53 @@ namespace Terminal.Gui.TopLevelTests {
Application.Driver.GetCursorVisibility (out cursor);
Assert.Equal (CursorVisibility.Invisible, cursor);
}
+
+ [Fact, AutoInitShutdown]
+ public void IsLoaded_Application_Begin ()
+ {
+ var top = Application.Top;
+ Assert.False (top.IsLoaded);
+
+ Application.Begin (top);
+ Assert.True (top.IsLoaded);
+ }
+
+ [Fact, AutoInitShutdown]
+ public void IsLoaded_With_Sub_Toplevel_Application_Begin_NeedDisplay ()
+ {
+ var top = Application.Top;
+ var subTop = new Toplevel ();
+ var view = new View (new Rect (0, 0, 20, 10));
+ subTop.Add (view);
+ top.Add (subTop);
+
+ Assert.False (top.IsLoaded);
+ Assert.False (subTop.IsLoaded);
+ Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+ Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+
+ view.LayoutStarted += view_LayoutStarted;
+
+ void view_LayoutStarted (View.LayoutEventArgs e)
+ {
+ Assert.Equal (new Rect (0, 0, 20, 10), view.NeedDisplay);
+ view.LayoutStarted -= view_LayoutStarted;
+ }
+
+ Application.Begin (top);
+
+ Assert.True (top.IsLoaded);
+ Assert.True (subTop.IsLoaded);
+ Assert.Equal (new Rect (0, 0, 20, 10), view.Frame);
+
+ view.Frame = new Rect (1, 3, 10, 5);
+ Assert.Equal (new Rect (1, 3, 10, 5), view.Frame);
+ 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 (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 5a98d5db9..e04a4b818 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
@@ -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 ();
@@ -487,13 +488,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,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=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 ("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 (19, v6.Frame.Width); // 99*20%=19
- Assert.Equal (38, v6.Frame.Height); // 198-7*20=38
+ Assert.Equal (38, v6.Frame.Height); // 198-7*20=18
};
Application.Iteration += () => Application.RequestStop ();
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index ae3766244..1d5885e17 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -21,8 +21,8 @@
TRACE;DEBUG_IDISPOSABLE
-
-
+
+
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 ());
diff --git a/UnitTests/Views/ScrollViewTests.cs b/UnitTests/Views/ScrollViewTests.cs
index eb14fe339..f441e3c86 100644
--- a/UnitTests/Views/ScrollViewTests.cs
+++ b/UnitTests/Views/ScrollViewTests.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using NStack;
using Xunit;
using Xunit.Abstractions;
@@ -280,5 +276,227 @@ namespace Terminal.Gui.ViewTests {
◄░░░├─┤░►
", output);
}
+
+ [Fact, AutoInitShutdown]
+ public void Frame_And_Labels_Does_Not_Overspill_ScrollView ()
+ {
+ var sv = new ScrollView {
+ X = 3,
+ Y = 3,
+ Width = 10,
+ Height = 10,
+ ContentSize = new Size (50, 50)
+ };
+ for (int i = 0; i < 8; i++) {
+ sv.Add (new CustomButton ("█", $"Button {i}", 20, 3) { Y = i * 3 });
+ }
+ Application.Top.Add (sv);
+ Application.Begin (Application.Top);
+
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+ █████████▲
+ ██████But┬
+ █████████┴
+ ┌────────░
+ │ But░
+ └────────░
+ ┌────────░
+ │ But░
+ └────────▼
+ ◄├┤░░░░░► ", output);
+
+ sv.ContentOffset = new Point (5, 5);
+ Application.Refresh ();
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+ ─────────▲
+ ─────────┬
+ Button 2│
+ ─────────┴
+ ─────────░
+ Button 3░
+ ─────────░
+ ─────────░
+ Button 4▼
+ ◄├─┤░░░░► ", output);
+ }
+
+ private class CustomButton : FrameView {
+ private Label labelFill;
+ private Label labelText;
+
+ public CustomButton (string fill, ustring text, int width, int height)
+ {
+ Width = width;
+ Height = height;
+ labelFill = new Label () { AutoSize = false, Width = Dim.Fill (), Height = Dim.Fill (), Visible = 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);
+ }
+ }
+ labelFill.Text = fillText.ToString ();
+ labelText = new Label (text) { X = Pos.Center (), Y = Pos.Center () };
+ Add (labelFill, labelText);
+ CanFocus = true;
+ }
+
+ public override bool OnEnter (View view)
+ {
+ Border.BorderStyle = BorderStyle.None;
+ Border.DrawMarginFrame = false;
+ labelFill.Visible = true;
+ view = this;
+ return base.OnEnter (view);
+ }
+
+ public override bool OnLeave (View view)
+ {
+ Border.BorderStyle = BorderStyle.Single;
+ Border.DrawMarginFrame = true;
+ labelFill.Visible = false;
+ if (view == null)
+ view = this;
+ return base.OnLeave (view);
+ }
+ }
+
+ [Fact, AutoInitShutdown]
+ public void Clear_Window_Inside_ScrollView ()
+ {
+ var topLabel = new Label ("At 15,0") { X = 15 };
+ var sv = new ScrollView {
+ X = 3,
+ Y = 3,
+ Width = 10,
+ Height = 10,
+ ContentSize = new Size (23, 23),
+ KeepContentAlwaysInViewport = false
+ };
+ var bottomLabel = new Label ("At 15,15") { X = 15, Y = 15 };
+ Application.Top.Add (topLabel, sv, bottomLabel);
+ Application.Begin (Application.Top);
+
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+ At 15,0
+
+
+ ▲
+ ┬
+ ┴
+ ░
+ ░
+ ░
+ ░
+ ░
+ ▼
+ ◄├┤░░░░░►
+
+
+ At 15,15", output);
+
+ var attributes = new Attribute [] {
+ Colors.TopLevel.Normal,
+ Colors.TopLevel.Focus,
+ Colors.Base.Normal
+ };
+
+ TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00011111111110000000000
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000", attributes);
+
+ sv.Add (new Window ("1") { X = 3, Y = 3, Width = 20, Height = 20 });
+ Application.Refresh ();
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+ At 15,0
+
+
+ ▲
+ ┬
+ ┴
+ ┌ 1 ──░
+ │ ░
+ │ ░
+ │ ░
+ │ ░
+ │ ▼
+ ◄├┤░░░░░►
+
+
+ At 15,15", output);
+
+ TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000022222210000000000
+00000022222210000000000
+00000022222210000000000
+00000022222210000000000
+00000022222210000000000
+00000022222210000000000
+00011111111110000000000
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000", attributes);
+
+ sv.ContentOffset = new Point (20, 20);
+ Application.Refresh ();
+ TestHelpers.AssertDriverContentsWithFrameAre (@"
+ At 15,0
+
+
+ │ ▲
+ │ ░
+ ──┘ ░
+ ░
+ ░
+ ┬
+ │
+ ┴
+ ▼
+ ◄░░░░├─┤►
+
+
+ At 15,15", output);
+
+ TestHelpers.AssertDriverColorsAre (@"
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000
+00022200000010000000000
+00022200000010000000000
+00022200000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00000000000010000000000
+00011111111110000000000
+00000000000000000000000
+00000000000000000000000
+00000000000000000000000", attributes);
+ }
}
}
diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs
index bb08a22ff..2bcc46d95 100644
--- a/UnitTests/Views/TableViewTests.cs
+++ b/UnitTests/Views/TableViewTests.cs
@@ -321,6 +321,8 @@ namespace Terminal.Gui.ViewTests {
Bounds = new Rect (0, 0, 10, 5)
};
+ tableView.ChangeSelectionToEndOfTable(false);
+
// select the last row
tableView.MultiSelectedRegions.Clear ();
tableView.MultiSelectedRegions.Push (new TableView.TableSelection (new Point (0, 3), new Rect (0, 3, 4, 1)));
@@ -1506,6 +1508,185 @@ namespace Terminal.Gui.ViewTests {
Assert.DoesNotContain (new Point (1, 0), tableView.GetAllSelectedCells ());
}
+
+ [Fact, AutoInitShutdown]
+ public void TestToggleCells_MultiSelectOn ()
+ {
+ // 2 row table
+ var tableView = GetABCDEFTableView (out var dt);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+
+ tableView.MultiSelect = true;
+ tableView.AddKeyBinding(Key.Space,Command.ToggleChecked);
+
+ var selectedCell = tableView.GetAllSelectedCells().Single();
+ Assert.Equal(0,selectedCell.X);
+ Assert.Equal(0,selectedCell.Y);
+
+ // Go Right
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorRight });
+
+ selectedCell = tableView.GetAllSelectedCells().Single();
+ Assert.Equal(1,selectedCell.X);
+ Assert.Equal(0,selectedCell.Y);
+
+ // Toggle Select
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+ var m = tableView.MultiSelectedRegions.Single();
+ Assert.True(m.IsToggled);
+ Assert.Equal(1,m.Origin.X);
+ Assert.Equal(0,m.Origin.Y);
+ selectedCell = tableView.GetAllSelectedCells().Single();
+ Assert.Equal(1,selectedCell.X);
+ Assert.Equal(0,selectedCell.Y);
+
+ // Go Left
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorLeft });
+
+ // Both Toggled and Moved to should be selected
+ Assert.Equal(2,tableView.GetAllSelectedCells().Count());
+ var s1 = tableView.GetAllSelectedCells().ElementAt(0);
+ var s2 = tableView.GetAllSelectedCells().ElementAt(1);
+ Assert.Equal(1,s1.X);
+ Assert.Equal(0,s1.Y);
+ Assert.Equal(0,s2.X);
+ Assert.Equal(0,s2.Y);
+
+ // Go Down
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorDown });
+
+ // Both Toggled and Moved to should be selected but not 0,0
+ // which we moved down from
+ Assert.Equal(2,tableView.GetAllSelectedCells().Count());
+ s1 = tableView.GetAllSelectedCells().ElementAt(0);
+ s2 = tableView.GetAllSelectedCells().ElementAt(1);
+ Assert.Equal(1,s1.X);
+ Assert.Equal(0,s1.Y);
+ Assert.Equal(0,s2.X);
+ Assert.Equal(1,s2.Y);
+
+
+ // Go back to the toggled cell
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorRight});
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorUp});
+
+ // Toggle off
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+
+ // Go Left
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorLeft});
+
+ selectedCell = tableView.GetAllSelectedCells().Single();
+ Assert.Equal(0,selectedCell.X);
+ Assert.Equal(0,selectedCell.Y);
+ }
+
+ [Fact, AutoInitShutdown]
+ public void TestToggleCells_MultiSelectOn_FullRowSelect ()
+ {
+ // 2 row table
+ var tableView = GetABCDEFTableView (out var dt);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ tableView.FullRowSelect = true;
+ tableView.MultiSelect = true;
+ tableView.AddKeyBinding(Key.Space,Command.ToggleChecked);
+
+ // Toggle Select Cell 0,0
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+
+ // Go Down
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorDown });
+
+ var m = tableView.MultiSelectedRegions.Single();
+ Assert.True(m.IsToggled);
+ Assert.Equal(0,m.Origin.X);
+ Assert.Equal(0,m.Origin.Y);
+
+ //First row toggled and Second row active = 12 selected cells
+ Assert.Equal(12,tableView.GetAllSelectedCells().Count());
+
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorRight });
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorUp });
+
+ Assert.Single(tableView.MultiSelectedRegions.Where(r=>r.IsToggled));
+
+ // Can untoggle at 1,0 even though 0,0 was initial toggle because FullRowSelect is on
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+
+ Assert.Empty(tableView.MultiSelectedRegions.Where(r=>r.IsToggled));
+
+ }
+
+
+ [Fact, AutoInitShutdown]
+ public void TestToggleCells_MultiSelectOn_SquareSelectToggled ()
+ {
+ // 3 row table
+ var tableView = GetABCDEFTableView (out var dt);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ tableView.MultiSelect = true;
+ tableView.AddKeyBinding(Key.Space,Command.ToggleChecked);
+
+ // Make a square selection
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorDown});
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorRight});
+
+ Assert.Equal(4,tableView.GetAllSelectedCells().Count());
+
+ // Toggle the square selected region on
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+
+ // Go Right
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorRight });
+
+ //Toggled on square + the active cell (x=2,y=1)
+ Assert.Equal(5,tableView.GetAllSelectedCells().Count());
+ Assert.Equal(2,tableView.SelectedColumn);
+ Assert.Equal(1,tableView.SelectedRow);
+
+ // Untoggle the rectangular region by hitting toggle in
+ // any cell in that rect
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorUp });
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorLeft });
+
+ Assert.Equal(4,tableView.GetAllSelectedCells().Count());
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space });
+ Assert.Equal(1,tableView.GetAllSelectedCells().Count());
+ }
+
+
+
+ [Fact, AutoInitShutdown]
+ public void TestToggleCells_MultiSelectOn_Two_SquareSelects_BothToggled ()
+ {
+ // 6 row table
+ var tableView = GetABCDEFTableView (out var dt);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ dt.Rows.Add (1, 2, 3, 4, 5, 6);
+ tableView.MultiSelect = true;
+ tableView.AddKeyBinding(Key.Space,Command.ToggleChecked);
+
+ // Make first square selection (0,0 to 1,1)
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorDown});
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorRight});
+ tableView.ProcessKey (new KeyEvent { Key = Key.Space});
+ Assert.Equal(4,tableView.GetAllSelectedCells().Count());
+
+ // Make second square selection leaving 1 unselected line between them
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorLeft });
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorDown });
+ tableView.ProcessKey (new KeyEvent { Key = Key.CursorDown });
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorDown});
+ tableView.ProcessKey (new KeyEvent { Key = Key.ShiftMask | Key.CursorRight});
+
+ // 2 square selections
+ Assert.Equal(8,tableView.GetAllSelectedCells().Count());
+ }
+
[Theory, AutoInitShutdown]
[InlineData(new object[] { true,true })]
diff --git a/UnitTests/Views/TileViewTests.cs b/UnitTests/Views/TileViewTests.cs
index 0155d3aba..d3e97acec 100644
--- a/UnitTests/Views/TileViewTests.cs
+++ b/UnitTests/Views/TileViewTests.cs
@@ -1,6 +1,6 @@
using System;
+using System.ComponentModel;
using System.Linq;
-using Terminal.Gui;
using Terminal.Gui.Graphs;
using Xunit;
using Xunit.Abstractions;
@@ -60,7 +60,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_Focused ()
{
var tileView = Get11By3TileView (out var line);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Redraw (tileView.Bounds);
@@ -100,7 +100,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_Focused_WithBorder ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Redraw (tileView.Bounds);
@@ -141,9 +141,10 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_Focused_50PercentSplit ()
{
var tileView = Get11By3TileView (out var line);
- SetInputFocusLine (tileView);
tileView.SetSplitterPos (0, Pos.Percent (50));
Assert.IsType (tileView.SplitterDistances.ElementAt (0));
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
+
tileView.Redraw (tileView.Bounds);
string looksLike =
@@ -209,7 +210,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_View1MinSize_Absolute ()
{
var tileView = Get11By3TileView (out var line);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Tiles.ElementAt (0).MinSize = 6;
// distance is too small (below 6)
@@ -254,7 +255,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_View1MinSize_Absolute_WithBorder ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Tiles.ElementAt (0).MinSize = 5;
// distance is too small (below 5)
@@ -298,7 +299,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_View2MinSize_Absolute ()
{
var tileView = Get11By3TileView (out var line);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Tiles.ElementAt (1).MinSize = 6;
// distance leaves too little space for view2 (less than 6 would remain)
@@ -342,7 +343,7 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Vertical_View2MinSize_Absolute_WithBorder ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Tiles.ElementAt (1).MinSize = 5;
// distance leaves too little space for view2 (less than 5 would remain)
@@ -386,8 +387,6 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_InsertPanelAtStart ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
-
tileView.InsertTile (0);
tileView.Redraw (tileView.Bounds);
@@ -405,8 +404,6 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_InsertPanelMiddle ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
-
tileView.InsertTile (1);
tileView.Redraw (tileView.Bounds);
@@ -424,8 +421,6 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_InsertPanelAtEnd ()
{
var tileView = Get11By3TileView (out var line, true);
- SetInputFocusLine (tileView);
-
tileView.InsertTile (2);
tileView.Redraw (tileView.Bounds);
@@ -445,7 +440,9 @@ namespace Terminal.Gui.ViewTests {
var tileView = Get11By3TileView (out var line);
tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
- SetInputFocusLine (tileView);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
+
+ Assert.True (line.HasFocus);
tileView.Redraw (tileView.Bounds);
@@ -485,9 +482,9 @@ namespace Terminal.Gui.ViewTests {
public void TestTileView_Horizontal_View1MinSize_Absolute ()
{
var tileView = Get11By3TileView (out var line);
+ tileView.ProcessHotKey (new KeyEvent (tileView.ToggleResizable, new KeyModifiers ()));
tileView.Orientation = Terminal.Gui.Graphs.Orientation.Horizontal;
- SetInputFocusLine (tileView);
tileView.Tiles.ElementAt (0).MinSize = 1;
// 0 should not be allowed because it brings us below minimum size of View1
@@ -2045,6 +2042,45 @@ namespace Terminal.Gui.ViewTests {
}
+ [Fact, AutoInitShutdown]
+ public void Test_SplitTop_WholeBottom()
+ {
+ var tileView = new TileView (2) {
+ Width = 20,
+ Height = 10,
+ Orientation = Orientation.Horizontal,
+ };
+ tileView.Border.BorderStyle = BorderStyle.Single;
+
+ Assert.True (tileView.TrySplitTile (0,2,out TileView top));
+
+ top.Tiles.ElementAt (0).ContentView.Add (new Label ("bleh"));
+ top.Tiles.ElementAt (1).ContentView.Add (new Label ("blah"));
+
+ tileView.Tiles.ElementAt (1).ContentView.Add (new Label ("Hello"));
+ tileView.ColorScheme = new ColorScheme ();
+ top.ColorScheme = new ColorScheme ();
+ tileView.LayoutSubviews ();
+
+ tileView.Redraw (tileView.Bounds);
+
+ string looksLike =
+@"
+┌─────────┬────────┐
+│bleh │blah │
+│ │ │
+│ │ │
+│ │ │
+├─────────┴────────┤
+│Hello │
+│ │
+│ │
+└──────────────────┘";
+
+ TestHelpers.AssertDriverContentsAre (looksLike, output);
+
+ }
+
[Fact, AutoInitShutdown]
public void TestNestedContainer3RightAnd1Down_TitleDoesNotOverspill()
{
@@ -2094,12 +2130,10 @@ namespace Terminal.Gui.ViewTests {
TestHelpers.AssertDriverContentsAre (looksLike, output);
}
-
-
- [Fact,AutoInitShutdown]
+ [Fact, AutoInitShutdown]
public void TestDisposal_NoEarlyDisposalsOfUsersViews_DuringRebuildForTileCount ()
{
- var tv = GetTileView (20,10);
+ var tv = GetTileView (20, 10);
var myReusableView = new DisposeCounter ();
@@ -2113,10 +2147,10 @@ namespace Terminal.Gui.ViewTests {
// but I still want my view in the first tile
tv.Tiles.ElementAt (0).ContentView.Add (myReusableView);
Assert.Multiple (
- ()=>Assert.Equal (0, myReusableView.DisposalCount)
- ,()=> {
+ () => Assert.Equal (0, myReusableView.DisposalCount)
+ , () => {
tv.Dispose ();
- Assert.Equal (1, myReusableView.DisposalCount);
+ Assert.Equal (1, myReusableView.DisposalCount);
});
}
[Fact, AutoInitShutdown]
@@ -2140,15 +2174,13 @@ namespace Terminal.Gui.ViewTests {
() => Assert.Equal (0, myReusableView.DisposalCount)
, () => {
tv.Dispose ();
-
- // TODO seems to be double disposed ?!
- Assert.True (myReusableView.DisposalCount >= 1);
+ Assert.True (myReusableView.DisposalCount>=1);
});
}
[Theory, AutoInitShutdown]
- [InlineData(0)]
+ [InlineData (0)]
[InlineData (1)]
- public void TestDisposal_NoEarlyDisposalsOfUsersViews_DuringRemoveTile(int idx)
+ public void TestDisposal_NoEarlyDisposalsOfUsersViews_DuringRemoveTile (int idx)
{
var tv = GetTileView (20, 10);
@@ -2166,14 +2198,10 @@ namespace Terminal.Gui.ViewTests {
() => Assert.Equal (0, myReusableView.DisposalCount)
, () => {
tv.Dispose ();
-
- // TODO seems to be double disposed ?!
Assert.True (myReusableView.DisposalCount >= 1);
});
}
-
- private class DisposeCounter : View
- {
+ private class DisposeCounter : View {
public int DisposalCount;
protected override void Dispose (bool disposing)
{
@@ -2255,13 +2283,6 @@ namespace Terminal.Gui.ViewTests {
return tileView.Subviews.OfType ().Single ();
}
- private void SetInputFocusLine (TileView tileView)
- {
- var line = GetLine (tileView);
- line.SetFocus ();
- Assert.True (line.HasFocus);
- }
-
private TileView Get5x1TilesView (bool border = true)
{