EscSeqRequests.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #nullable enable
  2. using System.Collections.Concurrent;
  3. namespace Terminal.Gui;
  4. /// <summary>
  5. /// Manages ANSI Escape Sequence requests and responses. The list of <see cref="EscSeqReqStatus"/>
  6. /// contains the
  7. /// status of the request. Each request is identified by the terminator (e.g. ESC[8t ... t is the terminator).
  8. /// </summary>
  9. public static class EscSeqRequests
  10. {
  11. /// <summary>Gets the <see cref="EscSeqReqStatus"/> list.</summary>
  12. public static List<EscSeqReqStatus> Statuses { get; } = new ();
  13. /// <summary>
  14. /// Adds a new request for the ANSI Escape Sequence defined by <paramref name="terminator"/>. Adds a
  15. /// <see cref="EscSeqReqStatus"/> instance to <see cref="Statuses"/> list.
  16. /// </summary>
  17. /// <param name="terminator">The terminator.</param>
  18. /// <param name="numReq">The number of requests.</param>
  19. public static void Add (string terminator, int numReq = 1)
  20. {
  21. lock (Statuses)
  22. {
  23. EscSeqReqStatus? found = Statuses.Find (x => x.Terminator == terminator);
  24. if (found is null)
  25. {
  26. Statuses.Add (new EscSeqReqStatus (terminator, numReq));
  27. }
  28. else if (found.NumOutstanding < found.NumRequests)
  29. {
  30. found.NumOutstanding = Math.Min (found.NumOutstanding + numReq, found.NumRequests);
  31. }
  32. }
  33. }
  34. /// <summary>
  35. /// Clear the <see cref="Statuses"/> property.
  36. /// </summary>
  37. public static void Clear ()
  38. {
  39. lock (Statuses)
  40. {
  41. Statuses.Clear ();
  42. }
  43. }
  44. /// <summary>
  45. /// Indicates if a <see cref="EscSeqReqStatus"/> with the <paramref name="terminator"/> exists in the
  46. /// <see cref="Statuses"/> list.
  47. /// </summary>
  48. /// <param name="terminator"></param>
  49. /// <returns><see langword="true"/> if exist, <see langword="false"/> otherwise.</returns>
  50. public static bool HasResponse (string terminator)
  51. {
  52. lock (Statuses)
  53. {
  54. EscSeqReqStatus? found = Statuses.Find (x => x.Terminator == terminator);
  55. if (found is null)
  56. {
  57. return false;
  58. }
  59. if (found is { NumOutstanding: > 0 })
  60. {
  61. return true;
  62. }
  63. // BUGBUG: Why does an API that returns a bool remove the entry from the list?
  64. // NetDriver and Unit tests never exercise this line of code. Maybe Curses does?
  65. Statuses.Remove (found);
  66. return false;
  67. }
  68. }
  69. /// <summary>
  70. /// Removes a request defined by <paramref name="terminator"/>. If a matching <see cref="EscSeqReqStatus"/> is
  71. /// found and the number of outstanding requests is greater than 0, the number of outstanding requests is decremented.
  72. /// If the number of outstanding requests is 0, the <see cref="EscSeqReqStatus"/> is removed from
  73. /// <see cref="Statuses"/>.
  74. /// </summary>
  75. /// <param name="terminator">The terminating string.</param>
  76. public static void Remove (string terminator)
  77. {
  78. lock (Statuses)
  79. {
  80. EscSeqReqStatus? found = Statuses.Find (x => x.Terminator == terminator);
  81. if (found is null)
  82. {
  83. return;
  84. }
  85. if (found.NumOutstanding == 0)
  86. {
  87. Statuses.Remove (found);
  88. }
  89. else if (found.NumOutstanding > 0)
  90. {
  91. found.NumOutstanding--;
  92. if (found.NumOutstanding == 0)
  93. {
  94. Statuses.Remove (found);
  95. }
  96. }
  97. }
  98. }
  99. }