// VD.js -- a viewdata terminal emulator // constructor function VD(wd, ht, scr_id, initscr) { var r; var c; var scr = document.getElementById(scr_id); this.wd_ = wd; this.ht_ = ht; this.text_ = new Array(ht); for (r=0; r -1) var hashstring = hashstring.split(':')[1]; hashstring = hashstring.substring(0,this.wd_*this.ht_); for (var p=0; p 0 ) { b64bit = 1; } // Update the current code. currentcode |= b64bit << (6-charbit); // If we've reached the end of this character cell // and it's the last bit in the character we're // writing to, set the character code or place the // code. if (charbit === 6) { if (currentcode < 32) { stuff += '\x1b'; currentcode += 64; } stuff += String.fromCharCode(currentcode); currentcode = 0; } } } return stuff; } VD.prototype.clear = function() { this.row_ = this.col_ = 0; for (r=0; r 0); } VD.prototype.getch = function(isr) { this.getch_isr_ = isr; setTimeout(VD.go_getch_, 0); } VD.go_getch_ = function VD_go_getch() { var vt = VD.the_vt_; if (vt === undefined) return; var isr = vt.getch_isr_; vt.getch_isr_ = undefined; if (isr === undefined) return; var ch = vt.key_buf_.shift(); if (ch === undefined) { vt.getch_isr_ = isr; return; } isr(ch,vt); } VD.prototype.move = function(r, c) { if (r < 0) r = 0; else if (r >= this.ht_) r = this.ht_ - 1; if (c < 0) c = 0; else if (c >= this.wd_) c = this.wd_ - 1; this.row_ = r; this.col_ = c; } VD.prototype.refresh = function() { var r, c, stuff = "", start_tag = "", end_tag = "", ch, chtype, pair, cr, cc, ht, wd, cv, n_fg, n_bg, n_mode, n_type, a_fg=-1, a_bg=-1, a_mode=-1, n_dblnextline=-2, n_heldchar, n_heldtype; ht = this.ht_; wd = this.wd_; cr = this.row_; cc = this.col_; cv = this.cursor_vis_; if (cc >= wd) cc = wd - 1; for (r = 0; r < ht; ++r) { if (r > 0) { stuff += '\n'; } n_fg = 7; n_bg = 0; n_mode = 0; n_type = 0; n_heldchar = 32; n_heldtype = 0; if (n_dblnextline+1 < r) n_dblnextline = -2; for (c = 0; c < wd; ++c) { if (cv && r == cr && c == cc) { // Draw the cursor here. n_mode |= VD.A_REVERSE; } else { n_mode &= ~VD.A_REVERSE; } if (r == n_dblnextline+1) { ch = this.text_[r-1][c].charCodeAt(0); } else { ch = this.text_[r][c].charCodeAt(0); } ctrlch = ch; // set-at if (ctrlch == 0x89) // steady n_mode &= ~VD.A_BLINK; if (ctrlch == 0x8c) { // normal if (n_type & 8) { n_heldchar = 32; n_heldtype = 0; } n_type &= ~8; } if (ctrlch == 0x98 && this.reveal_ == false) // conceal n_type |= 16; if (ctrlch == 0x99) // contig n_type &= ~1; if (ctrlch == 0x9a) // sep n_type |= 1; if (ctrlch == 0x9c) // black n_bg = 0; if (ctrlch == 0x9d) // newback n_bg = n_fg; if (ctrlch == 0x9e) // hold n_type |= 32; // If the attributes changed, make a new span. if (n_mode != a_mode || n_fg != a_fg || n_bg != a_bg) { stuff += end_tag; pair = this.html_colours_(n_fg, n_bg, n_mode); stuff += '' end_tag = ""; if (n_mode & VD.A_BLINK) { stuff += ''; end_tag += ""; } a_fg = n_fg; a_bg = n_bg; a_mode = n_mode; } chtype = n_type; if (ch >= 128) { if (n_type & 32) { ch = n_heldchar; chtype = n_heldtype; } else { ch = 32; } } if (ch == 127) { if (n_type & 2) { ch = 0xe23f+((chtype & 1)*0xc0); n_heldchar = 127; } else { ch = 0xb6; } } if (n_type & 2) { if ( ch >= 0x20 && ch <= 0x3f) { n_heldchar = ch; ch = ch+0xe1e0+((chtype & 1)*0xc0); } else if ( ch >= 0x60 && ch <= 0x7e) { n_heldchar = ch; ch = ch+0xe1c0+((chtype & 1)*0xc0); } } if (n_type & 16) ch = 32; n_heldtype = chtype; switch (ch) { case 32: ch = 0xa0; break; case 0x7e: ch = 0xf7; break; case 0x5f: // _ ch = 0x23; break // # case 123: // { ch = 0xbc; break case 92: // \ ch = 0xbd; break case 125: // } ch = 0xbe; break case 0x23: // # ch = 0xa3; break } if (n_type & 8) { if (ch < 0x100) { ch = ch+0xe000+((r==n_dblnextline+1)*0x100); } else { ch = ch+0x40+((r==n_dblnextline+1)*0x40) } } else if (r==n_dblnextline+1) { ch = 0xa0; } stuff += "&#x" + ch.toString(16) + ";" // set-after if (ctrlch >= 129 && ctrlch <= 135) { if (n_type & 2) { n_heldchar=32; n_heldtype=0; } n_fg = ctrlch-128; n_type &= ~2; n_type &= ~16; } if (ctrlch >= 145 && ctrlch <= 151) { if (n_type & 2 == 0) { n_heldchar=32; n_heldtype=0; } n_fg = ctrlch-144; n_type |= 2; n_type &= ~16; } if (ctrlch == 0x88) // flash n_mode |= VD.A_BLINK; if (ctrlch == 0x8d) { // double if (n_type & 8 == 0) { n_heldchar = 32; n_heldtype = 0; } n_type |= 8; if (n_dblnextline < 0) n_dblnextline = r; } if (ctrlch == 0x9f) // release n_type &= ~32; } } stuff += end_tag this.scr_.innerHTML = "" + stuff + "\n"; } VD.prototype.write = function(stuff) { var ch, i; for (i = 0; i < stuff.length; ++i) { ch = stuff.charCodeAt(i); if (this.esc_state_ && ch > 31) ch = (ch % 32) + 128; this.esc_state_ = 0; switch (ch) { case 8: if (this.col_ != 0) { --this.col_; } else { this.col_ = this.wd_-1; if (this.row_ == 0) { this.row_ = this.ht_-1; } else { --this.row_; } } break; case 9: if (this.col_ >= this.wd_) { this.col_ = 0; if (this.row_ == this.ht_-1) { this.row_ = 0; } else { ++this.row_; } } else { ++this.col_; } break; case 10: if (this.row_ >= this.ht_-1) { this.row_ = 0; } else { ++this.row_; } break; case 11: if (this.row_ == 0) { this.row_ = this.ht_-1; } else { --this.row_; } break; case 12: this.clear(); this.move(0, 0); this.reveal_ = false; break; case 13: this.col_ = 0; break; case 17: this.curs_set(1); break; case 20: this.curs_set(0); break; case 27: this.esc_state_ = 1; break; case 30: this.move(0, 0); break; default: if (ch > 31) { this.text_[this.row_][this.col_] = String.fromCharCode(ch); if (this.col_ >= this.wd_-1) { this.col_ = 0; if (this.row_ >= this.ht_-1) { this.row_ = 0; } else { ++this.row_; } } else { ++this.col_; } } } } this.refresh(); }