mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-09-15 21:59:05 +00:00
314 lines
9.7 KiB
JavaScript
314 lines
9.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TeleTypeWithKeyboard = exports.TeleType = void 0;
|
|
class TeleType {
|
|
constructor(page, fixed) {
|
|
this.ncols = 80;
|
|
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 = $('<div class="transcript-line"/>')[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, style) {
|
|
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 = $("<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) {
|
|
// 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, row) {
|
|
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) {
|
|
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) {
|
|
/*
|
|
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) {
|
|
/*
|
|
var ph = $("#printhead"); // TODO: speed?
|
|
if (show) ph.show(); else ph.hide();
|
|
*/
|
|
}
|
|
resize(columns) {
|
|
// 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 < state.lines.length; i++) {
|
|
this.page.appendChild(state.lines[i]);
|
|
}
|
|
this.lines = state.lines;
|
|
this.curline = state.lines[this.row];
|
|
}
|
|
}
|
|
exports.TeleType = TeleType;
|
|
class TeleTypeWithKeyboard extends TeleType {
|
|
constructor(page, fixed, input) {
|
|
super(page, fixed);
|
|
this.msecPerLine = 100; // IBM 1403
|
|
this.keepinput = true;
|
|
this.keephandler = true;
|
|
this.uppercaseOnly = false;
|
|
this.splitInput = false;
|
|
this.focused = true;
|
|
this.scrolling = 0;
|
|
this.input = input;
|
|
this.input.onkeypress = (e) => {
|
|
this.sendkey(e);
|
|
};
|
|
this.input.onfocus = (e) => {
|
|
this.focused = true;
|
|
console.log('inputline gained focus');
|
|
};
|
|
$("#workspace").on('click', (e) => {
|
|
this.focused = false;
|
|
console.log('inputline lost focus');
|
|
});
|
|
this.page.onclick = (e) => {
|
|
this.input.focus();
|
|
};
|
|
}
|
|
clear() {
|
|
super.clear();
|
|
this.hideinput();
|
|
this.waitingfor = null;
|
|
}
|
|
focusinput() {
|
|
this.ensureline();
|
|
this.showPrintHead(false);
|
|
// don't steal focus while editing
|
|
if (this.keepinput)
|
|
$(this.input).css('visibility', 'visible');
|
|
else
|
|
$(this.input).appendTo(this.curline).show()[0];
|
|
// scroll to bottom
|
|
this.scrollToBottom();
|
|
// refocus?
|
|
if (this.focused) {
|
|
$(this.input).focus();
|
|
}
|
|
// change size
|
|
if (this.waitingfor == 'char')
|
|
$(this.input).addClass('transcript-input-char');
|
|
else
|
|
$(this.input).removeClass('transcript-input-char');
|
|
this.lastInputRequestTime = Date.now();
|
|
}
|
|
hideinput() {
|
|
this.showPrintHead(true);
|
|
if (this.keepinput)
|
|
$(this.input).css('visibility', 'hidden');
|
|
else
|
|
$(this.input).appendTo($(this.page).parent()).hide();
|
|
}
|
|
clearinput() {
|
|
this.input.value = '';
|
|
this.waitingfor = null;
|
|
}
|
|
cancelinput() {
|
|
this.sendinput('');
|
|
}
|
|
sendkey(e) {
|
|
if (this.waitingfor == 'line') {
|
|
if (e.key == "Enter") {
|
|
this.sendinput(this.input.value.toString());
|
|
}
|
|
}
|
|
else if (this.waitingfor == 'char') {
|
|
this.sendchar(e.keyCode);
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
sendinput(s) {
|
|
if (this.resolveInput) {
|
|
var elapsed = Date.now() - this.lastInputRequestTime;
|
|
if (this.uppercaseOnly)
|
|
s = s.toUpperCase(); // TODO: always uppercase?
|
|
this.addtext(s, 4);
|
|
this.flushline();
|
|
this.clearinput();
|
|
this.hideinput(); // keep from losing input handlers
|
|
var vals = this.splitInput ? s.split(',') : null;
|
|
this.resolveInput({ line: s, vals: vals, elapsed: elapsed / 1000 });
|
|
if (!this.keephandler)
|
|
this.resolveInput = null;
|
|
}
|
|
}
|
|
sendchar(code) {
|
|
this.sendinput(String.fromCharCode(code));
|
|
}
|
|
ensureline() {
|
|
if (!this.keepinput)
|
|
$(this.input).hide();
|
|
super.ensureline();
|
|
}
|
|
scrollToBottom() {
|
|
if (this.scrolldiv) {
|
|
this.scrolling++;
|
|
var top = $(this.page).height() + $(this.input).height();
|
|
$(this.scrolldiv).stop().animate({ scrollTop: top }, this.msecPerLine, 'swing', () => {
|
|
this.scrolling = 0;
|
|
this.ncharsout = 0;
|
|
});
|
|
}
|
|
else {
|
|
this.input.scrollIntoView();
|
|
}
|
|
}
|
|
isBusy() {
|
|
// stop execution when scrolling and printing non-newlines
|
|
return this.scrolling > 0 && this.ncharsout > 0;
|
|
}
|
|
}
|
|
exports.TeleTypeWithKeyboard = TeleTypeWithKeyboard;
|
|
//# sourceMappingURL=teletype.js.map
|