mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
|
/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||
|
* the above copyright notice appear in all copies and that both that
|
||
|
* copyright notice and this permission notice appear in supporting
|
||
|
* documentation. No representations are made about the suitability of this
|
||
|
* software for any purpose. It is provided "as is" without express or
|
||
|
* implied warranty.
|
||
|
*/
|
||
|
|
||
|
import { byte } from '../types';
|
||
|
|
||
|
/**
|
||
|
* Printer UI. The "paper" is bound to the element selected by the input.
|
||
|
*
|
||
|
* Every line that is output to the printer is added as a <div> to the paper.
|
||
|
* The high bit of all characters is stripped and only visible characters are
|
||
|
* added to the output. The following characters receive special treatment:
|
||
|
*
|
||
|
* * `EOT` (ASCII 4): deletes last character
|
||
|
* * `HT` (ASCII 9): replaced with 8 spaces
|
||
|
* * `LF` (ASCII 10): silently removed
|
||
|
* * `CR` (ASCII 13): a newline and carriage return
|
||
|
*/
|
||
|
export default class Printer {
|
||
|
private paper: HTMLElement;
|
||
|
private _lineBuffer = '';
|
||
|
private _line: HTMLElement;
|
||
|
private _rawLen = 0;
|
||
|
private _raw = new Uint8Array(1024);
|
||
|
|
||
|
/**
|
||
|
* Creates a new printer bound to the given element.
|
||
|
* @param {string} el The selector of the element on which to bind the "paper".
|
||
|
*/
|
||
|
constructor(el: string) {
|
||
|
this.paper = document.querySelector(el)!;
|
||
|
this.newLine();
|
||
|
}
|
||
|
|
||
|
private newLine() {
|
||
|
this._line = document.createElement('div');
|
||
|
this._line.classList.add('line');
|
||
|
this._line.innerText = this._lineBuffer;
|
||
|
this.paper.append(this._line);
|
||
|
this._lineBuffer = '';
|
||
|
}
|
||
|
|
||
|
putChar(val: byte) {
|
||
|
const ascii = val & 0x7f;
|
||
|
const visible = val >= 0x20;
|
||
|
const c = String.fromCharCode(ascii);
|
||
|
|
||
|
if (c === '\r') {
|
||
|
this.newLine();
|
||
|
} else if (c === '\n') {
|
||
|
// eat for now
|
||
|
} else if (c === '\t') {
|
||
|
// possibly not right due to tab stops
|
||
|
this._lineBuffer += ' ';
|
||
|
} else if (ascii === 0x04) {
|
||
|
this._lineBuffer = this._lineBuffer.slice(0, -1);
|
||
|
} else if (visible) {
|
||
|
this._lineBuffer += c;
|
||
|
}
|
||
|
this._line.innerText = this._lineBuffer;
|
||
|
this._raw[this._rawLen] = val;
|
||
|
this._rawLen++;
|
||
|
if (this._rawLen > this._raw.length) {
|
||
|
const newRaw = new Uint8Array(this._raw.length * 2);
|
||
|
newRaw.set(this._raw);
|
||
|
this._raw = newRaw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clear() {
|
||
|
this._lineBuffer = '';
|
||
|
this.paper.innerHTML = '';
|
||
|
this.newLine();
|
||
|
this._raw = new Uint8Array(1024);
|
||
|
this._rawLen = 0;
|
||
|
}
|
||
|
|
||
|
hasPrintout() {
|
||
|
return this.paper.innerText.length > 0;
|
||
|
}
|
||
|
|
||
|
getRawOutput() {
|
||
|
return this._raw.slice(0, this._rawLen);
|
||
|
}
|
||
|
}
|