sgr.dart 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import 'package:xterm/buffer/cell_color.dart';
  2. import 'package:xterm/terminal/csi.dart';
  3. import 'package:xterm/terminal/terminal.dart';
  4. /// SGR selects one or more character attributes at the same time.
  5. /// Multiple params (up to 32) are applied from in order from left to right.
  6. /// The changed attributes are applied to all new characters received.
  7. /// If you move characters in the viewport by scrolling or any other means,
  8. /// then the attributes move with the characters.
  9. void sgrHandler(CSI csi, Terminal terminal) {
  10. final params = csi.params.toList();
  11. if (params.isEmpty) {
  12. params.add('0');
  13. }
  14. for (var i = 0; i < params.length; i++) {
  15. final param = params[i];
  16. switch (param) {
  17. case '':
  18. case '0':
  19. case '00':
  20. terminal.cellAttr.reset();
  21. break;
  22. case '1':
  23. case '01':
  24. terminal.cellAttr.bold = true;
  25. break;
  26. case '2':
  27. case '02':
  28. terminal.cellAttr.faint = true;
  29. break;
  30. case '3':
  31. case '03':
  32. terminal.cellAttr.italic = true;
  33. break;
  34. case '4':
  35. case '04':
  36. terminal.cellAttr.underline = true;
  37. break;
  38. case '5':
  39. case '05':
  40. terminal.cellAttr.blink = true;
  41. break;
  42. case '7':
  43. case '07':
  44. terminal.cellAttr.inverse = true;
  45. break;
  46. case '8':
  47. case '08':
  48. terminal.cellAttr.invisible = true;
  49. break;
  50. case '21':
  51. terminal.cellAttr.bold = false;
  52. break;
  53. case '22':
  54. terminal.cellAttr.faint = false;
  55. break;
  56. case '23':
  57. terminal.cellAttr.italic = false;
  58. break;
  59. case '24':
  60. terminal.cellAttr.underline = false;
  61. break;
  62. case '25':
  63. terminal.cellAttr.blink = false;
  64. break;
  65. case '27':
  66. terminal.cellAttr.inverse = false;
  67. break;
  68. case '28':
  69. terminal.cellAttr.invisible = false;
  70. break;
  71. case '29':
  72. // not strikethrough
  73. break;
  74. case '39':
  75. terminal.cellAttr.fgColor = terminal.colorScheme.foreground;
  76. break;
  77. case '30':
  78. terminal.cellAttr.fgColor = terminal.colorScheme.black;
  79. break;
  80. case '31':
  81. terminal.cellAttr.fgColor = terminal.colorScheme.red;
  82. break;
  83. case '32':
  84. terminal.cellAttr.fgColor = terminal.colorScheme.green;
  85. break;
  86. case '33':
  87. terminal.cellAttr.fgColor = terminal.colorScheme.yellow;
  88. break;
  89. case '34':
  90. terminal.cellAttr.fgColor = terminal.colorScheme.blue;
  91. break;
  92. case '35':
  93. terminal.cellAttr.fgColor = terminal.colorScheme.magenta;
  94. break;
  95. case '36':
  96. terminal.cellAttr.fgColor = terminal.colorScheme.cyan;
  97. break;
  98. case '37':
  99. terminal.cellAttr.fgColor = terminal.colorScheme.white;
  100. break;
  101. case '90':
  102. terminal.cellAttr.fgColor = terminal.colorScheme.brightBlack;
  103. break;
  104. case '91':
  105. terminal.cellAttr.fgColor = terminal.colorScheme.brightRed;
  106. break;
  107. case '92':
  108. terminal.cellAttr.fgColor = terminal.colorScheme.brightGreen;
  109. break;
  110. case '93':
  111. terminal.cellAttr.fgColor = terminal.colorScheme.brightYellow;
  112. break;
  113. case '94':
  114. terminal.cellAttr.fgColor = terminal.colorScheme.brightBlue;
  115. break;
  116. case '95':
  117. terminal.cellAttr.fgColor = terminal.colorScheme.brightMagenta;
  118. break;
  119. case '96':
  120. terminal.cellAttr.fgColor = terminal.colorScheme.brightCyan;
  121. break;
  122. case '97':
  123. terminal.cellAttr.fgColor = terminal.colorScheme.white;
  124. break;
  125. case '49':
  126. terminal.cellAttr.bgColor = terminal.colorScheme.background;
  127. break;
  128. case '40':
  129. terminal.cellAttr.bgColor = terminal.colorScheme.black;
  130. break;
  131. case '41':
  132. terminal.cellAttr.bgColor = terminal.colorScheme.red;
  133. break;
  134. case '42':
  135. terminal.cellAttr.bgColor = terminal.colorScheme.green;
  136. break;
  137. case '43':
  138. terminal.cellAttr.bgColor = terminal.colorScheme.yellow;
  139. break;
  140. case '44':
  141. terminal.cellAttr.bgColor = terminal.colorScheme.blue;
  142. break;
  143. case '45':
  144. terminal.cellAttr.bgColor = terminal.colorScheme.magenta;
  145. break;
  146. case '46':
  147. terminal.cellAttr.bgColor = terminal.colorScheme.cyan;
  148. break;
  149. case '47':
  150. terminal.cellAttr.bgColor = terminal.colorScheme.white;
  151. break;
  152. case '100':
  153. terminal.cellAttr.bgColor = terminal.colorScheme.brightBlack;
  154. break;
  155. case '101':
  156. terminal.cellAttr.bgColor = terminal.colorScheme.brightRed;
  157. break;
  158. case '102':
  159. terminal.cellAttr.bgColor = terminal.colorScheme.brightGreen;
  160. break;
  161. case '103':
  162. terminal.cellAttr.bgColor = terminal.colorScheme.brightYellow;
  163. break;
  164. case '104':
  165. terminal.cellAttr.bgColor = terminal.colorScheme.brightBlue;
  166. break;
  167. case '105':
  168. terminal.cellAttr.bgColor = terminal.colorScheme.brightMagenta;
  169. break;
  170. case '106':
  171. terminal.cellAttr.bgColor = terminal.colorScheme.brightCyan;
  172. break;
  173. case '107':
  174. terminal.cellAttr.bgColor = terminal.colorScheme.white;
  175. break;
  176. case '38': // set foreground
  177. final color = parseAnsiColour(params.sublist(i), terminal);
  178. terminal.cellAttr.fgColor = color;
  179. return;
  180. case '48': // set background
  181. final color = parseAnsiColour(params.sublist(i), terminal);
  182. terminal.cellAttr.bgColor = color;
  183. return;
  184. default:
  185. terminal.debug.onError('unknown SGR: $param');
  186. }
  187. }
  188. }
  189. CellColor parseAnsiColour(List<String> params, Terminal terminal) {
  190. if (params.length > 2) {
  191. switch (params[1]) {
  192. case "5":
  193. // 8 bit colour
  194. final colNum = int.tryParse(params[2]);
  195. if (colNum == null || colNum >= 256 || colNum < 0) {
  196. return CellColor.empty();
  197. }
  198. return parse8BitSgrColour(colNum, terminal);
  199. case "2":
  200. if (params.length < 4) {
  201. return CellColor.empty();
  202. }
  203. // 24 bit colour
  204. if (params.length == 5) {
  205. final r = int.tryParse(params[2]);
  206. final g = int.tryParse(params[3]);
  207. final b = int.tryParse(params[4]);
  208. if (r == null || g == null || b == null) {
  209. return CellColor.empty();
  210. }
  211. return CellColor.fromARGB(0xff, r, g, b);
  212. }
  213. if (params.length > 5) {
  214. // ISO/IEC International Standard 8613-6
  215. final r = int.tryParse(params[3]);
  216. final g = int.tryParse(params[4]);
  217. final b = int.tryParse(params[5]);
  218. if (r == null || g == null || b == null) {
  219. return CellColor.empty();
  220. }
  221. return CellColor.fromARGB(0xff, r, g, b);
  222. }
  223. }
  224. }
  225. return CellColor.empty();
  226. }
  227. const grayscaleColors = {
  228. 232: 0xff080808,
  229. 233: 0xff121212,
  230. 234: 0xff1c1c1c,
  231. 235: 0xff262626,
  232. 236: 0xff303030,
  233. 237: 0xff3a3a3a,
  234. 238: 0xff444444,
  235. 239: 0xff4e4e4e,
  236. 240: 0xff585858,
  237. 241: 0xff626262,
  238. 242: 0xff6c6c6c,
  239. 243: 0xff767676,
  240. 244: 0xff808080,
  241. 245: 0xff8a8a8a,
  242. 246: 0xff949494,
  243. 247: 0xff9e9e9e,
  244. 248: 0xffa8a8a8,
  245. 249: 0xffb2b2b2,
  246. 250: 0xffbcbcbc,
  247. 251: 0xffc6c6c6,
  248. 252: 0xffd0d0d0,
  249. 253: 0xffdadada,
  250. 254: 0xffe4e4e4,
  251. 255: 0xffeeeeee,
  252. };
  253. CellColor parse8BitSgrColour(int colNum, Terminal terminal) {
  254. // https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
  255. switch (colNum) {
  256. case 0:
  257. return terminal.colorScheme.black;
  258. case 1:
  259. return terminal.colorScheme.red;
  260. case 2:
  261. return terminal.colorScheme.green;
  262. case 3:
  263. return terminal.colorScheme.yellow;
  264. case 4:
  265. return terminal.colorScheme.blue;
  266. case 5:
  267. return terminal.colorScheme.magenta;
  268. case 6:
  269. return terminal.colorScheme.cyan;
  270. case 7:
  271. return terminal.colorScheme.white;
  272. case 8:
  273. return terminal.colorScheme.brightBlack;
  274. case 9:
  275. return terminal.colorScheme.brightRed;
  276. case 10:
  277. return terminal.colorScheme.brightGreen;
  278. case 11:
  279. return terminal.colorScheme.brightYellow;
  280. case 12:
  281. return terminal.colorScheme.brightBlue;
  282. case 13:
  283. return terminal.colorScheme.brightMagenta;
  284. case 14:
  285. return terminal.colorScheme.brightCyan;
  286. case 15:
  287. return terminal.colorScheme.white;
  288. }
  289. if (colNum < 232) {
  290. var r = 0;
  291. var g = 0;
  292. var b = 0;
  293. final index = colNum - 16;
  294. for (var i = 0; i < index; i++) {
  295. if (b == 0) {
  296. b = 95;
  297. } else if (b < 255) {
  298. b += 40;
  299. } else {
  300. b = 0;
  301. if (g == 0) {
  302. g = 95;
  303. } else if (g < 255) {
  304. g += 40;
  305. } else {
  306. g = 0;
  307. if (r == 0) {
  308. r = 95;
  309. } else if (r < 255) {
  310. r += 40;
  311. } else {
  312. break;
  313. }
  314. }
  315. }
  316. }
  317. return CellColor.fromARGB(0xff, r, g, b);
  318. }
  319. return CellColor(grayscaleColors[colNum.clamp(232, 255)]);
  320. }