/src/Framework/SharpMud.Net.Telnet/Net/Telnet/Protocols/ANSI/Utility.cs

http://sharpmud-framework.googlecode.com/ · C# · 346 lines · 217 code · 39 blank · 90 comment · 25 complexity · 564f56d657cac5880257e946ce65fc5a MD5 · raw file

  1. using System;
  2. namespace SharpMud.Net.Telnet.ANSI
  3. {
  4. public class Utility
  5. {
  6. protected Utility()
  7. {
  8. }
  9. static Utility()
  10. {
  11. InitializeColorLookup();
  12. }
  13. internal const int ForegroundDefaultColor = 39;
  14. internal const int BackgroundDefaultColor = 49;
  15. internal const int BackgroundForegroundDifference = BackgroundDefaultColor - ForegroundDefaultColor;
  16. /// <summary>
  17. /// This property returns a string for the regular expression that will match ANSI
  18. /// control sequences with 99% accuracy.
  19. /// </summary>
  20. public static string AnsiSequenceRegex
  21. {
  22. get
  23. {
  24. return System.Text.RegularExpressions.Regex.Escape(ESC) + @"\[{0,1}\d*[;\d]*[a-zA-Z]";
  25. }
  26. }
  27. /// <summary>
  28. /// Returns the ANSI escape sequence that will move the cursor UP the
  29. /// given number of lines
  30. /// </summary>
  31. /// <param name="numLines">The number of lines to move the cursor</param>
  32. /// <returns>Returns an ANSI escape sequence</returns>
  33. public static string MoveCursorUp(int numLines)
  34. {
  35. return ESC + String.Format("[{0}A",numLines);
  36. }
  37. /// <summary>
  38. /// Returns the ANSI escape sequence that will move the cursor DOWN the
  39. /// given number of lines
  40. /// </summary>
  41. /// <param name="numLines">The number of lines to move the cursor</param>
  42. /// <returns>Returns an ANSI escape sequence</returns>
  43. public static string MoveCursorDown(int numLines)
  44. {
  45. return ESC + String.Format("[{0}B",numLines);
  46. }
  47. /// <summary>
  48. /// Returns the ANSI escape sequence that will move the cursor RIGHT the
  49. /// given number of columns
  50. /// </summary>
  51. /// <param name="numCols">The number of columns to move the cursor</param>
  52. /// <returns>Returns an ANSI escape sequence</returns>
  53. public static string MoveCursorRight(int numCols)
  54. {
  55. return ESC + String.Format("[{0}C",numCols);
  56. }
  57. /// <summary>
  58. /// Returns the ANSI escape sequence that will move the cursor LEFT the
  59. /// given number of columns
  60. /// </summary>
  61. /// <param name="numCols">The number of columns to move the cursor</param>
  62. /// <returns>Returns an ANSI escape sequence</returns>
  63. public static string MoveCursorLeft(int numCols)
  64. {
  65. return ESC + String.Format("[{0}D",numCols);
  66. }
  67. /// <summary>
  68. /// Returns the ANSI sequence that instructs the terminal to save the
  69. /// current cursor position
  70. /// </summary>
  71. public static string SaveCursorPosition
  72. {
  73. get
  74. {
  75. return ESC + "[s";
  76. }
  77. }
  78. /// <summary>
  79. /// Returns the ANSI sequence that instructs the terminal to resume the
  80. /// cursor position to the last saved one
  81. /// </summary>
  82. public static string LoadCursorPosition
  83. {
  84. get
  85. {
  86. return ESC + "[u";
  87. }
  88. }
  89. /// <summary>
  90. /// Returns the ANSI sequence that clears the screen and moves the cursor
  91. /// to the beginning of the line
  92. /// </summary>
  93. public static string ClearScreenAndHomeCursor
  94. {
  95. get
  96. {
  97. return ESC + "[2J";
  98. }
  99. }
  100. /// <summary>
  101. /// Returns the ANSI sequence that clears to the end of the current line
  102. /// </summary>
  103. public static string ClearToEOL
  104. {
  105. get
  106. {
  107. return ESC + "K";
  108. }
  109. }
  110. public static string SetColor(ForegroundColor foregroundColor)
  111. {
  112. string seq=null;
  113. bool found=false;
  114. found = _ForegroundLookupTable.TryGetValue(foregroundColor, out seq);
  115. if (!found)
  116. return null;
  117. if (found)
  118. return seq;
  119. return null;
  120. }
  121. public static string SetColor(BackgroundColor backgroundColor)
  122. {
  123. string seq = null;
  124. bool found = false;
  125. found = _BackgroundLookupTable.TryGetValue(backgroundColor, out seq);
  126. if (!found)
  127. return null;
  128. if (found)
  129. return seq;
  130. return null;
  131. }
  132. public static string SetForegroundColor(BasicColor foregroundColor)
  133. {
  134. return ESC + String.Format("[{0}m",
  135. (int)MakeScopedColor(foregroundColor,TextColorScope.FG) );
  136. }
  137. public static string SetBackgroundColor(BasicColor backgroundColor)
  138. {
  139. return ESC + String.Format("[{0}m",
  140. (int)MakeScopedColor(backgroundColor,TextColorScope.BG) );
  141. }
  142. public static string SetForegroundColorDefault()
  143. {
  144. return ESC + String.Format("[{0},", (int)Utility.ForegroundDefaultColor);
  145. }
  146. public static string SetBackgroundColorDefault()
  147. {
  148. return ESC + String.Format("[{0},", (int)Utility.BackgroundDefaultColor);
  149. }
  150. /// <summary>
  151. /// Returns an ANSI sequence that operates the given attribute, a
  152. /// foreground color, and a background color, on the terminal
  153. /// </summary>
  154. /// <param name="attribute">An extended text attribute to use</param>
  155. /// <param name="foregroundColor">The foreground color to use</param>
  156. /// <param name="backgroundColor">The background color to use</param>
  157. /// <returns>Returns an ANSI escape sequence</returns>
  158. public static string SetTextAttributes(ExtendedTextAttribute attribute, BasicColor foregroundColor, BasicColor backgroundColor)
  159. {
  160. return ESC + String.Format("[{0};{1};{2}m",
  161. (int)attribute,
  162. (int)MakeScopedColor(foregroundColor,TextColorScope.FG),
  163. (int)MakeScopedColor(backgroundColor,TextColorScope.BG));
  164. }
  165. public static string SetTextColor(BasicColor basicAnsiColor, ColorScope colorScope)
  166. {
  167. return SetTextColor(basicAnsiColor, colorScope, false);
  168. }
  169. public static string SetTextColor(BasicColor basicAnsiColor, ColorScope colorScope, bool useBright)
  170. {
  171. if (colorScope == ColorScope.Background && useBright == true)
  172. {
  173. throw new ArgumentException("You cannot combine the 'bright' attribute with a background color.");
  174. }
  175. if (!System.Enum.IsDefined(typeof(ColorScope), colorScope))
  176. throw new ArgumentException("Argument value undefined.", "colorScope");
  177. if (!System.Enum.IsDefined(typeof(BasicColor), basicAnsiColor))
  178. throw new ArgumentException("Argument value undefined.", "basicAnsiColor");
  179. int resultAnsiColor;
  180. if (colorScope == ColorScope.Foreground)
  181. resultAnsiColor = (int)basicAnsiColor;
  182. else
  183. resultAnsiColor = (int)basicAnsiColor + Utility.BackgroundForegroundDifference;
  184. if (!useBright)
  185. return ESC + String.Format("[{0};{1}m", (int)ExtendedTextAttribute.Normal,resultAnsiColor);
  186. if (useBright)
  187. return ESC + String.Format("[{0};{1}m", (int)ExtendedTextAttribute.Bold, resultAnsiColor);
  188. return null;
  189. }
  190. /// <summary>
  191. /// Returns an ANSI sequence that operates the given ANSI attribute on a terminal
  192. /// </summary>
  193. /// <param name="attribute">An extended text attribute to use</param>
  194. /// <returns>Returns an ANSI escape sequence</returns>
  195. public static string SetTextAttributes(ExtendedTextAttribute attribute)
  196. {
  197. return ESC + String.Format("[{0}m",
  198. (int)attribute );
  199. }
  200. /// <summary>
  201. /// Returns an ANSI sequence that operates the given
  202. /// foreground color and background color on the terminal
  203. /// </summary>
  204. /// <param name="foregroundColor">The foreground color to use</param>
  205. /// <param name="backgroundColor">The background color to use</param>
  206. /// <returns>Returns an ANSI escape sequence</returns>
  207. public static string SetTextAttributes(BasicColor foregroundColor, BasicColor backgroundColor)
  208. {
  209. return ESC + String.Format("[{0};{1}m",
  210. (int)MakeScopedColor(foregroundColor,TextColorScope.FG),
  211. (int)MakeScopedColor(backgroundColor,TextColorScope.BG));
  212. }
  213. /// <summary>
  214. /// Returns the ANSI escape sequence that will move the cursor to another
  215. /// onscreen location
  216. /// </summary>
  217. /// <param name="line">The line number to move the cursor to</param>
  218. /// <param name="col">The column number to move the cursor to</param>
  219. /// <returns>Returns an ANSI escape sequence</returns>
  220. public static string MoveCursorTo(int line, int col)
  221. {
  222. return ESC + String.Format("[{0};{1}H",line,col);
  223. }
  224. /// <summary>
  225. /// The magic string (character) that must begin all ANSI control sequences
  226. /// </summary>
  227. public const string ESC = "\x1B"; // ASCII # 33
  228. /// <summary>
  229. /// Whether or not a color is for the foreground or background
  230. /// </summary>
  231. internal enum TextColorScope
  232. {
  233. Foreground = ColorScope.Foreground,
  234. Background = ColorScope.Background,
  235. FG = Foreground,
  236. BG = Background
  237. }
  238. /// <summary>
  239. /// This method takes a basic color and translates it to the form that can be inserted
  240. /// into an ANSI sequence, by taking into account whether or not it is a foreground or
  241. /// background color.
  242. /// </summary>
  243. /// <param name="color">The basic color to translate</param>
  244. /// <param name="scope">Whether or not the color is for foreground or background</param>
  245. /// <returns>Returns a scoped color</returns>
  246. internal static ScopedColor MakeScopedColor(BasicColor color, TextColorScope scope)
  247. {
  248. if(scope==TextColorScope.Foreground)
  249. {
  250. return (ScopedColor)color;
  251. }
  252. else if(scope==TextColorScope.Background)
  253. {
  254. return (ScopedColor)(color+10);
  255. }
  256. else
  257. {
  258. throw new ArgumentOutOfRangeException("scope");
  259. }
  260. }
  261. #region Color Value Lookup
  262. private static System.Collections.Generic.Dictionary<ForegroundColor, string> _ForegroundLookupTable;
  263. private static System.Collections.Generic.Dictionary<BackgroundColor, string> _BackgroundLookupTable;
  264. /// <summary>
  265. /// Since ANSI sequences for enum-based color values are stored using custom attributes,
  266. /// and reflection isn't the fastest way to lookup data, we need to pre-fetch the data
  267. /// </summary>
  268. private static void InitializeColorLookup()
  269. {
  270. _ForegroundLookupTable = new System.Collections.Generic.Dictionary<ForegroundColor, string>();
  271. _BackgroundLookupTable = new System.Collections.Generic.Dictionary<BackgroundColor, string>();
  272. string s = null;
  273. AnsiRepresentationAttribute ara = null;
  274. ///Program in ForegroundColor lookups
  275. foreach (ForegroundColor colorValue in System.Enum.GetValues(typeof(ForegroundColor)))
  276. {
  277. s = null;
  278. ara = null;
  279. ara = AnsiRepresentationAttribute.FindForValue<ForegroundColor>(colorValue);
  280. if (ara != null)
  281. {
  282. if (_ForegroundLookupTable.ContainsKey(colorValue) == false)
  283. {
  284. s = ara.Sequence;
  285. _ForegroundLookupTable.Add(colorValue, s);
  286. }
  287. }
  288. }
  289. ///Program in BackgroundColor lookups
  290. foreach (BackgroundColor colorValue in System.Enum.GetValues(typeof(BackgroundColor)))
  291. {
  292. s = null;
  293. ara = null;
  294. ara = AnsiRepresentationAttribute.FindForValue<BackgroundColor>(colorValue);
  295. if (ara != null)
  296. {
  297. if (_BackgroundLookupTable.ContainsKey(colorValue) == false)
  298. {
  299. s = ara.Sequence;
  300. _BackgroundLookupTable.Add(colorValue, s);
  301. }
  302. }
  303. }
  304. }
  305. #endregion
  306. }
  307. }