PageRenderTime 88ms CodeModel.GetById 476ms app.highlight 521ms RepoModel.GetById 118ms app.codeStats 2ms

/butterfly/static/main.js

https://github.com/PKUbuntu/butterfly
JavaScript | 2891 lines | 2730 code | 160 blank | 1 comment | 560 complexity | 4cac6a01a99d89cee09c0c422076a746 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1(function() {
   2  var $, Selection, State, Terminal, alt, bench, cancel, cbench, cols, ctl, ctrl, first, next_leaf, open_ts, previous_leaf, quit, rows, s, selection, send, term, virtual_input, ws, ws_url,
   3    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
   4    __slice = [].slice;
   5
   6  cancel = function(ev) {
   7    if (ev.preventDefault) {
   8      ev.preventDefault();
   9    }
  10    if (ev.stopPropagation) {
  11      ev.stopPropagation();
  12    }
  13    ev.cancelBubble = true;
  14    return false;
  15  };
  16
  17  s = 0;
  18
  19  State = {
  20    normal: s++,
  21    escaped: s++,
  22    csi: s++,
  23    osc: s++,
  24    charset: s++,
  25    dcs: s++,
  26    ignore: s++
  27  };
  28
  29  Terminal = (function() {
  30    function Terminal(parent, out, ctl) {
  31      var div, i, term_size;
  32      this.parent = parent;
  33      this.out = out;
  34      this.ctl = ctl != null ? ctl : function() {};
  35      this.context = this.parent.ownerDocument.defaultView;
  36      this.document = this.parent.ownerDocument;
  37      this.body = this.document.getElementsByTagName('body')[0];
  38      this.element = this.document.createElement('div');
  39      this.element.className = 'terminal focus';
  40      this.element.style.outline = 'none';
  41      this.element.setAttribute('tabindex', 0);
  42      this.parent.appendChild(this.element);
  43      div = this.document.createElement('div');
  44      div.className = 'line';
  45      this.element.appendChild(div);
  46      this.children = [div];
  47      this.compute_char_size();
  48      div.style.height = this.char_size.height + 'px';
  49      term_size = this.parent.getBoundingClientRect();
  50      this.cols = Math.floor(term_size.width / this.char_size.width);
  51      this.rows = Math.floor(term_size.height / this.char_size.height);
  52      i = this.rows - 1;
  53      while (i--) {
  54        div = this.document.createElement('div');
  55        div.style.height = this.char_size.height + 'px';
  56        div.className = 'line';
  57        this.element.appendChild(div);
  58        this.children.push(div);
  59      }
  60      this.scrollback = 100000;
  61      this.visualBell = 100;
  62      this.convertEol = false;
  63      this.termName = 'xterm';
  64      this.cursorBlink = true;
  65      this.cursorState = 0;
  66      this.last_cc = 0;
  67      this.reset_vars();
  68      this.refresh(0, this.rows - 1);
  69      this.focus();
  70      this.startBlink();
  71      addEventListener('keydown', this.keyDown.bind(this));
  72      addEventListener('keypress', this.keyPress.bind(this));
  73      addEventListener('focus', this.focus.bind(this));
  74      addEventListener('blur', this.blur.bind(this));
  75      addEventListener('paste', this.paste.bind(this));
  76      addEventListener('resize', this.resize.bind(this));
  77      if (typeof InstallTrigger !== "undefined") {
  78        this.element.contentEditable = 'true';
  79        this.element.addEventListener("mouseup", function() {
  80          var sel;
  81          sel = getSelection().getRangeAt(0);
  82          if (sel.startOffset === sel.endOffset) {
  83            return getSelection().removeAllRanges();
  84          }
  85        });
  86      }
  87      this.initmouse();
  88      setTimeout(this.resize.bind(this), 100);
  89    }
  90
  91    Terminal.prototype.reset_vars = function() {
  92      var i;
  93      this.ybase = 0;
  94      this.ydisp = 0;
  95      this.x = 0;
  96      this.y = 0;
  97      this.cursorHidden = false;
  98      this.state = State.normal;
  99      this.queue = '';
 100      this.scrollTop = 0;
 101      this.scrollBottom = this.rows - 1;
 102      this.applicationKeypad = false;
 103      this.applicationCursor = false;
 104      this.originMode = false;
 105      this.wraparoundMode = false;
 106      this.normal = null;
 107      this.charset = null;
 108      this.gcharset = null;
 109      this.glevel = 0;
 110      this.charsets = [null];
 111      this.defAttr = (0 << 18) | (257 << 9) | (256 << 0);
 112      this.curAttr = this.defAttr;
 113      this.params = [];
 114      this.currentParam = 0;
 115      this.prefix = "";
 116      this.lines = [];
 117      i = this.rows;
 118      while (i--) {
 119        this.lines.push(this.blankLine());
 120      }
 121      this.setupStops();
 122      return this.skipNextKey = null;
 123    };
 124
 125    Terminal.prototype.compute_char_size = function() {
 126      var test_span;
 127      test_span = document.createElement('span');
 128      test_span.textContent = '0123456789';
 129      this.children[0].appendChild(test_span);
 130      this.char_size = {
 131        width: test_span.getBoundingClientRect().width / 10,
 132        height: this.children[0].getBoundingClientRect().height
 133      };
 134      return this.children[0].removeChild(test_span);
 135    };
 136
 137    Terminal.prototype.eraseAttr = function() {
 138      return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff);
 139    };
 140
 141    Terminal.prototype.focus = function() {
 142      if (this.sendFocus) {
 143        this.send('\x1b[I');
 144      }
 145      this.showCursor();
 146      this.element.classList.add('focus');
 147      return this.element.classList.remove('blur');
 148    };
 149
 150    Terminal.prototype.blur = function() {
 151      this.cursorState = 1;
 152      this.refresh(this.y, this.y);
 153      if (this.sendFocus) {
 154        this.send('\x1b[O');
 155      }
 156      this.element.classList.add('blur');
 157      return this.element.classList.remove('focus');
 158    };
 159
 160    Terminal.prototype.paste = function(ev) {
 161      if (ev.clipboardData) {
 162        this.send(ev.clipboardData.getData('text/plain'));
 163      } else if (this.context.clipboardData) {
 164        this.send(this.context.clipboardData.getData('Text'));
 165      }
 166      return cancel(ev);
 167    };
 168
 169    Terminal.prototype.initmouse = function() {
 170      var encode, getButton, getCoords, pressed, sendButton, sendEvent, sendMove;
 171      pressed = 32;
 172      sendButton = function(ev) {
 173        var button, pos;
 174        button = getButton(ev);
 175        pos = getCoords(ev);
 176        if (!pos) {
 177          return;
 178        }
 179        sendEvent(button, pos);
 180        switch (ev.type) {
 181          case "mousedown":
 182            return pressed = button;
 183          case "mouseup":
 184            return pressed = 32;
 185        }
 186      };
 187      sendMove = function(ev) {
 188        var button, pos;
 189        button = pressed;
 190        pos = getCoords(ev);
 191        if (!pos) {
 192          return;
 193        }
 194        button += 32;
 195        return sendEvent(button, pos);
 196      };
 197      encode = (function(_this) {
 198        return function(data, ch) {
 199          if (!_this.utfMouse) {
 200            if (ch === 255) {
 201              return data.push(0);
 202            }
 203            if (ch > 127) {
 204              ch = 127;
 205            }
 206            return data.push(ch);
 207          } else {
 208            if (ch === 2047) {
 209              return data.push(0);
 210            }
 211            if (ch < 127) {
 212              return data.push(ch);
 213            } else {
 214              if (ch > 2047) {
 215                ch = 2047;
 216              }
 217              data.push(0xC0 | (ch >> 6));
 218              return data.push(0x80 | (ch & 0x3F));
 219            }
 220          }
 221        };
 222      })(this);
 223      sendEvent = (function(_this) {
 224        return function(button, pos) {
 225          var data;
 226          if (_this.urxvtMouse) {
 227            pos.x -= 32;
 228            pos.y -= 32;
 229            pos.x++;
 230            pos.y++;
 231            _this.send("\x1b[" + button + ";" + pos.x + ";" + pos.y + "M");
 232            return;
 233          }
 234          if (_this.sgrMouse) {
 235            pos.x -= 32;
 236            pos.y -= 32;
 237            _this.send("\x1b[<" + ((button & 3) === 3 ? button & ~3 : button) + ";" + pos.x + ";" + pos.y + ((button & 3) === 3 ? "m" : "M"));
 238            return;
 239          }
 240          data = [];
 241          encode(data, button);
 242          encode(data, pos.x);
 243          encode(data, pos.y);
 244          return _this.send("\x1b[M" + String.fromCharCode.apply(String, data));
 245        };
 246      })(this);
 247      getButton = (function(_this) {
 248        return function(ev) {
 249          var button, ctrl, meta, mod, shift;
 250          switch (ev.type) {
 251            case "mousedown":
 252              button = ev.button != null ? +ev.button : (ev.which != null ? ev.which - 1 : null);
 253              break;
 254            case "mouseup":
 255              button = 3;
 256              break;
 257            case "wheel":
 258              button = ev.deltaY < 0 ? 64 : 65;
 259          }
 260          shift = ev.shiftKey ? 4 : 0;
 261          meta = ev.metaKey ? 8 : 0;
 262          ctrl = ev.ctrlKey ? 16 : 0;
 263          mod = shift | meta | ctrl;
 264          if (_this.vt200Mouse) {
 265            mod &= ctrl;
 266          } else {
 267            if (!_this.normalMouse) {
 268              mod = 0;
 269            }
 270          }
 271          return (32 + (mod << 2)) + button;
 272        };
 273      })(this);
 274      getCoords = (function(_this) {
 275        return function(ev) {
 276          var el, h, w, x, y;
 277          x = ev.pageX;
 278          y = ev.pageY;
 279          el = _this.element;
 280          while (el && el !== _this.document.documentElement) {
 281            x -= el.offsetLeft;
 282            y -= el.offsetTop;
 283            el = "offsetParent" in el ? el.offsetParent : el.parentNode;
 284          }
 285          w = _this.element.clientWidth;
 286          h = _this.element.clientHeight;
 287          x = Math.ceil((x / w) * _this.cols);
 288          y = Math.ceil((y / h) * _this.rows);
 289          if (x < 0) {
 290            x = 0;
 291          }
 292          if (x > _this.cols) {
 293            x = _this.cols;
 294          }
 295          if (y < 0) {
 296            y = 0;
 297          }
 298          if (y > _this.rows) {
 299            y = _this.rows;
 300          }
 301          x += 32;
 302          y += 32;
 303          return {
 304            x: x,
 305            y: y,
 306            type: ev.type
 307          };
 308        };
 309      })(this);
 310      addEventListener("mousedown", (function(_this) {
 311        return function(ev) {
 312          var sm, up;
 313          if (!_this.mouseEvents) {
 314            return;
 315          }
 316          sendButton(ev);
 317          if (_this.vt200Mouse) {
 318            sendButton({
 319              __proto__: ev,
 320              type: "mouseup"
 321            });
 322            return cancel(ev);
 323          }
 324          sm = sendMove.bind(_this);
 325          if (_this.normalMouse) {
 326            addEventListener("mousemove", sm);
 327          }
 328          if (!_this.x10Mouse) {
 329            addEventListener("mouseup", up = function(ev) {
 330              sendButton(ev);
 331              if (_this.normalMouse) {
 332                removeEventListener("mousemove", sm);
 333              }
 334              removeEventListener("mouseup", up);
 335              return cancel(ev);
 336            });
 337          }
 338          return cancel(ev);
 339        };
 340      })(this));
 341      return addEventListener("wheel", (function(_this) {
 342        return function(ev) {
 343          if (_this.mouseEvents) {
 344            if (_this.x10Mouse) {
 345              return;
 346            }
 347            sendButton(ev);
 348          } else {
 349            if (_this.applicationKeypad) {
 350              return;
 351            }
 352            _this.scrollDisp(ev.deltaY > 0 ? 5 : -5);
 353          }
 354          return cancel(ev);
 355        };
 356      })(this));
 357    };
 358
 359    Terminal.prototype.refresh = function(start, end) {
 360      var attr, bg, ch, classes, data, fg, flags, i, line, out, parent, row, width, x, y;
 361      if (end - start >= this.rows / 3) {
 362        parent = this.element.parentNode;
 363        if (parent != null) {
 364          parent.removeChild(this.element);
 365        }
 366      }
 367      width = this.cols;
 368      y = start;
 369      if (end >= this.lines.length) {
 370        end = this.lines.length - 1;
 371      }
 372      while (y <= end) {
 373        row = y + this.ydisp;
 374        line = this.lines[row];
 375        out = "";
 376        if (y === this.y && (this.ydisp === this.ybase || this.selectMode) && !this.cursorHidden) {
 377          x = this.x;
 378        } else {
 379          x = -Infinity;
 380        }
 381        attr = this.defAttr;
 382        i = 0;
 383        while (i < width) {
 384          data = line[i][0];
 385          ch = line[i][1];
 386          if (data !== attr) {
 387            if (attr !== this.defAttr) {
 388              out += "</span>";
 389            }
 390            if (data !== this.defAttr) {
 391              classes = [];
 392              out += "<span ";
 393              bg = data & 0x1ff;
 394              fg = (data >> 9) & 0x1ff;
 395              flags = data >> 18;
 396              if (flags & 1) {
 397                classes.push("bold");
 398              }
 399              if (flags & 2) {
 400                classes.push("underline");
 401              }
 402              if (flags & 4) {
 403                classes.push("blink");
 404              }
 405              if (flags & 8) {
 406                classes.push("reverse-video");
 407              }
 408              if (flags & 16) {
 409                classes.push("invisible");
 410              }
 411              if (flags & 1 && fg < 8) {
 412                fg += 8;
 413              }
 414              classes.push("bg-color-" + bg);
 415              classes.push("fg-color-" + fg);
 416              out += "class=\"";
 417              out += classes.join(" ");
 418              out += "\">";
 419            }
 420          }
 421          if (i === x) {
 422            out += "<span class=\"" + (this.cursorState ? "reverse-video " : "") + "cursor\">";
 423          }
 424          if (ch.length > 1) {
 425            out += ch;
 426          } else {
 427            switch (ch) {
 428              case "&":
 429                out += "&amp;";
 430                break;
 431              case "<":
 432                out += "&lt;";
 433                break;
 434              case ">":
 435                out += "&gt;";
 436                break;
 437              default:
 438                if (ch <= " ") {
 439                  out += "&nbsp;";
 440                } else {
 441                  if (("\uff00" < ch && ch < "\uffef")) {
 442                    i++;
 443                  }
 444                  out += ch;
 445                }
 446            }
 447          }
 448          if (i === x) {
 449            out += "</span>";
 450          }
 451          attr = data;
 452          i++;
 453        }
 454        if (attr !== this.defAttr) {
 455          out += "</span>";
 456        }
 457        this.children[y].innerHTML = out;
 458        y++;
 459      }
 460      return parent != null ? parent.appendChild(this.element) : void 0;
 461    };
 462
 463    Terminal.prototype._cursorBlink = function() {
 464      var cursor;
 465      this.cursorState ^= 1;
 466      cursor = this.element.querySelector(".cursor");
 467      if (!cursor) {
 468        return;
 469      }
 470      if (cursor.classList.contains("reverse-video")) {
 471        return cursor.classList.remove("reverse-video");
 472      } else {
 473        return cursor.classList.add("reverse-video");
 474      }
 475    };
 476
 477    Terminal.prototype.showCursor = function() {
 478      if (!this.cursorState) {
 479        this.cursorState = 1;
 480        return this.refresh(this.y, this.y);
 481      }
 482    };
 483
 484    Terminal.prototype.startBlink = function() {
 485      if (!this.cursorBlink) {
 486        return;
 487      }
 488      this._blinker = (function(_this) {
 489        return function() {
 490          return _this._cursorBlink();
 491        };
 492      })(this);
 493      return this.t_blink = setInterval(this._blinker, 500);
 494    };
 495
 496    Terminal.prototype.refreshBlink = function() {
 497      if (!this.cursorBlink) {
 498        return;
 499      }
 500      clearInterval(this.t_blink);
 501      return this.t_blink = setInterval(this._blinker, 500);
 502    };
 503
 504    Terminal.prototype.scroll = function() {
 505      var row;
 506      if (++this.ybase === this.scrollback) {
 507        this.ybase = this.ybase / 2 | 0;
 508        this.lines = this.lines.slice(-(this.ybase + this.rows) + 1);
 509      }
 510      this.ydisp = this.ybase;
 511      row = this.ybase + this.rows - 1;
 512      row -= this.rows - 1 - this.scrollBottom;
 513      if (row === this.lines.length) {
 514        this.lines.push(this.blankLine());
 515      } else {
 516        this.lines.splice(row, 0, this.blankLine());
 517      }
 518      if (this.scrollTop !== 0) {
 519        if (this.ybase !== 0) {
 520          this.ybase--;
 521          this.ydisp = this.ybase;
 522        }
 523        this.lines.splice(this.ybase + this.scrollTop, 1);
 524      }
 525      this.updateRange(this.scrollTop);
 526      return this.updateRange(this.scrollBottom);
 527    };
 528
 529    Terminal.prototype.scrollDisp = function(disp) {
 530      this.ydisp += disp;
 531      if (this.ydisp > this.ybase) {
 532        this.ydisp = this.ybase;
 533      } else {
 534        if (this.ydisp < 0) {
 535          this.ydisp = 0;
 536        }
 537      }
 538      return this.refresh(0, this.rows - 1);
 539    };
 540
 541    Terminal.prototype.write = function(data) {
 542      var ch, cs, i, j, l, pt, valid, _ref;
 543      this.refreshStart = this.y;
 544      this.refreshEnd = this.y;
 545      if (this.ybase !== this.ydisp) {
 546        this.ydisp = this.ybase;
 547        this.maxRange();
 548      }
 549      i = 0;
 550      l = data.length;
 551      while (i < l) {
 552        ch = data[i];
 553        switch (this.state) {
 554          case State.normal:
 555            switch (ch) {
 556              case "\x07":
 557                this.bell();
 558                break;
 559              case "\n":
 560              case "\x0b":
 561              case "\x0c":
 562                if (this.convertEol) {
 563                  this.x = 0;
 564                }
 565                this.y++;
 566                if (this.y > this.scrollBottom) {
 567                  this.y--;
 568                  this.scroll();
 569                }
 570                break;
 571              case "\r":
 572                this.x = 0;
 573                break;
 574              case "\b":
 575                if (this.x > 0) {
 576                  this.x--;
 577                }
 578                break;
 579              case "\t":
 580                this.x = this.nextStop();
 581                break;
 582              case "\x0e":
 583                this.setgLevel(1);
 584                break;
 585              case "\x0f":
 586                this.setgLevel(0);
 587                break;
 588              case "\x1b":
 589                this.state = State.escaped;
 590                break;
 591              default:
 592                if (ch >= " ") {
 593                  if ((_ref = this.charset) != null ? _ref[ch] : void 0) {
 594                    ch = this.charset[ch];
 595                  }
 596                  if (this.x >= this.cols) {
 597                    this.x = 0;
 598                    this.y++;
 599                    if (this.y > this.scrollBottom) {
 600                      this.y--;
 601                      this.scroll();
 602                    }
 603                  }
 604                  this.lines[this.y + this.ybase][this.x] = [this.curAttr, ch];
 605                  this.x++;
 606                  this.updateRange(this.y);
 607                  if (("\uff00" < ch && ch < "\uffef")) {
 608                    j = this.y + this.ybase;
 609                    if (this.cols < 2 || this.x >= this.cols) {
 610                      this.lines[j][this.x - 1] = [this.curAttr, " "];
 611                      break;
 612                    }
 613                    this.lines[j][this.x] = [this.curAttr, " "];
 614                    this.x++;
 615                  }
 616                }
 617            }
 618            break;
 619          case State.escaped:
 620            switch (ch) {
 621              case "[":
 622                this.params = [];
 623                this.currentParam = 0;
 624                this.state = State.csi;
 625                break;
 626              case "]":
 627                this.params = [];
 628                this.currentParam = 0;
 629                this.state = State.osc;
 630                break;
 631              case "P":
 632                this.params = [];
 633                this.currentParam = 0;
 634                this.state = State.dcs;
 635                break;
 636              case "_":
 637                this.state = State.ignore;
 638                break;
 639              case "^":
 640                this.state = State.ignore;
 641                break;
 642              case "c":
 643                this.reset();
 644                break;
 645              case "E":
 646                this.x = 0;
 647                this.index();
 648                break;
 649              case "D":
 650                this.index();
 651                break;
 652              case "M":
 653                this.reverseIndex();
 654                break;
 655              case "%":
 656                this.setgLevel(0);
 657                this.setgCharset(0, Terminal.prototype.charsets.US);
 658                this.state = State.normal;
 659                i++;
 660                break;
 661              case "(":
 662              case ")":
 663              case "*":
 664              case "+":
 665              case "-":
 666              case ".":
 667                switch (ch) {
 668                  case "(":
 669                    this.gcharset = 0;
 670                    break;
 671                  case ")":
 672                  case "-":
 673                    this.gcharset = 1;
 674                    break;
 675                  case "*":
 676                  case ".":
 677                    this.gcharset = 2;
 678                    break;
 679                  case "+":
 680                    this.gcharset = 3;
 681                }
 682                this.state = State.charset;
 683                break;
 684              case "/":
 685                this.gcharset = 3;
 686                this.state = State.charset;
 687                i--;
 688                break;
 689              case "n":
 690                this.setgLevel(2);
 691                break;
 692              case "o":
 693                this.setgLevel(3);
 694                break;
 695              case "|":
 696                this.setgLevel(3);
 697                break;
 698              case "}":
 699                this.setgLevel(2);
 700                break;
 701              case "~":
 702                this.setgLevel(1);
 703                break;
 704              case "7":
 705                this.saveCursor();
 706                this.state = State.normal;
 707                break;
 708              case "8":
 709                this.restoreCursor();
 710                this.state = State.normal;
 711                break;
 712              case "#":
 713                this.state = State.normal;
 714                i++;
 715                break;
 716              case "H":
 717                this.tabSet();
 718                break;
 719              case "=":
 720                this.applicationKeypad = true;
 721                this.state = State.normal;
 722                break;
 723              case ">":
 724                this.applicationKeypad = false;
 725                this.state = State.normal;
 726                break;
 727              default:
 728                this.state = State.normal;
 729                console.log("Unknown ESC control:", ch);
 730            }
 731            break;
 732          case State.charset:
 733            switch (ch) {
 734              case "0":
 735                cs = Terminal.prototype.charsets.SCLD;
 736                break;
 737              case "A":
 738                cs = Terminal.prototype.charsets.UK;
 739                break;
 740              case "B":
 741                cs = Terminal.prototype.charsets.US;
 742                break;
 743              case "4":
 744                cs = Terminal.prototype.charsets.Dutch;
 745                break;
 746              case "C":
 747              case "5":
 748                cs = Terminal.prototype.charsets.Finnish;
 749                break;
 750              case "R":
 751                cs = Terminal.prototype.charsets.French;
 752                break;
 753              case "Q":
 754                cs = Terminal.prototype.charsets.FrenchCanadian;
 755                break;
 756              case "K":
 757                cs = Terminal.prototype.charsets.German;
 758                break;
 759              case "Y":
 760                cs = Terminal.prototype.charsets.Italian;
 761                break;
 762              case "E":
 763              case "6":
 764                cs = Terminal.prototype.charsets.NorwegianDanish;
 765                break;
 766              case "Z":
 767                cs = Terminal.prototype.charsets.Spanish;
 768                break;
 769              case "H":
 770              case "7":
 771                cs = Terminal.prototype.charsets.Swedish;
 772                break;
 773              case "=":
 774                cs = Terminal.prototype.charsets.Swiss;
 775                break;
 776              case "/":
 777                cs = Terminal.prototype.charsets.ISOLatin;
 778                i++;
 779                break;
 780              default:
 781                cs = Terminal.prototype.charsets.US;
 782            }
 783            this.setgCharset(this.gcharset, cs);
 784            this.gcharset = null;
 785            this.state = State.normal;
 786            break;
 787          case State.osc:
 788            if (ch === "\x1b" || ch === "\x07") {
 789              if (ch === "\x1b") {
 790                i++;
 791              }
 792              this.params.push(this.currentParam);
 793              switch (this.params[0]) {
 794                case 0:
 795                case 1:
 796                case 2:
 797                  if (this.params[1]) {
 798                    this.title = this.params[1] + " - ƸӜƷ butterfly";
 799                    this.handleTitle(this.title);
 800                  }
 801              }
 802              this.params = [];
 803              this.currentParam = 0;
 804              this.state = State.normal;
 805            } else {
 806              if (!this.params.length) {
 807                if (ch >= "0" && ch <= "9") {
 808                  this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;
 809                } else if (ch === ";") {
 810                  this.params.push(this.currentParam);
 811                  this.currentParam = "";
 812                }
 813              } else {
 814                this.currentParam += ch;
 815              }
 816            }
 817            break;
 818          case State.csi:
 819            if (ch === "?" || ch === ">" || ch === "!") {
 820              this.prefix = ch;
 821              break;
 822            }
 823            if (ch >= "0" && ch <= "9") {
 824              this.currentParam = this.currentParam * 10 + ch.charCodeAt(0) - 48;
 825              break;
 826            }
 827            if (ch === "$" || ch === "\"" || ch === " " || ch === "'") {
 828              break;
 829            }
 830            this.params.push(this.currentParam);
 831            this.currentParam = 0;
 832            if (ch === ";") {
 833              break;
 834            }
 835            this.state = State.normal;
 836            switch (ch) {
 837              case "A":
 838                this.cursorUp(this.params);
 839                break;
 840              case "B":
 841                this.cursorDown(this.params);
 842                break;
 843              case "C":
 844                this.cursorForward(this.params);
 845                break;
 846              case "D":
 847                this.cursorBackward(this.params);
 848                break;
 849              case "H":
 850                this.cursorPos(this.params);
 851                break;
 852              case "J":
 853                this.eraseInDisplay(this.params);
 854                break;
 855              case "K":
 856                this.eraseInLine(this.params);
 857                break;
 858              case "m":
 859                if (!this.prefix) {
 860                  this.charAttributes(this.params);
 861                }
 862                break;
 863              case "n":
 864                if (!this.prefix) {
 865                  this.deviceStatus(this.params);
 866                }
 867                break;
 868              case "@":
 869                this.insertChars(this.params);
 870                break;
 871              case "E":
 872                this.cursorNextLine(this.params);
 873                break;
 874              case "F":
 875                this.cursorPrecedingLine(this.params);
 876                break;
 877              case "G":
 878                this.cursorCharAbsolute(this.params);
 879                break;
 880              case "L":
 881                this.insertLines(this.params);
 882                break;
 883              case "M":
 884                this.deleteLines(this.params);
 885                break;
 886              case "P":
 887                this.deleteChars(this.params);
 888                break;
 889              case "X":
 890                this.eraseChars(this.params);
 891                break;
 892              case "`":
 893                this.charPosAbsolute(this.params);
 894                break;
 895              case "a":
 896                this.HPositionRelative(this.params);
 897                break;
 898              case "c":
 899                this.sendDeviceAttributes(this.params);
 900                break;
 901              case "d":
 902                this.linePosAbsolute(this.params);
 903                break;
 904              case "e":
 905                this.VPositionRelative(this.params);
 906                break;
 907              case "f":
 908                this.HVPosition(this.params);
 909                break;
 910              case "h":
 911                this.setMode(this.params);
 912                break;
 913              case "l":
 914                this.resetMode(this.params);
 915                break;
 916              case "r":
 917                this.setScrollRegion(this.params);
 918                break;
 919              case "s":
 920                this.saveCursor(this.params);
 921                break;
 922              case "u":
 923                this.restoreCursor(this.params);
 924                break;
 925              case "I":
 926                this.cursorForwardTab(this.params);
 927                break;
 928              case "S":
 929                this.scrollUp(this.params);
 930                break;
 931              case "T":
 932                if (this.params.length < 2 && !this.prefix) {
 933                  this.scrollDown(this.params);
 934                }
 935                break;
 936              case "Z":
 937                this.cursorBackwardTab(this.params);
 938                break;
 939              case "b":
 940                this.repeatPrecedingCharacter(this.params);
 941                break;
 942              case "g":
 943                this.tabClear(this.params);
 944                break;
 945              case "p":
 946                if (this.prefix === '!') {
 947                  this.softReset(this.params);
 948                }
 949                break;
 950              default:
 951                console.error("Unknown CSI code: %s.", ch);
 952            }
 953            this.prefix = "";
 954            break;
 955          case State.dcs:
 956            if (ch === "\x1b" || ch === "\x07") {
 957              if (ch === "\x1b") {
 958                i++;
 959              }
 960              switch (this.prefix) {
 961                case "":
 962                  break;
 963                case "$q":
 964                  pt = this.currentParam;
 965                  valid = false;
 966                  switch (pt) {
 967                    case "\"q":
 968                      pt = "0\"q";
 969                      break;
 970                    case "\"p":
 971                      pt = "61\"p";
 972                      break;
 973                    case "r":
 974                      pt = "" + (this.scrollTop + 1) + ";" + (this.scrollBottom + 1) + "r";
 975                      break;
 976                    case "m":
 977                      pt = "0m";
 978                      break;
 979                    default:
 980                      console.error("Unknown DCS Pt: %s.", pt);
 981                      pt = "";
 982                  }
 983                  this.send("\x1bP" + +valid + "$r" + pt + "\x1b\\");
 984                  break;
 985                case "+q":
 986                  pt = this.currentParam;
 987                  valid = false;
 988                  this.send("\x1bP" + +valid + "+r" + pt + "\x1b\\");
 989                  break;
 990                default:
 991                  console.error("Unknown DCS prefix: %s.", this.prefix);
 992              }
 993              this.currentParam = 0;
 994              this.prefix = "";
 995              this.state = State.normal;
 996            } else if (!this.currentParam) {
 997              if (!this.prefix && ch !== "$" && ch !== "+") {
 998                this.currentParam = ch;
 999              } else if (this.prefix.length === 2) {
1000                this.currentParam = ch;
1001              } else {
1002                this.prefix += ch;
1003              }
1004            } else {
1005              this.currentParam += ch;
1006            }
1007            break;
1008          case State.ignore:
1009            if (ch === "\x1b" || ch === "\x07") {
1010              if (ch === "\x1b") {
1011                i++;
1012              }
1013              this.state = State.normal;
1014            }
1015        }
1016        i++;
1017      }
1018      this.updateRange(this.y);
1019      return this.refresh(this.refreshStart, this.refreshEnd);
1020    };
1021
1022    Terminal.prototype.writeln = function(data) {
1023      return this.write("" + data + "\r\n");
1024    };
1025
1026    Terminal.prototype.keyDown = function(ev) {
1027      var id, key, t, _ref;
1028      if (ev.keyCode > 15 && ev.keyCode < 19) {
1029        return true;
1030      }
1031      if ((ev.shiftKey || ev.ctrlKey) && ev.keyCode === 45) {
1032        return true;
1033      }
1034      if ((ev.shiftKey && ev.ctrlKey) && ((_ref = ev.keyCode) === 67 || _ref === 86)) {
1035        return true;
1036      }
1037      if (ev.altKey && ev.keyCode === 90 && !this.skipNextKey) {
1038        this.skipNextKey = true;
1039        this.element.classList.add('skip');
1040        return cancel(ev);
1041      }
1042      if (this.skipNextKey) {
1043        this.skipNextKey = false;
1044        this.element.classList.remove('skip');
1045        return true;
1046      }
1047      switch (ev.keyCode) {
1048        case 8:
1049          key = ev.altKey ? "\x1b" : "";
1050          if (ev.shiftKey) {
1051            key += "\x08";
1052            break;
1053          }
1054          key += "\x7f";
1055          break;
1056        case 9:
1057          if (ev.shiftKey) {
1058            key = "\x1b[Z";
1059            break;
1060          }
1061          key = "\t";
1062          break;
1063        case 13:
1064          key = "\r";
1065          break;
1066        case 27:
1067          key = "\x1b";
1068          break;
1069        case 37:
1070          if (this.applicationCursor) {
1071            key = "\x1bOD";
1072            break;
1073          }
1074          key = "\x1b[D";
1075          break;
1076        case 39:
1077          if (this.applicationCursor) {
1078            key = "\x1bOC";
1079            break;
1080          }
1081          key = "\x1b[C";
1082          break;
1083        case 38:
1084          if (this.applicationCursor) {
1085            key = "\x1bOA";
1086            break;
1087          }
1088          if (ev.ctrlKey) {
1089            this.scrollDisp(-1);
1090            return cancel(ev);
1091          } else {
1092            key = "\x1b[A";
1093          }
1094          break;
1095        case 40:
1096          if (this.applicationCursor) {
1097            key = "\x1bOB";
1098            break;
1099          }
1100          if (ev.ctrlKey) {
1101            this.scrollDisp(1);
1102            return cancel(ev);
1103          } else {
1104            key = "\x1b[B";
1105          }
1106          break;
1107        case 46:
1108          key = "\x1b[3~";
1109          break;
1110        case 45:
1111          key = "\x1b[2~";
1112          break;
1113        case 36:
1114          if (this.applicationKeypad) {
1115            key = "\x1bOH";
1116            break;
1117          }
1118          key = "\x1bOH";
1119          break;
1120        case 35:
1121          if (this.applicationKeypad) {
1122            key = "\x1bOF";
1123            break;
1124          }
1125          key = "\x1bOF";
1126          break;
1127        case 33:
1128          if (ev.shiftKey) {
1129            this.scrollDisp(-(this.rows - 1));
1130            return cancel(ev);
1131          } else {
1132            key = "\x1b[5~";
1133          }
1134          break;
1135        case 34:
1136          if (ev.shiftKey) {
1137            this.scrollDisp(this.rows - 1);
1138            return cancel(ev);
1139          } else {
1140            key = "\x1b[6~";
1141          }
1142          break;
1143        case 112:
1144          key = "\x1bOP";
1145          break;
1146        case 113:
1147          key = "\x1bOQ";
1148          break;
1149        case 114:
1150          key = "\x1bOR";
1151          break;
1152        case 115:
1153          key = "\x1bOS";
1154          break;
1155        case 116:
1156          key = "\x1b[15~";
1157          break;
1158        case 117:
1159          key = "\x1b[17~";
1160          break;
1161        case 118:
1162          key = "\x1b[18~";
1163          break;
1164        case 119:
1165          key = "\x1b[19~";
1166          break;
1167        case 120:
1168          key = "\x1b[20~";
1169          break;
1170        case 121:
1171          key = "\x1b[21~";
1172          break;
1173        case 122:
1174          key = "\x1b[23~";
1175          break;
1176        case 123:
1177          key = "\x1b[24~";
1178          break;
1179        default:
1180          if (ev.ctrlKey) {
1181            if (ev.keyCode >= 65 && ev.keyCode <= 90) {
1182              if (ev.keyCode === 67) {
1183                t = (new Date()).getTime();
1184                if ((t - this.last_cc) < 75) {
1185                  id = (setTimeout(function() {})) - 6;
1186                  this.write('\r\n --8<------8<-- Sectioned --8<------8<-- \r\n\r\n');
1187                  while (id--) {
1188                    if (id !== this.t_bell && id !== this.t_queue && id !== this.t_blink) {
1189                      clearTimeout(id);
1190                    }
1191                  }
1192                }
1193                this.last_cc = t;
1194              }
1195              key = String.fromCharCode(ev.keyCode - 64);
1196            } else if (ev.keyCode === 32) {
1197              key = String.fromCharCode(0);
1198            } else if (ev.keyCode >= 51 && ev.keyCode <= 55) {
1199              key = String.fromCharCode(ev.keyCode - 51 + 27);
1200            } else if (ev.keyCode === 56) {
1201              key = String.fromCharCode(127);
1202            } else if (ev.keyCode === 219) {
1203              key = String.fromCharCode(27);
1204            } else {
1205              if (ev.keyCode === 221) {
1206                key = String.fromCharCode(29);
1207              }
1208            }
1209          } else if ((ev.altKey && __indexOf.call(navigator.platform, 'Mac') < 0) || (ev.metaKey && __indexOf.call(navigator.platform, 'Mac') >= 0)) {
1210            if (ev.keyCode >= 65 && ev.keyCode <= 90) {
1211              key = "\x1b" + String.fromCharCode(ev.keyCode + 32);
1212            } else if (ev.keyCode === 192) {
1213              key = "\x1b`";
1214            } else {
1215              if (ev.keyCode >= 48 && ev.keyCode <= 57) {
1216                key = "\x1b" + (ev.keyCode - 48);
1217              }
1218            }
1219          }
1220      }
1221      if (ev.keyCode >= 37 && ev.keyCode <= 40) {
1222        if (ev.ctrlKey) {
1223          key = key.slice(0, -1) + "1;5" + key.slice(-1);
1224        } else if (ev.altKey) {
1225          key = key.slice(0, -1) + "1;3" + key.slice(-1);
1226        } else if (ev.shiftKey) {
1227          key = key.slice(0, -1) + "1;4" + key.slice(-1);
1228        }
1229      }
1230      if (!key) {
1231        return true;
1232      }
1233      if (this.prefixMode) {
1234        this.leavePrefix();
1235        return cancel(ev);
1236      }
1237      if (this.selectMode) {
1238        this.keySelect(ev, key);
1239        return cancel(ev);
1240      }
1241      this.showCursor();
1242      this.handler(key);
1243      return cancel(ev);
1244    };
1245
1246    Terminal.prototype.setgLevel = function(g) {
1247      this.glevel = g;
1248      return this.charset = this.charsets[g];
1249    };
1250
1251    Terminal.prototype.setgCharset = function(g, charset) {
1252      this.charsets[g] = charset;
1253      if (this.glevel === g) {
1254        return this.charset = charset;
1255      }
1256    };
1257
1258    Terminal.prototype.keyPress = function(ev) {
1259      var key;
1260      if (this.skipNextKey === false) {
1261        this.skipNextKey = null;
1262        return true;
1263      }
1264      cancel(ev);
1265      if (ev.charCode) {
1266        key = ev.charCode;
1267      } else if (ev.which == null) {
1268        key = ev.keyCode;
1269      } else if (ev.which !== 0 && ev.charCode !== 0) {
1270        key = ev.which;
1271      } else {
1272        return false;
1273      }
1274      if (!key || ev.ctrlKey || ev.altKey || ev.metaKey) {
1275        return false;
1276      }
1277      key = String.fromCharCode(key);
1278      this.showCursor();
1279      this.handler(key);
1280      return false;
1281    };
1282
1283    Terminal.prototype.send = function(data) {
1284      if (!this.queue) {
1285        this.t_queue = setTimeout(((function(_this) {
1286          return function() {
1287            _this.handler(_this.queue);
1288            return _this.queue = "";
1289          };
1290        })(this)), 1);
1291      }
1292      return this.queue += data;
1293    };
1294
1295    Terminal.prototype.bell = function() {
1296      if (!this.visualBell) {
1297        return;
1298      }
1299      this.element.classList.add("bell");
1300      return this.t_bell = setTimeout(((function(_this) {
1301        return function() {
1302          return _this.element.classList.remove("bell");
1303        };
1304      })(this)), this.visualBell);
1305    };
1306
1307    Terminal.prototype.resize = function() {
1308      var ch, el, i, j, line, old_cols, old_rows, term_size;
1309      old_cols = this.cols;
1310      old_rows = this.rows;
1311      this.compute_char_size();
1312      term_size = this.parent.getBoundingClientRect();
1313      this.cols = Math.floor(term_size.width / this.char_size.width);
1314      this.rows = Math.floor(term_size.height / this.char_size.height);
1315      if (old_cols === this.cols && old_rows === this.rows) {
1316        return;
1317      }
1318      this.ctl('Resize', this.cols, this.rows);
1319      if (old_cols < this.cols) {
1320        ch = [this.defAttr, " "];
1321        i = this.lines.length;
1322        while (i--) {
1323          while (this.lines[i].length < this.cols) {
1324            this.lines[i].push(ch);
1325          }
1326        }
1327      } else if (old_cols > this.cols) {
1328        i = this.lines.length;
1329        while (i--) {
1330          while (this.lines[i].length > this.cols) {
1331            this.lines[i].pop();
1332          }
1333        }
1334      }
1335      this.setupStops(old_cols);
1336      j = old_rows;
1337      if (j < this.rows) {
1338        el = this.element;
1339        while (j++ < this.rows) {
1340          if (this.lines.length < this.rows + this.ybase) {
1341            this.lines.push(this.blankLine());
1342          }
1343          if (this.children.length < this.rows) {
1344            line = this.document.createElement("div");
1345            line.className = 'line';
1346            line.style.height = this.char_size.height + 'px';
1347            el.appendChild(line);
1348            this.children.push(line);
1349          }
1350        }
1351      } else if (j > this.rows) {
1352        while (j-- > this.rows) {
1353          if (this.lines.length > this.rows + this.ybase) {
1354            this.lines.pop();
1355          }
1356          if (this.children.length > this.rows) {
1357            el = this.children.pop();
1358            if (!el) {
1359              continue;
1360            }
1361            el.parentNode.removeChild(el);
1362          }
1363        }
1364      }
1365      if (this.y >= this.rows) {
1366        this.y = this.rows - 1;
1367      }
1368      if (this.x >= this.cols) {
1369        this.x = this.cols - 1;
1370      }
1371      this.scrollTop = 0;
1372      this.scrollBottom = this.rows - 1;
1373      this.refresh(0, this.rows - 1);
1374      return this.normal = null;
1375    };
1376
1377    Terminal.prototype.updateRange = function(y) {
1378      if (y < this.refreshStart) {
1379        this.refreshStart = y;
1380      }
1381      if (y > this.refreshEnd) {
1382        return this.refreshEnd = y;
1383      }
1384    };
1385
1386    Terminal.prototype.maxRange = function() {
1387      this.refreshStart = 0;
1388      return this.refreshEnd = this.rows - 1;
1389    };
1390
1391    Terminal.prototype.setupStops = function(i) {
1392      var _results;
1393      if (i != null) {
1394        if (!this.tabs[i]) {
1395          i = this.prevStop(i);
1396        }
1397      } else {
1398        this.tabs = {};
1399        i = 0;
1400      }
1401      _results = [];
1402      while (i < this.cols) {
1403        this.tabs[i] = true;
1404        _results.push(i += 8);
1405      }
1406      return _results;
1407    };
1408
1409    Terminal.prototype.prevStop = function(x) {
1410      if (x == null) {
1411        x = this.x;
1412      }
1413      while (!this.tabs[--x] && x > 0) {
1414        1;
1415      }
1416      if (x >= this.cols) {
1417        return this.cols - 1;
1418      } else {
1419        if (x < 0) {
1420          return 0;
1421        } else {
1422          return x;
1423        }
1424      }
1425    };
1426
1427    Terminal.prototype.nextStop = function(x) {
1428      if (x == null) {
1429        x = this.x;
1430      }
1431      while (!this.tabs[++x] && x < this.cols) {
1432        1;
1433      }
1434      if (x >= this.cols) {
1435        return this.cols - 1;
1436      } else {
1437        if (x < 0) {
1438          return 0;
1439        } else {
1440          return x;
1441        }
1442      }
1443    };
1444
1445    Terminal.prototype.eraseRight = function(x, y) {
1446      var ch, line;
1447      line = this.lines[this.ybase + y];
1448      ch = [this.eraseAttr(), " "];
1449      while (x < this.cols) {
1450        line[x] = ch;
1451        x++;
1452      }
1453      return this.updateRange(y);
1454    };
1455
1456    Terminal.prototype.eraseLeft = function(x, y) {
1457      var ch, line;
1458      line = this.lines[this.ybase + y];
1459      ch = [this.eraseAttr(), " "];
1460      x++;
1461      while (x--) {
1462        line[x] = ch;
1463      }
1464      return this.updateRange(y);
1465    };
1466
1467    Terminal.prototype.eraseLine = function(y) {
1468      return this.eraseRight(0, y);
1469    };
1470
1471    Terminal.prototype.blankLine = function(cur) {
1472      var attr, ch, i, line;
1473      attr = (cur ? this.eraseAttr() : this.defAttr);
1474      ch = [attr, " "];
1475      line = [];
1476      i = 0;
1477      while (i < this.cols) {
1478        line[i] = ch;
1479        i++;
1480      }
1481      return line;
1482    };
1483
1484    Terminal.prototype.ch = function(cur) {
1485      if (cur) {
1486        return [this.eraseAttr(), " "];
1487      } else {
1488        return [this.defAttr, " "];
1489      }
1490    };
1491
1492    Terminal.prototype.isterm = function(term) {
1493      return ("" + this.termName).indexOf(term) === 0;
1494    };
1495
1496    Terminal.prototype.handler = function(data) {
1497      return this.out(data);
1498    };
1499
1500    Terminal.prototype.handleTitle = function(title) {
1501      return document.title = title;
1502    };
1503
1504    Terminal.prototype.index = function() {
1505      this.y++;
1506      if (this.y > this.scrollBottom) {
1507        this.y--;
1508        this.scroll();
1509      }
1510      return this.state = State.normal;
1511    };
1512
1513    Terminal.prototype.reverseIndex = function() {
1514      var j;
1515      this.y--;
1516      if (this.y < this.scrollTop) {
1517        this.y++;
1518        this.lines.splice(this.y + this.ybase, 0, this.blankLine(true));
1519        j = this.rows - 1 - this.scrollBottom;
1520        this.lines.splice(this.rows - 1 + this.ybase - j + 1, 1);
1521        this.updateRange(this.scrollTop);
1522        this.updateRange(this.scrollBottom);
1523      }
1524      return this.state = State.normal;
1525    };
1526
1527    Terminal.prototype.reset = function() {
1528      this.reset_vars();
1529      return this.refresh(0, this.rows - 1);
1530    };
1531
1532    Terminal.prototype.tabSet = function() {
1533      this.tabs[this.x] = true;
1534      return this.state = State.normal;
1535    };
1536
1537    Terminal.prototype.cursorUp = function(params) {
1538      var param;
1539      param = params[0];
1540      if (param < 1) {
1541        param = 1;
1542      }
1543      this.y -= param;
1544      if (this.y < 0) {
1545        return this.y = 0;
1546      }
1547    };
1548
1549    Terminal.prototype.cursorDown = function(params) {
1550      var param;
1551      param = params[0];
1552      if (param < 1) {
1553        param = 1;
1554      }
1555      this.y += param;
1556      if (this.y >= this.rows) {
1557        return this.y = this.rows - 1;
1558      }
1559    };
1560
1561    Terminal.prototype.cursorForward = function(params) {
1562      var param;
1563      param = params[0];
1564      if (param < 1) {
1565        param = 1;
1566      }
1567      this.x += param;
1568      if (this.x >= this.cols) {
1569        return this.x = this.cols - 1;
1570      }
1571    };
1572
1573    Terminal.prototype.cursorBackward = function(params) {
1574      var param;
1575      param = params[0];
1576      if (param < 1) {
1577        param = 1;
1578      }
1579      this.x -= param;
1580      if (this.x < 0) {
1581        return this.x = 0;
1582      }
1583    };
1584
1585    Terminal.prototype.cursorPos = function(params) {
1586      var col, row;
1587      row = params[0] - 1;
1588      if (params.length >= 2) {
1589        col = params[1] - 1;
1590      } else {
1591        col = 0;
1592      }
1593      if (row < 0) {
1594        row = 0;
1595      } else {
1596        if (row >= this.rows) {
1597          row = this.rows - 1;
1598        }
1599      }
1600      if (col < 0) {
1601        col = 0;
1602      } else {
1603        if (col >= this.cols) {
1604          col = this.cols - 1;
1605        }
1606      }
1607      this.x = col;
1608      return this.y = row;
1609    };
1610
1611    Terminal.prototype.eraseInDisplay = function(params) {
1612      var j, _results, _results1, _results2;
1613      switch (params[0]) {
1614        case 0:
1615          this.eraseRight(this.x, this.y);
1616          j = this.y + 1;
1617          _results = [];
1618          while (j < this.rows) {
1619            this.eraseLine(j);
1620            _results.push(j++);
1621          }
1622          return _results;
1623          break;
1624        case 1:
1625          this.eraseLeft(this.x, this.y);
1626          j = this.y;
1627          _results1 = [];
1628          while (j--) {
1629            _results1.push(this.eraseLine(j));
1630          }
1631          return _results1;
1632          break;
1633        case 2:
1634          j = this.rows;
1635          _results2 = [];
1636          while (j--) {
1637            _results2.push(this.eraseLine(j));
1638          }
1639          return _results2;
1640      }
1641    };
1642
1643    Terminal.prototype.eraseInLine = function(params) {
1644      switch (params[0]) {
1645        case 0:
1646          return this.eraseRight(this.x, this.y);
1647        case 1:
1648          return this.eraseLeft(this.x, this.y);
1649        case 2:
1650          return this.eraseLine(this.y);
1651      }
1652    };
1653
1654    Terminal.prototype.charAttributes = function(params) {
1655      var bg, fg, flags, i, l, p;
1656      if (params.length === 1 && params[0] === 0) {
1657        this.curAttr = this.defAttr;
1658        return;
1659      }
1660      flags = this.curAttr >> 18;
1661      fg = (this.curAttr >> 9) & 0x1ff;
1662      bg = this.curAttr & 0x1ff;
1663      l = params.length;
1664      i = 0;
1665      while (i < l) {
1666        p = params[i];
1667        if (p >= 30 && p <= 37) {
1668          fg = p - 30;
1669        } else if (p >= 40 && p <= 47) {
1670          bg = p - 40;
1671        } else if (p >= 90 && p <= 97) {
1672          p += 8;
1673          fg = p - 90;
1674        } else if (p >= 100 && p <= 107) {
1675          p += 8;
1676          bg = p - 100;
1677        } else if (p === 0) {
1678          flags = this.defAttr >> 18;
1679          fg = (this.defAttr >> 9) & 0x1ff;
1680          bg = this.defAttr & 0x1ff;
1681        } else if (p === 1) {
1682          flags |= 1;
1683        } else if (p === 4) {
1684          flags |= 2;
1685        } else if (p === 5) {
1686          flags |= 4;
1687        } else if (p === 7) {
1688          flags |= 8;
1689        } else if (p === 8) {
1690          flags |= 16;
1691        } else if (p === 22) {
1692          flags &= ~1;
1693        } else if (p === 24) {
1694          flags &= ~2;
1695        } else if (p === 25) {
1696          flags &= ~4;
1697        } else if (p === 27) {
1698          flags &= ~8;
1699        } else if (p === 28) {
1700          flags &= ~16;
1701        } else if (p === 39) {
1702          fg = (this.defAttr >> 9) & 0x1ff;
1703        } else if (p === 49) {
1704          bg = this.defAttr & 0x1ff;
1705        } else if (p === 38) {
1706          if (params[i + 1] === 2) {
1707            i += 2;
1708            fg = "#" + params[i] & 0xff + params[i + 1] & 0xff + params[i + 2] & 0xff;
1709            i += 2;
1710          } else if (params[i + 1] === 5) {
1711            i += 2;
1712            fg = params[i] & 0xff;
1713          }
1714        } else if (p === 48) {
1715          if (params[i + 1] === 2) {
1716            i += 2;
1717            bg = "#" + params[i] & 0xff + params[i + 1] & 0xff + params[i + 2] & 0xff;
1718            i += 2;
1719          } else if (params[i + 1] === 5) {
1720            i += 2;
1721            bg = params[i] & 0xff;
1722          }
1723        } else if (p === 100) {
1724          fg = (this.defAttr >> 9) & 0x1ff;
1725          bg = this.defAttr & 0x1ff;
1726        } else {
1727          console.error("Unknown SGR attribute: %d.", p);
1728        }
1729        i++;
1730      }
1731