diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 7d2b0b422..c915db6e4 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -62,40 +62,61 @@ namespace Terminal.Gui { Curses.move (crow, ccol); needMove = false; } - if (runeWidth < 2 && ccol > 0 - && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { + if (runeWidth == 0 && ccol > 0) { + var r = contents [crow, ccol - 1, 0]; + var s = new string (new char [] { (char)r, (char)rune }); + string sn; + if (!s.IsNormalized ()) { + sn = s.Normalize (); + } else { + sn = s; + } + var c = sn [0]; + Curses.mvaddch (crow, ccol - 1, (int)(uint)c); + contents [crow, ccol - 1, 0] = c; + contents [crow, ccol - 1, 1] = CurrentAttribute; + contents [crow, ccol - 1, 2] = 1; - var curAtttib = CurrentAttribute; - Curses.attrset (contents [crow, ccol - 1, 1]); - Curses.mvaddch (crow, ccol - 1, (int)(uint)' '); - contents [crow, ccol - 1, 0] = (int)(uint)' '; - Curses.move (crow, ccol); - Curses.attrset (curAtttib); - - } else if (runeWidth < 2 && ccol <= Clip.Right - 1 - && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { - - var curAtttib = CurrentAttribute; - Curses.attrset (contents [crow, ccol + 1, 1]); - Curses.mvaddch (crow, ccol + 1, (int)(uint)' '); - contents [crow, ccol + 1, 0] = (int)(uint)' '; - Curses.move (crow, ccol); - Curses.attrset (curAtttib); - - } - if (runeWidth > 1 && ccol == Clip.Right - 1) { - Curses.addch ((int)(uint)' '); - contents [crow, ccol, 0] = (int)(uint)' '; } else { - Curses.addch ((int)(uint)rune); - contents [crow, ccol, 0] = (int)(uint)rune; - } - contents [crow, ccol, 1] = CurrentAttribute; - contents [crow, ccol, 2] = 1; - } else - needMove = true; + if (runeWidth < 2 && ccol > 0 + && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { - ccol++; + var curAtttib = CurrentAttribute; + Curses.attrset (contents [crow, ccol - 1, 1]); + Curses.mvaddch (crow, ccol - 1, (int)(uint)' '); + contents [crow, ccol - 1, 0] = (int)(uint)' '; + Curses.move (crow, ccol); + Curses.attrset (curAtttib); + + } else if (runeWidth < 2 && ccol <= Clip.Right - 1 + && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { + + var curAtttib = CurrentAttribute; + Curses.attrset (contents [crow, ccol + 1, 1]); + Curses.mvaddch (crow, ccol + 1, (int)(uint)' '); + contents [crow, ccol + 1, 0] = (int)(uint)' '; + Curses.move (crow, ccol); + Curses.attrset (curAtttib); + + } + if (runeWidth > 1 && ccol == Clip.Right - 1) { + Curses.addch ((int)(uint)' '); + contents [crow, ccol, 0] = (int)(uint)' '; + } else { + Curses.addch ((int)(uint)rune); + contents [crow, ccol, 0] = (int)(uint)rune; + } + contents [crow, ccol, 1] = CurrentAttribute; + contents [crow, ccol, 2] = 1; + } + } else { + needMove = true; + } + + if (runeWidth < 0 || runeWidth > 0) { + ccol++; + } + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -104,8 +125,9 @@ namespace Terminal.Gui { ccol++; } - if (sync) + if (sync) { UpdateScreen (); + } } public override void AddStr (ustring str) @@ -143,6 +165,19 @@ namespace Terminal.Gui { 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 (); @@ -155,6 +190,8 @@ namespace Terminal.Gui { public Curses.Window window; + //static short last_color_pair = 16; + /// /// Creates a curses color from the provided foreground and background colors /// @@ -180,6 +217,37 @@ namespace Terminal.Gui { return MakeColor ((short)MapColor (fore), (short)MapColor (back)); } + int [,] colorPairs = new int [16, 16]; + + public override void SetColors (ConsoleColor foreground, ConsoleColor background) + { + // BUGBUG: This code is never called ?? See Issue #2300 + int f = (short)foreground; + int b = (short)background; + var v = colorPairs [f, b]; + if ((v & 0x10000) == 0) { + b &= 0x7; + bool bold = (f & 0x8) != 0; + f &= 0x7; + + v = MakeColor ((short)f, (short)b) | (bold ? Curses.A_BOLD : 0); + colorPairs [(int)foreground, (int)background] = v | 0x1000; + } + SetAttribute (v & 0xffff); + } + + Dictionary rawPairs = new Dictionary (); + public override void SetColors (short foreColorId, short backgroundColorId) + { + // BUGBUG: This code is never called ?? See Issue #2300 + int key = ((ushort)foreColorId << 16) | (ushort)backgroundColorId; + if (!rawPairs.TryGetValue (key, out var v)) { + v = MakeColor (foreColorId, backgroundColorId); + rawPairs [key] = v; + } + SetAttribute (v); + } + static Key MapCursesKey (int cursesKey) { switch (cursesKey) { @@ -767,7 +835,7 @@ namespace Terminal.Gui { }; } - Curses.Event reportableMouseEvents; + Curses.Event oldMouseEvents, reportableMouseEvents; public override void Init (Action terminalResized) { if (window != null) @@ -824,7 +892,7 @@ namespace Terminal.Gui { Curses.noecho (); Curses.Window.Standard.keypad (true); - reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out _); + reportableMouseEvents = Curses.mousemask (Curses.Event.AllEvents | Curses.Event.ReportMousePosition, out oldMouseEvents); TerminalResized = terminalResized; if (reportableMouseEvents.HasFlag (Curses.Event.ReportMousePosition)) StartReportingMouseMoves (); @@ -946,7 +1014,7 @@ namespace Terminal.Gui { case Color.White: return Curses.COLOR_WHITE | Curses.A_BOLD | Curses.COLOR_GRAY; case Color.Invalid: - return Curses.COLOR_BLACK; + return Curses.COLOR_BLACK; } throw new ArgumentException ("Invalid color code"); } @@ -1020,6 +1088,23 @@ namespace Terminal.Gui { Console.Out.Flush (); } + //int lastMouseInterval; + //bool mouseGrabbed; + + public override void UncookMouse () + { + //if (mouseGrabbed) + // return; + //lastMouseInterval = Curses.mouseinterval (0); + //mouseGrabbed = true; + } + + public override void CookMouse () + { + //mouseGrabbed = false; + //Curses.mouseinterval (lastMouseInterval); + } + /// public override bool GetCursorVisibility (out CursorVisibility visibility) { diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs index 3adbb7a23..661daaca4 100644 --- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs @@ -33,7 +33,7 @@ namespace Terminal.Gui { UseFakeClipboard = useFakeClipboard; FakeClipboardAlwaysThrowsNotSupportedException = fakeClipboardAlwaysThrowsNotSupportedException; FakeClipboardIsSupportedAlwaysFalse = fakeClipboardIsSupportedAlwaysTrue; - + // double check usage is correct Debug.Assert (useFakeClipboard == false && fakeClipboardAlwaysThrowsNotSupportedException == false); Debug.Assert (useFakeClipboard == false && fakeClipboardIsSupportedAlwaysTrue == false); @@ -131,31 +131,51 @@ namespace Terminal.Gui { //MockConsole.CursorTop = crow; needMove = false; } - if (runeWidth < 2 && ccol > 0 + if (runeWidth == 0 && ccol > 0) { + var r = contents [crow, ccol - 1, 0]; + var s = new string (new char [] { (char)r, (char)rune }); + string sn; + if (!s.IsNormalized ()) { + sn = s.Normalize (); + } else { + sn = s; + } + var c = sn [0]; + contents [crow, ccol - 1, 0] = c; + contents [crow, ccol - 1, 1] = CurrentAttribute; + contents [crow, ccol - 1, 2] = 1; + + } else { + if (runeWidth < 2 && ccol > 0 && Rune.ColumnWidth ((Rune)contents [crow, ccol - 1, 0]) > 1) { - contents [crow, ccol - 1, 0] = (int)(uint)' '; + contents [crow, ccol - 1, 0] = (int)(uint)' '; - } else if (runeWidth < 2 && ccol <= Clip.Right - 1 - && Rune.ColumnWidth ((Rune)contents [crow, ccol, 0]) > 1) { + } else if (runeWidth < 2 && ccol <= Clip.Right - 1 + && Rune.ColumnWidth ((Rune)contents [crow, ccol, 0]) > 1) { - contents [crow, ccol + 1, 0] = (int)(uint)' '; - contents [crow, ccol + 1, 2] = 1; + contents [crow, ccol + 1, 0] = (int)(uint)' '; + contents [crow, ccol + 1, 2] = 1; + } + if (runeWidth > 1 && ccol == Clip.Right - 1) { + contents [crow, ccol, 0] = (int)(uint)' '; + } else { + contents [crow, ccol, 0] = (int)(uint)rune; + } + contents [crow, ccol, 1] = CurrentAttribute; + contents [crow, ccol, 2] = 1; + + dirtyLine [crow] = true; } - if (runeWidth > 1 && ccol == Clip.Right - 1) { - contents [crow, ccol, 0] = (int)(uint)' '; - } else { - contents [crow, ccol, 0] = (int)(uint)rune; - } - contents [crow, ccol, 1] = CurrentAttribute; - contents [crow, ccol, 2] = 1; - - dirtyLine [crow] = true; - } else + } else { needMove = true; + } + + if (runeWidth < 0 || runeWidth > 0) { + ccol++; + } - ccol++; if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -169,8 +189,9 @@ namespace Terminal.Gui { // if (crow + 1 < Rows) // crow++; //} - if (sync) + if (sync) { UpdateScreen (); + } } public override void AddStr (ustring str) @@ -621,6 +642,7 @@ namespace Terminal.Gui { return hasColor; } + #region Unused public override void UpdateCursor () { if (!EnsureCursorVisibility ()) @@ -636,10 +658,35 @@ namespace Terminal.Gui { } } - #region Unused - public override void StartReportingMouseMoves () {} - public override void StopReportingMouseMoves () {} - public override void Suspend () {} + public override void StartReportingMouseMoves () + { + } + + public override void StopReportingMouseMoves () + { + } + + public override void Suspend () + { + } + + public override void SetColors (ConsoleColor foreground, ConsoleColor background) + { + } + + public override void SetColors (short foregroundColorId, short backgroundColorId) + { + throw new NotImplementedException (); + } + + public override void CookMouse () + { + } + + public override void UncookMouse () + { + } + #endregion public class FakeClipboard : ClipboardBase { diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 485a06f6e..9ae4eb20e 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1241,30 +1241,49 @@ namespace Terminal.Gui { var validClip = IsValidContent (ccol, crow, Clip); if (validClip) { - if (runeWidth < 2 && ccol > 0 - && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { + if (runeWidth == 0 && ccol > 0) { + var r = contents [crow, ccol - 1, 0]; + var s = new string (new char [] { (char)r, (char)rune }); + string sn; + if (!s.IsNormalized ()) { + sn = s.Normalize (); + } else { + sn = s; + } + var c = sn [0]; + contents [crow, ccol - 1, 0] = c; + contents [crow, ccol - 1, 1] = CurrentAttribute; + contents [crow, ccol - 1, 2] = 1; - contents [crow, ccol - 1, 0] = (int)(uint)' '; - - } else if (runeWidth < 2 && ccol <= Clip.Right - 1 - && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { - - contents [crow, ccol + 1, 0] = (int)(uint)' '; - contents [crow, ccol + 1, 2] = 1; - - } - if (runeWidth > 1 && ccol == Clip.Right - 1) { - contents [crow, ccol, 0] = (int)(uint)' '; } else { - contents [crow, ccol, 0] = (int)(uint)rune; - } - contents [crow, ccol, 1] = CurrentAttribute; - contents [crow, ccol, 2] = 1; + if (runeWidth < 2 && ccol > 0 + && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { + contents [crow, ccol - 1, 0] = (int)(uint)' '; + + } else if (runeWidth < 2 && ccol <= Clip.Right - 1 + && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { + + contents [crow, ccol + 1, 0] = (int)(uint)' '; + contents [crow, ccol + 1, 2] = 1; + + } + if (runeWidth > 1 && ccol == Clip.Right - 1) { + contents [crow, ccol, 0] = (int)(uint)' '; + } else { + contents [crow, ccol, 0] = (int)(uint)rune; + } + contents [crow, ccol, 1] = CurrentAttribute; + contents [crow, ccol, 2] = 1; + + } dirtyLine [crow] = true; } - ccol++; + if (runeWidth < 0 || runeWidth > 0) { + ccol++; + } + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { contents [crow, ccol, 1] = CurrentAttribute; @@ -1487,7 +1506,7 @@ namespace Terminal.Gui { outputWidth++; var rune = contents [row, col, 0]; char [] spair; - if (Rune.DecodeSurrogatePair((uint) rune, out spair)) { + if (Rune.DecodeSurrogatePair ((uint)rune, out spair)) { output.Append (spair); } else { output.Append ((char)rune); @@ -1995,6 +2014,24 @@ namespace Terminal.Gui { return hasColor; } + #region Unused + public override void SetColors (ConsoleColor foreground, ConsoleColor background) + { + } + + public override void SetColors (short foregroundColorId, short backgroundColorId) + { + } + + public override void CookMouse () + { + } + + public override void UncookMouse () + { + } + #endregion + // // These are for the .NET driver, but running natively on Windows, wont run // on the Mono emulation diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 9b0568a62..8a7502c26 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1517,35 +1517,57 @@ namespace Terminal.Gui { var validClip = IsValidContent (ccol, crow, Clip); if (validClip) { - if (runeWidth < 2 && ccol > 0 - && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { - + if (runeWidth == 0 && ccol > 0) { + var r = contents [crow, ccol - 1, 0]; + var s = new string (new char [] { (char)r, (char)rune }); + string sn; + if (!s.IsNormalized ()) { + sn = s.Normalize (); + } else { + sn = s; + } + var c = sn [0]; var prevPosition = crow * Cols + (ccol - 1); - OutputBuffer [prevPosition].Char.UnicodeChar = ' '; - contents [crow, ccol - 1, 0] = (int)(uint)' '; - - } else if (runeWidth < 2 && ccol <= Clip.Right - 1 - && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { - - var prevPosition = GetOutputBufferPosition () + 1; - OutputBuffer [prevPosition].Char.UnicodeChar = (char)' '; - contents [crow, ccol + 1, 0] = (int)(uint)' '; - - } - if (runeWidth > 1 && ccol == Clip.Right - 1) { - OutputBuffer [position].Char.UnicodeChar = (char)' '; - contents [crow, ccol, 0] = (int)(uint)' '; + OutputBuffer [prevPosition].Char.UnicodeChar = c; + contents [crow, ccol - 1, 0] = c; + OutputBuffer [prevPosition].Attributes = (ushort)CurrentAttribute; + contents [crow, ccol - 1, 1] = CurrentAttribute; + contents [crow, ccol - 1, 2] = 1; + WindowsConsole.SmallRect.Update (ref damageRegion, (short)(ccol - 1), (short)crow); } else { - OutputBuffer [position].Char.UnicodeChar = (char)rune; - contents [crow, ccol, 0] = (int)(uint)rune; + if (runeWidth < 2 && ccol > 0 + && Rune.ColumnWidth ((char)contents [crow, ccol - 1, 0]) > 1) { + + var prevPosition = crow * Cols + (ccol - 1); + OutputBuffer [prevPosition].Char.UnicodeChar = ' '; + contents [crow, ccol - 1, 0] = (int)(uint)' '; + + } else if (runeWidth < 2 && ccol <= Clip.Right - 1 + && Rune.ColumnWidth ((char)contents [crow, ccol, 0]) > 1) { + + var prevPosition = GetOutputBufferPosition () + 1; + OutputBuffer [prevPosition].Char.UnicodeChar = (char)' '; + contents [crow, ccol + 1, 0] = (int)(uint)' '; + + } + if (runeWidth > 1 && ccol == Clip.Right - 1) { + OutputBuffer [position].Char.UnicodeChar = (char)' '; + contents [crow, ccol, 0] = (int)(uint)' '; + } else { + OutputBuffer [position].Char.UnicodeChar = (char)rune; + contents [crow, ccol, 0] = (int)(uint)rune; + } + OutputBuffer [position].Attributes = (ushort)CurrentAttribute; + contents [crow, ccol, 1] = CurrentAttribute; + contents [crow, ccol, 2] = 1; + WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow); } - OutputBuffer [position].Attributes = (ushort)CurrentAttribute; - contents [crow, ccol, 1] = CurrentAttribute; - contents [crow, ccol, 2] = 1; - WindowsConsole.SmallRect.Update (ref damageRegion, (short)ccol, (short)crow); } - ccol++; + if (runeWidth < 0 || runeWidth > 0) { + ccol++; + } + if (runeWidth > 1) { if (validClip && ccol < Clip.Right) { position = GetOutputBufferPosition (); @@ -1558,8 +1580,9 @@ namespace Terminal.Gui { ccol++; } - if (sync) + if (sync) { UpdateScreen (); + } } public override void AddStr (ustring str) @@ -1764,9 +1787,33 @@ namespace Terminal.Gui { } #region Unused - public override void StartReportingMouseMoves () { } - public override void StopReportingMouseMoves () { } - public override void Suspend () { } + public override void SetColors (ConsoleColor foreground, ConsoleColor background) + { + } + + public override void SetColors (short foregroundColorId, short backgroundColorId) + { + } + + public override void Suspend () + { + } + + public override void StartReportingMouseMoves () + { + } + + public override void StopReportingMouseMoves () + { + } + + public override void UncookMouse () + { + } + + public override void CookMouse () + { + } #endregion } diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs index 327c9e2c4..681a4733a 100644 --- a/Terminal.Gui/Core/Application.cs +++ b/Terminal.Gui/Core/Application.cs @@ -57,7 +57,7 @@ namespace Terminal.Gui { /// /// public static class Application { - static Stack toplevels = new Stack (); + static readonly Stack toplevels = new Stack (); /// /// The current in use. @@ -111,28 +111,33 @@ namespace Terminal.Gui { /// public static View WantContinuousButtonPressedView { get; private set; } + private static bool? _heightAsBuffer; + /// /// The current used in the terminal. /// + /// public static bool HeightAsBuffer { get { if (Driver == null) { - throw new ArgumentNullException ("The driver must be initialized first."); + return _heightAsBuffer.HasValue && _heightAsBuffer.Value; } return Driver.HeightAsBuffer; } set { + _heightAsBuffer = value; if (Driver == null) { - throw new ArgumentNullException ("The driver must be initialized first."); + return; } - Driver.HeightAsBuffer = value; + + Driver.HeightAsBuffer = _heightAsBuffer.Value; } } static Key alternateForwardKey = Key.PageDown | Key.CtrlMask; /// - /// Alternative key to navigate forwards through all views. Ctrl+Tab is always used. + /// Alternative key to navigate forwards through views. Ctrl+Tab is the primary key. /// public static Key AlternateForwardKey { get => alternateForwardKey; @@ -147,7 +152,7 @@ namespace Terminal.Gui { static void OnAlternateForwardKeyChanged (Key oldKey) { - foreach (var top in toplevels) { + foreach (var top in toplevels.ToArray()) { top.OnAlternateForwardKeyChanged (oldKey); } } @@ -155,7 +160,7 @@ namespace Terminal.Gui { static Key alternateBackwardKey = Key.PageUp | Key.CtrlMask; /// - /// Alternative key to navigate backwards through all views. Shift+Ctrl+Tab is always used. + /// Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key. /// public static Key AlternateBackwardKey { get => alternateBackwardKey; @@ -170,7 +175,7 @@ namespace Terminal.Gui { static void OnAlternateBackwardKeyChanged (Key oldKey) { - foreach (var top in toplevels) { + foreach (var top in toplevels.ToArray()) { top.OnAlternateBackwardKeyChanged (oldKey); } } @@ -200,7 +205,8 @@ namespace Terminal.Gui { static void OnQuitKeyChanged (Key oldKey) { - foreach (var top in toplevels) { + // Duplicate the list so if it changes during enumeration we're safe + foreach (var top in toplevels.ToArray()) { top.OnQuitKeyChanged (oldKey); } } @@ -212,7 +218,7 @@ namespace Terminal.Gui { public static MainLoop MainLoop { get; private set; } /// - /// Disable or enable the mouse in this + /// Disable or enable the mouse. The mouse is enabled by default. /// public static bool IsMouseDisabled { get; set; } @@ -266,7 +272,7 @@ namespace Terminal.Gui { // users use async/await on their code // class MainLoopSyncContext : SynchronizationContext { - MainLoop mainLoop; + readonly MainLoop mainLoop; public MainLoopSyncContext (MainLoop mainLoop) { @@ -305,9 +311,9 @@ namespace Terminal.Gui { } /// - /// If set, it forces the use of the System.Console-based driver. + /// If , forces the use of the System.Console-based (see ) driver. The default is . /// - public static bool UseSystemConsole; + public static bool UseSystemConsole { get; set; } = false; // For Unit testing - ignores UseSystemConsole internal static bool ForceFakeConsole; @@ -422,6 +428,7 @@ namespace Terminal.Gui { MainLoop = new MainLoop (mainLoopDriver); try { + Driver.HeightAsBuffer = HeightAsBuffer; Driver.Init (TerminalResized); } catch (InvalidOperationException ex) { // This is a case where the driver is unable to initialize the console. @@ -705,6 +712,7 @@ namespace Terminal.Gui { return; OnGrabbedMouse (view); mouseGrabView = view; + Driver.UncookMouse (); } /// @@ -716,6 +724,7 @@ namespace Terminal.Gui { return; OnUnGrabbedMouse (mouseGrabView); mouseGrabView = null; + Driver.CookMouse (); } static void OnGrabbedMouse (View view) @@ -984,9 +993,7 @@ namespace Terminal.Gui { toplevel.PositionToplevels (); toplevel.WillPresent (); if (refreshDriver) { - if (MdiTop != null) { - MdiTop.OnChildLoaded (toplevel); - } + MdiTop?.OnChildLoaded (toplevel); toplevel.OnLoaded (); Redraw (toplevel); toplevel.PositionCursor (); @@ -1109,12 +1116,6 @@ namespace Terminal.Gui { Driver.Refresh (); } - static void Refresh (View view) - { - view.Redraw (view.Bounds); - Driver.Refresh (); - } - /// /// Triggers a refresh of the entire display. /// diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index e0f52ccc6..49a50695f 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -170,18 +170,9 @@ namespace Terminal.Gui { /// Attributes are used as elements that contain both a foreground and a background or platform specific features /// /// - /// /// s are needed to map colors to terminal capabilities that might lack colors. /// They encode both the foreground and the background color and are used in the /// class to define color schemes that can be used in an application. - /// - /// - /// s are driver-specific and, as a result, are only valid if initialized by a . - /// If an is created before a driver is initialized will be - /// and attempts to use the will result in an exception. To use an that is not - /// initilzied, after a driver is initialized, recreate the by calling the constructor - /// or . - /// /// public struct Attribute { /// @@ -433,11 +424,11 @@ namespace Terminal.Gui { public bool Equals (ColorScheme other) { return other != null && - EqualityComparer.Default.Equals (_normal, other._normal) && - EqualityComparer.Default.Equals (_focus, other._focus) && - EqualityComparer.Default.Equals (_hotNormal, other._hotNormal) && - EqualityComparer.Default.Equals (_hotFocus, other._hotFocus) && - EqualityComparer.Default.Equals (_disabled, other._disabled); + EqualityComparer.Default.Equals (_normal, other._normal) && + EqualityComparer.Default.Equals (_focus, other._focus) && + EqualityComparer.Default.Equals (_hotNormal, other._hotNormal) && + EqualityComparer.Default.Equals (_hotFocus, other._hotFocus) && + EqualityComparer.Default.Equals (_disabled, other._disabled); } /// @@ -664,6 +655,71 @@ namespace Terminal.Gui { 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. @@ -824,8 +880,8 @@ namespace Terminal.Gui { /// /// The current attribute the driver is using. /// - internal virtual Attribute CurrentAttribute { - get => _currentAttribute; + public virtual Attribute CurrentAttribute { + get => currentAttribute; set { if (!value.Initialized && value.HasValidColors && Application.Driver != null) { CurrentAttribute = Application.Driver.MakeAttribute (value.Foreground, value.Background); @@ -833,7 +889,7 @@ namespace Terminal.Gui { } if (!value.Initialized) Debug.WriteLine ("ConsoleDriver.CurrentAttribute: Attributes must be initialized before use."); - _currentAttribute = value; + currentAttribute = value; } } @@ -849,6 +905,23 @@ namespace Terminal.Gui { CurrentAttribute = c; } + /// + /// Set Colors from limit sets of colors. Not implemented by any driver: See Issue #2300. + /// + /// Foreground. + /// Background. + public abstract void SetColors (ConsoleColor foreground, ConsoleColor background); + + // Advanced uses - set colors to any pre-set pairs, you would need to init_color + // that independently with the R, G, B values. + /// + /// Advanced uses - set colors to any pre-set pairs, you would need to init_color + /// that independently with the R, G, B values. Not implemented by any driver: See Issue #2300. + /// + /// Foreground color identifier. + /// Background color identifier. + public abstract void SetColors (short foregroundColorId, short backgroundColorId); + /// /// Gets the foreground and background colors based on the value. /// @@ -1165,6 +1238,17 @@ namespace Terminal.Gui { /// public abstract void StopReportingMouseMoves (); + /// + /// Disables the cooked event processing from the mouse driver. + /// At startup, it is assumed mouse events are cooked. Not implemented by any driver: See Issue #2300. + /// + public abstract void UncookMouse (); + + /// + /// Enables the cooked event processing from the mouse driver. Not implemented by any driver: See Issue #2300. + /// + public abstract void CookMouse (); + /// /// Horizontal line character. /// @@ -1354,8 +1438,7 @@ namespace Terminal.Gui { /// Lower right rounded corner /// public Rune LRRCorner = '\u256f'; - - private Attribute _currentAttribute; + private Attribute currentAttribute; /// /// Make the attribute for the foreground and background colors. @@ -1383,8 +1466,6 @@ namespace Terminal.Gui { /// Ensures all s in are correclty /// initalized by the driver. /// - /// - /// /// Flag indicating if colors are supported (not used). public void InitalizeColorSchemes (bool supportsColors = true) { @@ -1397,6 +1478,35 @@ namespace Terminal.Gui { return; } + Colors.TopLevel.Normal = MakeColor (Color.BrightGreen, Color.Black); + Colors.TopLevel.Focus = MakeColor (Color.White, Color.Cyan); + Colors.TopLevel.HotNormal = MakeColor (Color.Brown, Color.Black); + Colors.TopLevel.HotFocus = MakeColor (Color.Blue, Color.Cyan); + Colors.TopLevel.Disabled = MakeColor (Color.DarkGray, Color.Black); + + Colors.Base.Normal = MakeColor (Color.White, Color.Blue); + Colors.Base.Focus = MakeColor (Color.Black, Color.Gray); + Colors.Base.HotNormal = MakeColor (Color.BrightCyan, Color.Blue); + Colors.Base.HotFocus = MakeColor (Color.BrightBlue, Color.Gray); + Colors.Base.Disabled = MakeColor (Color.DarkGray, Color.Blue); + + Colors.Dialog.Normal = MakeColor (Color.Black, Color.Gray); + Colors.Dialog.Focus = MakeColor (Color.White, Color.DarkGray); + Colors.Dialog.HotNormal = MakeColor (Color.Blue, Color.Gray); + Colors.Dialog.HotFocus = MakeColor (Color.BrightYellow, Color.DarkGray); + Colors.Dialog.Disabled = MakeColor (Color.Gray, Color.DarkGray); + + Colors.Menu.Normal = MakeColor (Color.White, Color.DarkGray); + Colors.Menu.Focus = MakeColor (Color.White, Color.Black); + Colors.Menu.HotNormal = MakeColor (Color.BrightYellow, Color.DarkGray); + Colors.Menu.HotFocus = MakeColor (Color.BrightYellow, Color.Black); + Colors.Menu.Disabled = MakeColor (Color.Gray, Color.DarkGray); + + Colors.Error.Normal = MakeColor (Color.Red, Color.White); + Colors.Error.Focus = MakeColor (Color.Black, Color.BrightRed); + Colors.Error.HotNormal = MakeColor (Color.Black, Color.White); + Colors.Error.HotFocus = MakeColor (Color.White, Color.BrightRed); + Colors.Error.Disabled = MakeColor (Color.DarkGray, Color.White); } } diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 8734261c0..454a64dd1 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -769,7 +769,7 @@ namespace Terminal.Gui { void Initialize (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed, TextDirection direction = TextDirection.LeftRight_TopBottom, Border border = null) { - TextFormatter = new TextFormatter (); + TextFormatter = new TextFormatter (); TextFormatter.HotKeyChanged += TextFormatter_HotKeyChanged; TextDirection = direction; Border = border; @@ -1447,8 +1447,9 @@ namespace Terminal.Gui { /// public virtual ColorScheme ColorScheme { get { - if (colorScheme == null) + if (colorScheme == null) { return SuperView?.ColorScheme; + } return colorScheme; } set { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 14cd47ece..4c8f19eee 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -164,7 +164,7 @@ namespace UICatalog { public UICatalogTopLevel () { - ColorScheme = _colorScheme; + ColorScheme = _colorScheme = Colors.Base; MenuBar = new MenuBar (new MenuBarItem [] { new MenuBarItem ("_File", new MenuItem [] { new MenuItem ("_Quit", "Quit UI Catalog", () => RequestStop(), null, null, Key.Q | Key.CtrlMask) diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index b7ef1d8db..7228d8ad6 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -24,7 +24,6 @@ namespace Terminal.Gui.ApplicationTests { Assert.Null (Application.Driver); Assert.Null (Application.Top); Assert.Null (Application.Current); - Assert.Throws (() => Application.HeightAsBuffer == true); Assert.Null (Application.MainLoop); Assert.Null (Application.Iteration); Assert.Null (Application.RootMouseEvent);