using System; using System.Collections.Generic; namespace Terminal.Gui { /// /// Represents the status of an ANSI escape sequence request made to the terminal using . /// /// /// public class EscSeqReqStatus { /// /// Gets the Escape Sequence Termintor (e.g. ESC[8t ... t is the terminator). /// public string Terminator { get; } /// /// Gets the number of requests. /// public int NumRequests { get; } /// /// Gets the number of unfinished requests. /// public int NumOutstanding { get; set; } /// /// Creates a new state of escape sequence request. /// /// The terminator. /// The number of requests. public EscSeqReqStatus (string terminator, int numReq) { Terminator = terminator; NumRequests = NumOutstanding = numReq; } } // TODO: This class is a singleton. It should use the singleton pattern. /// /// Manages ANSI Escape Sequence requests and responses. The list of contains the status of the request. /// Each request is identified by the terminator (e.g. ESC[8t ... t is the terminator). /// public class EscSeqRequests { /// /// Gets the list. /// public List Statuses { get; } = new List (); /// /// Adds a new request for the ANSI Escape Sequence defined by . Adds a /// instance to list. /// /// The terminator. /// The number of requests. public void Add (string terminator, int numReq = 1) { lock (Statuses) { var found = Statuses.Find (x => x.Terminator == terminator); if (found == null) { Statuses.Add (new EscSeqReqStatus (terminator, numReq)); } else if (found != null && found.NumOutstanding < found.NumRequests) { found.NumOutstanding = Math.Min (found.NumOutstanding + numReq, found.NumRequests); } } } /// /// Removes a request defined by . If a matching is found /// and the number of outstanding /// requests is greater than 0, the number of outstanding requests is decremented. If the number of outstanding requests /// is 0, the is removed from . /// /// The terminating string. public void Remove (string terminator) { lock (Statuses) { var found = Statuses.Find (x => x.Terminator == terminator); if (found == null) { return; } if (found != null && found.NumOutstanding == 0) { Statuses.Remove (found); } else if (found != null && found.NumOutstanding > 0) { found.NumOutstanding--; if (found.NumOutstanding == 0) { Statuses.Remove (found); } } } } /// /// Indicates if a with the exists /// in the list. /// /// /// if exist, otherwise. public bool HasResponse (string terminator) { lock (Statuses) { var found = Statuses.Find (x => x.Terminator == terminator); if (found == null) { return false; } if (found != null && found.NumOutstanding > 0) { return true; } else { // BUGBUG: Why does an API that returns a bool remove the entry from the list? // NetDriver and Unit tests never exercise this line of code. Maybe Curses does? Statuses.Remove (found); } return false; } } } }