Advertisement
Gottox

Untitled

Apr 27th, 2012
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.93 KB | None | 0 0
  1. /*
  2. Javascript Terminal
  3.  
  4. Copyright (c) 2011 Fabrice Bellard
  5.  
  6. Redistribution or commercial use is prohibited without the author's
  7. permission.
  8. */
  9. "use strict";
  10. if (!Function.prototype.bind) {
  11. Function.prototype.bind = function (aa) {
  12. var ba = [].slice,
  13. ca = ba.call(arguments, 1),
  14. self = this,
  15. da = function () {},
  16. ea = function () {
  17. return self.apply(this instanceof da ? this : (aa || {}), ca.concat(ba.call(arguments)));
  18. };
  19. da.prototype = self.prototype;
  20. ea.prototype = new da();
  21. return ea;
  22. };
  23. }
  24. function Term(fa, ga, ha) {
  25. this.w = fa;
  26. this.h = ga;
  27. this.x = 0;
  28. this.y = 0;
  29. this.cursorstate = 0;
  30. this.handler = ha;
  31. this.convert_lf_to_crlf = false;
  32. this.state = 0;
  33. this.output_queue = "";
  34. this.bg_colors = ["#000000", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff"];
  35. this.fg_colors = ["#000000", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff"];
  36. this.def_attr = (7 << 3) | 0;
  37. this.cur_attr = this.def_attr;
  38. this.is_mac = (navigator.userAgent.indexOf("Mac") >= 0) ? true : false;
  39. this.key_rep_state = 0;
  40. this.key_rep_str = "";
  41. }
  42. Term.prototype.open = function () {
  43. var y, ia, i, ja, c;
  44. this.lines = new Array();
  45. c = 32 | (this.def_attr << 16);
  46. for (y = 0; y < this.h; y++) {
  47. ia = new Array();
  48. for (i = 0; i < this.w; i++) ia[i] = c;
  49. this.lines[y] = ia;
  50. }
  51. document.writeln('<table border="0" cellspacing="0" cellpadding="0">');
  52. for (y = 0; y < this.h; y++) {
  53. document.writeln('<tr><td class="term" id="tline' + y + '"></td></tr>');
  54. }
  55. document.writeln('</table>');
  56. this.refresh(0, this.h - 1);
  57. document.addEventListener("keydown", this.keyDownHandler.bind(this), true);
  58. document.addEventListener("keypress", this.keyPressHandler.bind(this), true);
  59. ja = this;
  60. setInterval(function () {
  61. ja.cursor_timer_cb();
  62. }, 1000);
  63. };
  64. Term.prototype.refresh = function (ka, la) {
  65. var ma, y, ia, na, c, w, i, oa, pa, qa, ra, sa;
  66. for (y = ka; y <= la; y++) {
  67. ia = this.lines[y];
  68. na = "";
  69. w = this.w;
  70. if (y == this.y && this.cursor_state) {
  71. oa = this.x;
  72. } else {
  73. oa = -1;
  74. }
  75. qa = this.def_attr;
  76. for (i = 0; i < w; i++) {
  77. c = ia[i];
  78. pa = c >> 16;
  79. c &= 0xffff;
  80. if (i == oa) {
  81. pa = -1;
  82. }
  83. if (pa != qa) {
  84. if (qa != this.def_attr) na += '</span>';
  85. if (pa != this.def_attr) {
  86. if (pa == -1) {
  87. na += '<span class="termReverse">';
  88. } else {
  89. na += '<span style="';
  90. ra = (pa >> 3) & 7;
  91. sa = pa & 7;
  92. if (ra != 7) {
  93. na += 'color:' + this.fg_colors[ra] + ';';
  94. }
  95. if (sa != 0) {
  96. na += 'background-color:' + this.bg_colors[sa] + ';';
  97. }
  98. na += '">';
  99. }
  100. }
  101. }
  102. switch (c) {
  103. case 32:
  104. na += "&nbsp;";
  105. break;
  106. case 38:
  107. na += "&amp;";
  108. break;
  109. case 60:
  110. na += "&lt;";
  111. break;
  112. case 62:
  113. na += "&gt;";
  114. break;
  115. default:
  116. if (c < 32) {
  117. na += "&nbsp;";
  118. } else {
  119. na += String.fromCharCode(c);
  120. }
  121. break;
  122. }
  123. qa = pa;
  124. }
  125. if (qa != this.def_attr) {
  126. na += '</span>';
  127. }
  128. ma = document.getElementById("tline" + y);
  129. ma.innerHTML = na;
  130. }
  131. };
  132. Term.prototype.cursor_timer_cb = function () {
  133. this.cursor_state ^= 1;
  134. this.refresh(this.y, this.y);
  135. };
  136. Term.prototype.show_cursor = function () {
  137. if (!this.cursor_state) {
  138. this.cursor_state = 1;
  139. this.refresh(this.y, this.y);
  140. }
  141. };
  142. Term.prototype.scroll = function () {
  143. var y, ia, x, c;
  144. for (y = 0; y < this.h; y++) this.lines[y] = this.lines[y + 1];
  145. c = 32 | (this.def_attr << 16);
  146. ia = new Array();
  147. for (x = 0; x < this.w; x++) ia[x] = c;
  148. this.lines[this.h - 1] = ia;
  149. };
  150. Term.prototype.write = function (ta) {
  151. function ua(y) {
  152. ka = Math.min(ka, y);
  153. la = Math.max(la, y);
  154. }
  155. function va(s, x, y) {
  156. var l, i, c;
  157. l = s.lines[y];
  158. c = 32 | (s.def_attr << 16);
  159. for (i = x; i < s.w; i++) l[i] = c;
  160. ua(y);
  161. }
  162. function wa(s, xa) {
  163. var j, n;
  164. if (xa.length == 0) {
  165. s.cur_attr = s.def_attr;
  166. } else {
  167. for (j = 0; j < xa.length; j++) {
  168. n = xa[j];
  169. if (n >= 30 && n <= 37) {
  170. s.cur_attr = (s.cur_attr & ~ (7 << 3)) | ((n - 30) << 3);
  171. } else if (n >= 40 && n <= 47) {
  172. s.cur_attr = (s.cur_attr & ~7) | (n - 40);
  173. } else if (n == 0) {
  174. s.cur_attr = s.def_attr;
  175. }
  176. }
  177. }
  178. }
  179. var ya = 0;
  180. var za = 1;
  181. var Aa = 2;
  182. var i, c, ka, la, l, n, j;
  183. ka = this.h;
  184. la = -1;
  185. ua(this.y);
  186. for (i = 0; i < ta.length; i++) {
  187. c = ta.charCodeAt(i);
  188. switch (this.state) {
  189. case ya:
  190. switch (c) {
  191. case 10:
  192. if (this.convert_lf_to_crlf) {
  193. this.x = 0;
  194. }
  195. this.y++;
  196. if (this.y >= this.h) {
  197. this.y--;
  198. this.scroll();
  199. ka = 0;
  200. la = this.h - 1;
  201. }
  202. break;
  203. case 13:
  204. this.x = 0;
  205. break;
  206. case 8:
  207. if (this.x > 0) {
  208. this.x--;
  209. }
  210. break;
  211. case 9:
  212. n = (this.x + 8) & ~7;
  213. if (n <= this.w) {
  214. this.x = n;
  215. }
  216. break;
  217. case 27:
  218. this.state = za;
  219. break;
  220. default:
  221. if (c >= 32) {
  222. if (this.x >= this.w) {
  223. this.x = 0;
  224. this.y++;
  225. if (this.y >= this.h) {
  226. this.y--;
  227. this.scroll();
  228. ka = 0;
  229. la = this.h - 1;
  230. }
  231. }
  232. this.lines[this.y][this.x] = (c & 0xffff) | (this.cur_attr << 16);
  233. this.x++;
  234. ua(this.y);
  235. }
  236. break;
  237. }
  238. break;
  239. case za:
  240. if (c == 91) {
  241. this.esc_params = new Array();
  242. this.cur_param = 0;
  243. this.state = Aa;
  244. } else {
  245. this.state = ya;
  246. }
  247. break;
  248. case Aa:
  249. if (c >= 48 && c <= 57) {
  250. this.cur_param = this.cur_param * 10 + c - 48;
  251. } else {
  252. this.esc_params[this.esc_params.length] = this.cur_param;
  253. this.cur_param = 0;
  254. if (c == 59) break;
  255. this.state = ya;
  256. switch (c) {
  257. case 65:
  258. n = this.esc_params[0];
  259. if (n < 1) n = 1;
  260. this.y -= n;
  261. if (this.y < 0) this.y = 0;
  262. break;
  263. case 66:
  264. n = this.esc_params[0];
  265. if (n < 1) n = 1;
  266. this.y += n;
  267. if (this.y >= this.h) this.y = this.h - 1;
  268. break;
  269. case 67:
  270. n = this.esc_params[0];
  271. if (n < 1) n = 1;
  272. this.x += n;
  273. if (this.x >= this.w - 1) this.x = this.w - 1;
  274. break;
  275. case 68:
  276. n = this.esc_params[0];
  277. if (n < 1) n = 1;
  278. this.x -= n;
  279. if (this.x < 0) this.x = 0;
  280. break;
  281. case 72:
  282. {
  283. var Ba, Ca;
  284. Ca = this.esc_params[0] - 1;
  285. if (this.esc_params.length >= 2) Ba = this.esc_params[1] - 1;
  286. else Ba = 0;
  287. if (Ca < 0) Ca = 0;
  288. else if (Ca >= this.h) Ca = this.h - 1;
  289. if (Ba < 0) Ba = 0;
  290. else if (Ba >= this.w) Ba = this.w - 1;
  291. this.x = Ba;
  292. this.y = Ca;
  293. }
  294. break;
  295. case 74:
  296. va(this, this.x, this.y);
  297. for (j = this.y + 1; j < this.h; j++) va(this, 0, j);
  298. break;
  299. case 75:
  300. va(this, this.x, this.y);
  301. break;
  302. case 109:
  303. wa(this, this.esc_params);
  304. break;
  305. case 110:
  306. this.queue_chars("\x1b[" + (this.y + 1) + ";" + (this.x + 1) + "R");
  307. break;
  308. default:
  309. break;
  310. }
  311. }
  312. break;
  313. }
  314. }
  315. ua(this.y);
  316. if (la >= ka) this.refresh(ka, la);
  317. };
  318. Term.prototype.writeln = function (ta) {
  319. this.write(ta + '\r\n');
  320. };
  321. Term.prototype.keyDownHandler = function (Da) {
  322. var ta;
  323. ta = "";
  324. switch (Da.keyCode) {
  325. case 8:
  326. ta = "";
  327. break;
  328. case 9:
  329. ta = "\t";
  330. break;
  331. case 13:
  332. ta = "\r";
  333. break;
  334. case 27:
  335. ta = "\x1b";
  336. break;
  337. case 37:
  338. ta = "\x1b[D";
  339. break;
  340. case 39:
  341. ta = "\x1b[C";
  342. break;
  343. case 38:
  344. ta = "\x1b[A";
  345. break;
  346. case 40:
  347. ta = "\x1b[B";
  348. break;
  349. case 46:
  350. ta = "\x1b[3~";
  351. break;
  352. case 45:
  353. ta = "\x1b[2~";
  354. break;
  355. case 36:
  356. ta = "\x1bOH";
  357. break;
  358. case 35:
  359. ta = "\x1bOF";
  360. break;
  361. case 33:
  362. ta = "\x1b[5~";
  363. break;
  364. case 34:
  365. ta = "\x1b[6~";
  366. break;
  367. default:
  368. if (Da.ctrlKey) {
  369. if (Da.keyCode >= 65 && Da.keyCode <= 90) {
  370. ta = String.fromCharCode(Da.keyCode - 64);
  371. } else if (Da.keyCode == 32) {
  372. ta = String.fromCharCode(0);
  373. }
  374. } else if ((!this.is_mac && Da.altKey) || (this.is_mac && Da.metaKey)) {
  375. if (Da.keyCode >= 65 && Da.keyCode <= 90) {
  376. ta = "\x1b" + String.fromCharCode(Da.keyCode + 32);
  377. }
  378. }
  379. break;
  380. }
  381. if (ta) {
  382. if (Da.stopPropagation) Da.stopPropagation();
  383. if (Da.preventDefault) Da.preventDefault();
  384. this.show_cursor();
  385. this.key_rep_state = 1;
  386. this.key_rep_str = ta;
  387. this.handler(ta);
  388. return false;
  389. } else {
  390. this.key_rep_state = 0;
  391. return true;
  392. }
  393. };
  394. Term.prototype.keyPressHandler = function (Da) {
  395. var ta, Ea;
  396. if (Da.stopPropagation) Da.stopPropagation();
  397. if (Da.preventDefault) Da.preventDefault();
  398. ta = "";
  399. if (!("charCode" in Da)) {
  400. Ea = Da.keyCode;
  401. if (this.key_rep_state == 1) {
  402. this.key_rep_state = 2;
  403. return false;
  404. } else if (this.key_rep_state == 2) {
  405. this.show_cursor();
  406. this.handler(this.key_rep_str);
  407. return false;
  408. }
  409. } else {
  410. Ea = Da.charCode;
  411. }
  412. if (Ea != 0) {
  413. if (!Da.ctrlKey && ((!this.is_mac && !Da.altKey) || (this.is_mac && !Da.metaKey))) {
  414. ta = String.fromCharCode(Ea);
  415. }
  416. }
  417. if (ta) {
  418. this.show_cursor();
  419. this.handler(ta);
  420. return false;
  421. } else {
  422. return true;
  423. }
  424. };
  425. Term.prototype.queue_chars = function (ta) {
  426. this.output_queue += ta;
  427. if (this.output_queue) setTimeout(this.outputHandler.bind(this), 0);
  428. };
  429. Term.prototype.outputHandler = function () {
  430. if (this.output_queue) {
  431. this.handler(this.output_queue);
  432. this.output_queue = "";
  433. }
  434. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement