import { InputResponse } from "./basic/runtime"; export class TeleType { page: HTMLElement; fixed: boolean; ncols: number = 80; scrolldiv: HTMLElement; bell; // Audio curline: HTMLElement; curstyle: number; reverse: boolean; col: number; row: number; lines: HTMLElement[]; ncharsout : number; constructor(page: HTMLElement, fixed: boolean) { this.page = page; this.fixed = fixed; this.clear(); } clear() { this.curline = null; this.curstyle = 0; this.reverse = false; this.col = 0; this.row = -1; this.lines = []; this.ncharsout = 0; $(this.page).empty(); this.showPrintHead(true); } ensureline() { if (this.curline == null) { this.curline = this.lines[++this.row]; if (this.curline == null) { this.curline = $('
')[0]; this.page.appendChild(this.curline); this.lines[this.row] = this.curline; this.scrollToBottom(); } } } flushline() { this.curline = null; this.col = 0; this.movePrintHead(false); } addtext(line: string, style: number) { this.ensureline(); if (line.length) { // in fixed mode, only do characters if (this.fixed && line.length > 1) { for (var i = 0; i < line.length; i++) this.addtext(line[i], style); return; } // process control codes if (line.length == 1) { var ch = line.charCodeAt(0); switch (ch) { case 7: if (this.bell) this.bell.play(); break; case 8: if (this.col > 0) this.col--; break; case 12: this.formfeed(); break; case 13: this.col = 0; break; } if (ch < 32) return; // ignore non-printables } var span = $("").text(line); for (var i = 0; i < 8; i++) { if (style & (1 << i)) span.addClass("transcript-style-" + (1 << i)); } if (this.reverse) span.addClass("transcript-reverse"); //span.data('vmip', this.vm.pc); // in fixed mode, we can overwrite individual characters if (this.fixed && line.length == 1 && this.col < this.curline.childNodes.length) { this.curline.replaceChild(span[0], this.curline.childNodes[this.col]); } else { span.appendTo(this.curline); } this.col += line.length; // wrap @ 80 columns (TODO: const) if (this.fixed && this.col >= this.ncols) this.flushline(); this.ncharsout += line.length; this.movePrintHead(true); } } newline() { this.flushline(); this.ensureline(); } print(val: string) { // split by newlines var lines = val.split("\n"); for (var i = 0; i < lines.length; i++) { if (i > 0) this.newline(); this.addtext(lines[i], this.curstyle); } } move_cursor(col: number, row: number) { if (!this.fixed) return; // fixed windows only // ensure enough row elements while (this.lines.length <= row) { this.flushline(); this.ensureline(); } // select row element this.curline = this.lines[row]; this.row = row; // get children in row (individual text cells) var children = $(this.curline).children(); // add whitespace to line? if (children.length > col) { this.col = col; } else { while (this.col < col) this.addtext(' ', this.curstyle); } } setrows(size: number) { if (!this.fixed) return; // fixed windows only // truncate rows? var allrows = $(this.page).children(); if (allrows.length > size) { this.flushline(); allrows.slice(size).remove(); this.lines = this.lines.slice(0, size); //this.move_cursor(0,0); } } formfeed() { for (var i=0; i<60; i++) { this.newline(); this.ensureline(); } } scrollToBottom() { this.curline.scrollIntoView(); } movePrintHead(printing: boolean) { /* var ph = $("#printhead"); // TODO: speed? var x = $(this.page).position().left + this.col * ($(this.page).width() / 80) - 200; ph.stop().animate({left: x}, {duration:20}); //ph.offset({left: x}); if (printing) ph.addClass("printing"); else ph.removeClass("printing"); */ } showPrintHead(show: boolean) { /* var ph = $("#printhead"); // TODO: speed? if (show) ph.show(); else ph.hide(); */ } resize(columns: number) { // set font size proportional to window width var charwidth = $(this.page).width() * 1.6 / columns; $(this.page).css('font-size', charwidth + 'px'); this.scrollToBottom(); } saveState() { return { curstyle: this.curstyle, reverse: this.reverse, col: this.col, row: this.row, ncharsout : this.ncharsout, lines: this.lines.map((line) => line.cloneNode(true)), } } loadState(state) { this.curstyle = state.curstyle; this.reverse = state.reverse; this.col = state.col; this.row = state.row; this.ncharsout = state.ncharsout; $(this.page).empty(); for (var i=0; i