diff --git a/VtNetCore/VirtualTerminal/Model/TerminalAttribute.cs b/VtNetCore/VirtualTerminal/Model/TerminalAttribute.cs index 5bbf813..b5863cb 100644 --- a/VtNetCore/VirtualTerminal/Model/TerminalAttribute.cs +++ b/VtNetCore/VirtualTerminal/Model/TerminalAttribute.cs @@ -1,6 +1,8 @@ namespace VtNetCore.VirtualTerminal.Model { using System; + using System.Collections.Generic; + using System.Linq; using VtNetCore.VirtualTerminal.Enums; /// @@ -8,21 +10,21 @@ /// public class TerminalAttribute { - private static readonly ushort BrightBit = 0x0040; - private static readonly ushort UnderscoreBit = 0x0080; - private static readonly ushort StandoutBit = 0x0100; - private static readonly ushort BlinkBit = 0x0200; - private static readonly ushort ReverseBit = 0x0400; - private static readonly ushort HiddenBit = 0x0800; - private static readonly ushort ProtectionBits = 0x3000; + public TerminalColor ForegroundRgb { get; set; } = TerminalColorsLookup[ETerminalColor.Black]; - private ushort InternalBits = - (ushort)ETerminalColor.White | // ForegroundColor - (ushort)ETerminalColor.Black; // BackgroundColor + public TerminalColor BackgroundRgb { get; set; } = TerminalColorsLookup[ETerminalColor.White]; - public TerminalColor ForegroundRgb { get; set; } - - public TerminalColor BackgroundRgb { get; set; } + public static readonly Dictionary TerminalColorsLookup = new Dictionary() + { + { ETerminalColor.Black, new TerminalColor(ETerminalColor.Black, false) }, + { ETerminalColor.Red, new TerminalColor(ETerminalColor.Red, false) }, + { ETerminalColor.Green, new TerminalColor(ETerminalColor.Green, false) }, + { ETerminalColor.Yellow,new TerminalColor(ETerminalColor.Yellow, false) }, + { ETerminalColor.Blue, new TerminalColor(ETerminalColor.Blue, false) }, + { ETerminalColor.Magenta, new TerminalColor(ETerminalColor.Magenta, false) }, + { ETerminalColor.Cyan, new TerminalColor(ETerminalColor.Cyan, false) }, + { ETerminalColor.White, new TerminalColor(ETerminalColor.White, true) } + }; public override bool Equals(object obj) { @@ -60,8 +62,11 @@ public override bool Equals(object obj) ) return false; - return - InternalBits == other.InternalBits; + return Bright == other.Bright && + Standout == other.Standout && + Underscore == other.Underscore && + Blink == other.Blink && + Reverse == other.Reverse; } public override int GetHashCode() @@ -76,11 +81,11 @@ public ETerminalColor ForegroundColor { get { - return (ETerminalColor)(InternalBits & 0x7); + return TerminalColorsLookup.Single(x => x.Value == ForegroundRgb).Key; } set { - InternalBits = (ushort)((InternalBits & 0xFFF8) | (ushort)value); + ForegroundRgb = TerminalColorsLookup[value]; } } @@ -92,11 +97,11 @@ public ETerminalColor BackgroundColor { get { - return (ETerminalColor)((InternalBits >> 3) & 0x7); + return TerminalColorsLookup.Single(x => x.Value == BackgroundRgb).Key; } set { - InternalBits = (ushort)((InternalBits & 0xFFC7) | ((int)value << 3)); + BackgroundRgb = TerminalColorsLookup[value]; } } @@ -106,126 +111,38 @@ public ETerminalColor BackgroundColor /// /// This is an old naming system and should be udpated /// - public bool Bright - { - get - { - return (InternalBits & BrightBit) == BrightBit; - } - set - { - if (value) - InternalBits |= BrightBit; - else - InternalBits = (ushort)((InternalBits & ~BrightBit) & 0xFFFF); - } - } + public bool Bright { get; set; } = false; /// /// Unclear what this is /// /// TODO : Figure out what Standout text is - public bool Standout - { - get - { - return (InternalBits & StandoutBit) == StandoutBit; - } - set - { - if (value) - InternalBits |= StandoutBit; - else - InternalBits = (ushort)((InternalBits & ~StandoutBit) & 0xFFFF); - } - } + public bool Standout { get; set; } = false; /// /// Sets the text as having a line beneath the character /// - public bool Underscore - { - get - { - return (InternalBits & UnderscoreBit) == UnderscoreBit; - } - set - { - if (value) - InternalBits |= UnderscoreBit; - else - InternalBits = (ushort)((InternalBits & ~UnderscoreBit) & 0xFFFF); - } - } + public bool Underscore { get; set; } = false; /// /// Sets the blink attribute /// - public bool Blink - { - get - { - return (InternalBits & BlinkBit) == BlinkBit; - } - set - { - if (value) - InternalBits |= BlinkBit; - else - InternalBits = (ushort)((InternalBits & ~BlinkBit) & 0xFFFF); - } - } + public bool Blink { get; set; } = false; /// /// Reverses the foreground and the background colors of the text /// - public bool Reverse - { - get - { - return (InternalBits & ReverseBit) == ReverseBit; - } - set - { - if (value) - InternalBits |= ReverseBit; - else - InternalBits = (ushort)((InternalBits & ~ReverseBit) & 0xFFFF); - } - } + public bool Reverse { get; set; } = false; /// /// Specifies that the character should not be displayed. /// - public bool Hidden - { - get - { - return (InternalBits & HiddenBit) == HiddenBit; - } - set - { - if (value) - InternalBits |= HiddenBit; - else - InternalBits = (ushort)((InternalBits & ~HiddenBit) & 0xFFFF); - } - } + public bool Hidden { get; set; } = false; /// /// Specifies that the character should not be erased on SEL and SED operations. /// - public int Protected - { - get - { - return (InternalBits & ProtectionBits) >> 12; - } - set - { - InternalBits = (ushort)((InternalBits & ~ProtectionBits) | ((value & 0x3) << 12)); - } - } + public int Protected { get; set; } = 0; /// /// Returns a deep copy of the attribute @@ -235,9 +152,15 @@ public TerminalAttribute Clone() { return new TerminalAttribute { - InternalBits = InternalBits, ForegroundRgb = ForegroundRgb == null ? null : new TerminalColor(ForegroundRgb), - BackgroundRgb = BackgroundRgb == null ? null : new TerminalColor(BackgroundRgb) + BackgroundRgb = BackgroundRgb == null ? null : new TerminalColor(BackgroundRgb), + Bright = Bright, + Standout = Standout, + Underscore = Underscore, + Blink = Blink, + Reverse = Reverse, + Hidden = Hidden, + Protected = Protected }; } @@ -251,9 +174,15 @@ public TerminalAttribute Inverse { return new TerminalAttribute { - InternalBits = (ushort)((InternalBits & 0xFFC0) | ((InternalBits & 0x0007) << 3) | ((InternalBits >> 3) & 0x0007)), ForegroundRgb = BackgroundRgb == null ? null : new TerminalColor(BackgroundRgb), BackgroundRgb = ForegroundRgb == null ? null : new TerminalColor(ForegroundRgb), + Bright = Bright, + Standout = Standout, + Underscore = Underscore, + Blink = Blink, + Reverse = Reverse, + Hidden = Hidden, + Protected = Protected }; } } diff --git a/VtNetCore/VirtualTerminal/VirtualTerminalController.cs b/VtNetCore/VirtualTerminal/VirtualTerminalController.cs index cd24780..29a2b68 100644 --- a/VtNetCore/VirtualTerminal/VirtualTerminalController.cs +++ b/VtNetCore/VirtualTerminal/VirtualTerminalController.cs @@ -44,6 +44,8 @@ public class VirtualTerminalController : IVirtualTerminalController private EActiveBuffer ActiveBuffer { get; set; } = EActiveBuffer.Normal; + public bool IsActiveBufferNormal => ActiveBuffer == EActiveBuffer.Normal; + /// /// The logical top row of the view port. This translates relative to the buffer /// @@ -304,6 +306,16 @@ public VirtualTerminalController() /// public EventHandler SizeChanged; + /// + /// Emitted when a change to the characters on the terminal occurs + /// + public event Action OnCharacterChanged; + + /// + /// Emitted when the buffer is changed + /// + public event Action OnScreenBufferChanged; + /// /// Enables storing of raw text for scripting tools /// @@ -831,6 +843,8 @@ public void FullReset() LastMousePosition.Set(-1, -1); + OnScreenBufferChanged?.Invoke(); + ChangeCount++; } @@ -1977,6 +1991,8 @@ public void EnableNormalBuffer() alternativeBufferTopRow = TopRow; TopRow = normalBufferTopRow; + OnScreenBufferChanged?.Invoke(); + ChangeCount++; } @@ -1993,6 +2009,8 @@ public void EnableAlternateBuffer() normalBufferTopRow = TopRow; TopRow = alternativeBufferTopRow; + OnScreenBufferChanged?.Invoke(); + ChangeCount++; } @@ -2194,9 +2212,12 @@ public void SetLeftAndRightMargins(int left, int right) SetCursorPosition(1, 1); } + public bool InEraseState = false; + public void EraseLine(bool ignoreProtected = true) { LogController("EraseLine(ignoreProtected: " + ignoreProtected + ")"); + InEraseState = true; for (var i = 0; i < Columns; i++) SetCharacter(i, CursorState.CurrentRow, ' ', CursorState.Attributes, ignoreProtected); @@ -2205,12 +2226,14 @@ public void EraseLine(bool ignoreProtected = true) while (line.Count > Columns) line.RemoveAt(line.Count - 1); + InEraseState = false; ChangeCount++; } public void EraseToEndOfLine(bool ignoreProtected=true) { LogController("EraseToEndOfLine(ignoreProtected: " + ignoreProtected + ")"); + InEraseState = true; for (var i = CursorState.CurrentColumn; i < Columns; i++) SetCharacter(i, CursorState.CurrentRow, ' ', CursorState.Attributes, ignoreProtected); @@ -2231,12 +2254,14 @@ public void EraseToEndOfLine(bool ignoreProtected=true) ); } + InEraseState = false; ChangeCount++; } public void EraseToStartOfLine(bool ignoreProtected = true) { LogController("EraseToStartOfLine(ignoreProtected: " + ignoreProtected + ")"); + InEraseState = true; for (var i = 0; i < Columns && i <= CursorState.CurrentColumn; i++) SetCharacter(i, CursorState.CurrentRow, ' ', CursorState.Attributes, ignoreProtected); @@ -2245,6 +2270,7 @@ public void EraseToStartOfLine(bool ignoreProtected = true) while (line.Count > Columns) line.RemoveAt(line.Count - 1); + InEraseState = false; ChangeCount++; } @@ -2252,6 +2278,7 @@ public void EraseBelow(bool ignoreProtected = true) { // TODO : Optimize LogController("EraseBelow(ignoreProtected: " + ignoreProtected + ")"); + InEraseState = true; for (var y = CursorState.CurrentRow + 1; y < VisibleRows; y++) { @@ -2266,12 +2293,15 @@ public void EraseBelow(bool ignoreProtected = true) for (var x = CursorState.CurrentColumn; x < VisibleColumns; x++) SetCharacter(x, CursorState.CurrentRow, ' ', CursorState.Attributes, ignoreProtected); + + InEraseState = false; } public void EraseAbove(bool ignoreProtected = true) { // TODO : Optimize LogController("EraseAbove(ignoreProtected: " + ignoreProtected + ")"); + InEraseState = true; for (var y = CursorState.CurrentRow - 1; y >= 0; y--) { @@ -2285,12 +2315,15 @@ public void EraseAbove(bool ignoreProtected = true) for (var x = 0; x <= CursorState.CurrentColumn; x++) SetCharacter(x, CursorState.CurrentRow, ' ', CursorState.Attributes, ignoreProtected); + + InEraseState = false; } public void DeleteLines(int count) { // TODO : Verify it works with scroll range LogController("DeleteLines(count:" + count.ToString() + ")"); + InEraseState = true; if ( CursorState.CurrentRow < ScrollTop || @@ -2338,6 +2371,7 @@ public void DeleteLines(int count) } } + InEraseState = false; ChangeCount++; } @@ -2806,6 +2840,8 @@ private TerminalCharacter SetCharacter(int currentColumn, int currentRow, char c character.CombiningCharacters = ""; } + OnCharacterChanged(currentRow, currentColumn, attribute, ch); + return character; }