diff --git a/html_orig/jssrc/term_screen.js b/html_orig/jssrc/term_screen.js index 0fb1d7f..9ed87d9 100644 --- a/html_orig/jssrc/term_screen.js +++ b/html_orig/jssrc/term_screen.js @@ -5,60 +5,48 @@ const frakturExceptions = { 'I': '\u2111', 'R': '\u211c', 'Z': '\u2128' -} +}; // constants for decoding the update blob -const SEQ_SET_COLOR_ATTR = 1 -const SEQ_REPEAT = 2 -const SEQ_SET_COLOR = 3 -const SEQ_SET_ATTR = 4 +const SEQ_SET_COLOR_ATTR = 1; +const SEQ_REPEAT = 2; +const SEQ_SET_COLOR = 3; +const SEQ_SET_ATTR = 4; -const SELECTION_BG = '#b2d7fe' -const SELECTION_FG = '#333' +const SELECTION_BG = '#b2d7fe'; +const SELECTION_FG = '#333'; const themes = [ [ // Tango - '#111213', '#CC0000', '#4E9A06', '#C4A000', '#3465A4', '#75507B', '#06989A', - '#D3D7CF', - '#555753', '#EF2929', '#8AE234', '#FCE94F', '#729FCF', '#AD7FA8', '#34E2E2', - '#EEEEEC' + '#111213', '#CC0000', '#4E9A06', '#C4A000', '#3465A4', '#75507B', '#06989A', '#D3D7CF', + '#555753', '#EF2929', '#8AE234', '#FCE94F', '#729FCF', '#AD7FA8', '#34E2E2', '#EEEEEC', ], [ // Linux - '#000000', '#aa0000', '#00aa00', '#aa5500', '#0000aa', '#aa00aa', '#00aaaa', - '#aaaaaa', - '#555555', '#ff5555', '#55ff55', '#ffff55', '#5555ff', '#ff55ff', '#55ffff', - '#ffffff' + '#000000', '#aa0000', '#00aa00', '#aa5500', '#0000aa', '#aa00aa', '#00aaaa', '#aaaaaa', + '#555555', '#ff5555', '#55ff55', '#ffff55', '#5555ff', '#ff55ff', '#55ffff', '#ffffff', ], [ // xterm - '#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', - '#e5e5e5', - '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', - '#ffffff' + '#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000ee', '#cd00cd', '#00cdcd', '#e5e5e5', + '#7f7f7f', '#ff0000', '#00ff00', '#ffff00', '#5c5cff', '#ff00ff', '#00ffff', '#ffffff', ], [ // rxvt - '#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000cd', '#cd00cd', '#00cdcd', - '#faebd7', - '#404040', '#ff0000', '#00ff00', '#ffff00', '#0000ff', '#ff00ff', '#00ffff', - '#ffffff' + '#000000', '#cd0000', '#00cd00', '#cdcd00', '#0000cd', '#cd00cd', '#00cdcd', '#faebd7', + '#404040', '#ff0000', '#00ff00', '#ffff00', '#0000ff', '#ff00ff', '#00ffff', '#ffffff', ], [ // Ambience - '#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', - '#d3d7cf', - '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', - '#eeeeec' + '#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', + '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec', ], [ // Solarized - '#073642', '#dc322f', '#859900', '#b58900', '#268bd2', '#d33682', '#2aa198', - '#eee8d5', - '#002b36', '#cb4b16', '#586e75', '#657b83', '#839496', '#6c71c4', '#93a1a1', - '#fdf6e3' + '#073642', '#dc322f', '#859900', '#b58900', '#268bd2', '#d33682', '#2aa198', '#eee8d5', + '#002b36', '#cb4b16', '#586e75', '#657b83', '#839496', '#6c71c4', '#93a1a1', '#fdf6e3', ] -] +]; class TermScreen { constructor () { - this.canvas = document.createElement('canvas') - this.ctx = this.canvas.getContext('2d') + this.canvas = document.createElement('canvas'); + this.ctx = this.canvas.getContext('2d'); if ('AudioContext' in window || 'webkitAudioContext' in window) { this.audioCtx = new (window.AudioContext || window.webkitAudioContext)() @@ -76,23 +64,22 @@ class TermScreen { visible: true, hanging: false, style: 'block', - blinkInterval: null - } + blinkInterval: 0, + }; - this._colors = themes[0] + this._colors = themes[0]; this._window = { width: 0, height: 0, devicePixelRatio: 1, - fontFamily: '"DejaVu Sans Mono", "Liberation Mono", "Inconsolata", ' + - 'monospace', + fontFamily: '"DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace', fontSize: 20, gridScaleX: 1.0, gridScaleY: 1.2, blinkStyleOn: true, - blinkInterval: null - } + blinkInterval: null, + }; this.windowState = { width: 0, height: 0, @@ -100,110 +87,109 @@ class TermScreen { gridScaleX: 0, gridScaleY: 0, fontFamily: '', - fontSize: 0 - } + fontSize: 0, + }; this.selection = { selectable: true, start: [0, 0], - end: [0, 0] - } + end: [0, 0], + }; - this.mouseMode = { clicks: false, movement: false } + this.mouseMode = { clicks: false, movement: false }; - const self = this + const self = this; this.window = new Proxy(this._window, { set (target, key, value, receiver) { - target[key] = value - self.updateSize() - self.scheduleDraw() + target[key] = value; + self.updateSize(); + self.scheduleDraw(); return true } - }) + }); - this.screen = [] - this.screenFG = [] - this.screenBG = [] - this.screenAttrs = [] + this.screen = []; + this.screenFG = []; + this.screenBG = []; + this.screenAttrs = []; - this.resetBlink() - this.resetCursorBlink() + this.resetBlink(); + this.resetCursorBlink(); - let selecting = false + let selecting = false; this.canvas.addEventListener('mousedown', e => { if (this.selection.selectable || e.altKey) { - let x = e.offsetX - let y = e.offsetY - selecting = true - this.selection.start = this.selection.end = this.screenToGrid(x, y) + let x = e.offsetX; + let y = e.offsetY; + selecting = true; + this.selection.start = this.selection.end = this.screenToGrid(x, y); this.scheduleDraw() } else { Input.onMouseDown(...this.screenToGrid(e.offsetX, e.offsetY), e.button + 1) } - }) + }); window.addEventListener('mousemove', e => { if (selecting) { - this.selection.end = this.screenToGrid(e.offsetX, e.offsetY) + this.selection.end = this.screenToGrid(e.offsetX, e.offsetY); this.scheduleDraw() } - }) + }); window.addEventListener('mouseup', e => { if (selecting) { - selecting = false - this.selection.end = this.screenToGrid(e.offsetX, e.offsetY) - this.scheduleDraw() + selecting = false; + this.selection.end = this.screenToGrid(e.offsetX, e.offsetY); + this.scheduleDraw(); Object.assign(this.selection, this.getNormalizedSelection()) } - }) + }); this.canvas.addEventListener('mousemove', e => { if (!selecting) { Input.onMouseMove(...this.screenToGrid(e.offsetX, e.offsetY)) } - }) + }); this.canvas.addEventListener('mouseup', e => { if (!selecting) { Input.onMouseUp(...this.screenToGrid(e.offsetX, e.offsetY), e.button + 1) } - }) + }); this.canvas.addEventListener('wheel', e => { if (this.mouseMode.clicks) { Input.onMouseWheel(...this.screenToGrid(e.offsetX, e.offsetY), - e.deltaY > 0 ? 1 : -1) + e.deltaY > 0 ? 1 : -1); // prevent page scrolling e.preventDefault() } - }) + }); // bind ctrl+shift+c to copy key('⌃+⇧+c', e => { - e.preventDefault() + e.preventDefault(); this.copySelectionToClipboard() }) } get colors () { return this._colors } set colors (theme) { - this._colors = theme + this._colors = theme; this.scheduleDraw() } // schedule a draw in the next tick scheduleDraw () { - clearTimeout(this._scheduledDraw) + clearTimeout(this._scheduledDraw); this._scheduledDraw = setTimeout(() => this.draw(), 1) } getFont (modifiers = {}) { - let fontStyle = modifiers.style || 'normal' - let fontWeight = modifiers.weight || 'normal' - return `${fontStyle} normal ${fontWeight} ${ - this.window.fontSize}px ${this.window.fontFamily}` + let fontStyle = modifiers.style || 'normal'; + let fontWeight = modifiers.weight || 'normal'; + return `${fontStyle} normal ${fontWeight} ${this.window.fontSize}px ${this.window.fontFamily}` } getCharSize () { - this.ctx.font = this.getFont() + this.ctx.font = this.getFont(); return { width: this.ctx.measureText(' ').width, @@ -212,59 +198,59 @@ class TermScreen { } updateSize () { - this._window.devicePixelRatio = window.devicePixelRatio || 1 + this._window.devicePixelRatio = window.devicePixelRatio || 1; - let didChange = false + let didChange = false; for (let key in this.windowState) { - if (this.windowState[key] !== this.window[key]) { - didChange = true + if (this.windowState.hasOwnProperty(key) && this.windowState[key] !== this.window[key]) { + didChange = true; this.windowState[key] = this.window[key] } } if (didChange) { const { - width, height, devicePixelRatio, gridScaleX, gridScaleY, fontSize - } = this.window - const charSize = this.getCharSize() + width, height, devicePixelRatio, gridScaleX, gridScaleY + } = this.window; + const charSize = this.getCharSize(); - this.canvas.width = width * devicePixelRatio * charSize.width * gridScaleX + this.canvas.width = width * devicePixelRatio * charSize.width * gridScaleX; this.canvas.style.width = `${Math.ceil(width * charSize.width * - gridScaleX)}px` + gridScaleX)}px`; this.canvas.height = height * devicePixelRatio * charSize.height * - gridScaleY + gridScaleY; this.canvas.style.height = `${Math.ceil(height * charSize.height * gridScaleY)}px` } } resetCursorBlink () { - this.cursor.blinkOn = true - clearInterval(this.cursor.blinkInterval) + this.cursor.blinkOn = true; + clearInterval(this.cursor.blinkInterval); this.cursor.blinkInterval = setInterval(() => { - this.cursor.blinkOn = !this.cursor.blinkOn + this.cursor.blinkOn = !this.cursor.blinkOn; this.scheduleDraw() }, 500) } resetBlink () { - this.window.blinkStyleOn = true - clearInterval(this.window.blinkInterval) - let intervals = 0 + this.window.blinkStyleOn = true; + clearInterval(this.window.blinkInterval); + let intervals = 0; this.window.blinkInterval = setInterval(() => { - intervals++ + intervals++; if (intervals >= 4 && this.window.blinkStyleOn) { - this.window.blinkStyleOn = false + this.window.blinkStyleOn = false; intervals = 0 } else if (intervals >= 1 && !this.window.blinkStyleOn) { - this.window.blinkStyleOn = true + this.window.blinkStyleOn = true; intervals = 0 } }, 200) } getNormalizedSelection () { - let { start, end } = this.selection + let { start, end } = this.selection; // if the start line is after the end line, or if they're both on the same // line but the start column comes after the end column, swap if (start[1] > end[1] || (start[1] === end[1] && start[0] > end[0])) { @@ -274,30 +260,30 @@ class TermScreen { } isInSelection (col, line) { - let { start, end } = this.getNormalizedSelection() - let colAfterStart = start[0] <= col - let colBeforeEnd = col < end[0] - let onStartLine = line === start[1] - let onEndLine = line === end[1] - - if (onStartLine && onEndLine) return colAfterStart && colBeforeEnd - else if (onStartLine) return colAfterStart - else if (onEndLine) return colBeforeEnd + let { start, end } = this.getNormalizedSelection(); + let colAfterStart = start[0] <= col; + let colBeforeEnd = col < end[0]; + let onStartLine = line === start[1]; + let onEndLine = line === end[1]; + + if (onStartLine && onEndLine) return colAfterStart && colBeforeEnd; + else if (onStartLine) return colAfterStart; + else if (onEndLine) return colBeforeEnd; else return start[1] < line && line < end[1] } getSelectedText () { - const screenLength = this.window.width * this.window.height - let lines = [] - let previousLineIndex = -1 + const screenLength = this.window.width * this.window.height; + let lines = []; + let previousLineIndex = -1; for (let cell = 0; cell < screenLength; cell++) { - let x = cell % this.window.width - let y = Math.floor(cell / this.window.width) + let x = cell % this.window.width; + let y = Math.floor(cell / this.window.width); if (this.isInSelection(x, y)) { if (previousLineIndex !== y) { - previousLineIndex = y + previousLineIndex = y; lines.push('') } lines[lines.length - 1] += this.screen[cell] @@ -308,71 +294,71 @@ class TermScreen { } copySelectionToClipboard () { - let selectedText = this.getSelectedText() + let selectedText = this.getSelectedText(); // don't copy anything if nothing is selected - if (!selectedText) return - let textarea = document.createElement('textarea') - document.body.appendChild(textarea) - textarea.value = selectedText - textarea.select() + if (!selectedText) return; + let textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + textarea.value = selectedText; + textarea.select(); if (document.execCommand('copy')) { - Notify.show(`Copied to clipboard`) + Notify.show('Copied to clipboard'); } else { + console.warn('Copy failed'); // unsuccessful copy - // TODO: do something? } - document.body.removeChild(textarea) + document.body.removeChild(textarea); } screenToGrid (x, y) { - let charSize = this.getCharSize() - let cellWidth = charSize.width * this.window.gridScaleX - let cellHeight = charSize.height * this.window.gridScaleY + let charSize = this.getCharSize(); + let cellWidth = charSize.width * this.window.gridScaleX; + let cellHeight = charSize.height * this.window.gridScaleY; return [ Math.floor((x + cellWidth / 2) / cellWidth), Math.floor(y / cellHeight) - ] + ]; } drawCell ({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs }, - compositeAbove = false) { - const ctx = this.ctx - const inSelection = this.isInSelection(x, y) - ctx.fillStyle = inSelection ? SELECTION_BG : this.colors[bg] - if (!compositeAbove) ctx.globalCompositeOperation = 'destination-over' + compositeAbove = false) { + const ctx = this.ctx; + const inSelection = this.isInSelection(x, y); + ctx.fillStyle = inSelection ? SELECTION_BG : this.colors[bg]; + if (!compositeAbove) ctx.globalCompositeOperation = 'destination-over'; ctx.fillRect(x * cellWidth, y * cellHeight, - Math.ceil(cellWidth), Math.ceil(cellHeight)) - ctx.globalCompositeOperation = 'source-over' - - let fontModifiers = {} - let underline = false - let blink = false - let strike = false - if (attrs & 1) fontModifiers.weight = 'bold' - if (attrs & 1 << 1) ctx.globalAlpha = 0.5 - if (attrs & 1 << 2) fontModifiers.style = 'italic' - if (attrs & 1 << 3) underline = true - if (attrs & 1 << 4) blink = true - if (attrs & 1 << 5) text = TermScreen.alphaToFraktur(text) - if (attrs & 1 << 6) strike = true + Math.ceil(cellWidth), Math.ceil(cellHeight)); + ctx.globalCompositeOperation = 'source-over'; + + let fontModifiers = {}; + let underline = false; + let blink = false; + let strike = false; + if (attrs & 1) fontModifiers.weight = 'bold'; + if (attrs & 1 << 1) ctx.globalAlpha = 0.5; + if (attrs & 1 << 2) fontModifiers.style = 'italic'; + if (attrs & 1 << 3) underline = true; + if (attrs & 1 << 4) blink = true; + if (attrs & 1 << 5) text = TermScreen.alphaToFraktur(text); + if (attrs & 1 << 6) strike = true; if (!blink || this.window.blinkStyleOn) { - ctx.font = this.getFont(fontModifiers) - ctx.fillStyle = inSelection ? SELECTION_FG : this.colors[fg] - ctx.fillText(text, (x + 0.5) * cellWidth, (y + 0.5) * cellHeight) + ctx.font = this.getFont(fontModifiers); + ctx.fillStyle = inSelection ? SELECTION_FG : this.colors[fg]; + ctx.fillText(text, (x + 0.5) * cellWidth, (y + 0.5) * cellHeight); if (underline || strike) { let lineY = underline ? y * cellHeight + charSize.height - : (y + 0.5) * cellHeight - - ctx.strokeStyle = inSelection ? SELECTION_FG : this.colors[fg] - ctx.lineWidth = this.window.fontSize / 10 - ctx.lineCap = 'round' - ctx.beginPath() - ctx.moveTo(x * cellWidth, lineY) - ctx.lineTo((x + 1) * cellWidth, lineY) + : (y + 0.5) * cellHeight; + + ctx.strokeStyle = inSelection ? SELECTION_FG : this.colors[fg]; + ctx.lineWidth = this.window.fontSize / 10; + ctx.lineCap = 'round'; + ctx.beginPath(); + ctx.moveTo(x * cellWidth, lineY); + ctx.lineTo((x + 1) * cellWidth, lineY); ctx.stroke() } } @@ -381,76 +367,73 @@ class TermScreen { } draw () { - const ctx = this.ctx + const ctx = this.ctx; const { width, height, devicePixelRatio, - fontFamily, - fontSize, gridScaleX, gridScaleY - } = this.window + } = this.window; - const charSize = this.getCharSize() - const cellWidth = charSize.width * gridScaleX - const cellHeight = charSize.height * gridScaleY - const screenWidth = width * cellWidth - const screenHeight = height * cellHeight - const screenLength = width * height + const charSize = this.getCharSize(); + const cellWidth = charSize.width * gridScaleX; + const cellHeight = charSize.height * gridScaleY; + const screenWidth = width * cellWidth; + const screenHeight = height * cellHeight; + const screenLength = width * height; - ctx.setTransform(this.window.devicePixelRatio, 0, 0, - this.window.devicePixelRatio, 0, 0) - ctx.clearRect(0, 0, screenWidth, screenHeight) + ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0); + ctx.clearRect(0, 0, screenWidth, screenHeight); - ctx.font = this.getFont() - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' + ctx.font = this.getFont(); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; for (let cell = 0; cell < screenLength; cell++) { - let x = cell % width - let y = Math.floor(cell / width) - let isCursor = this.cursor.x === x && this.cursor.y === y - if (this.cursor.hanging) isCursor = false + let x = cell % width; + let y = Math.floor(cell / width); + let isCursor = this.cursor.x === x && this.cursor.y === y; + if (this.cursor.hanging) isCursor = false; let invertForCursor = isCursor && this.cursor.blinkOn && - this.cursor.style === 'block' + this.cursor.style === 'block'; - let text = this.screen[cell] - let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell] - let bg = invertForCursor ? this.screenFG[cell] : this.screenBG[cell] - let attrs = this.screenAttrs[cell] + let text = this.screen[cell]; + let fg = invertForCursor ? this.screenBG[cell] : this.screenFG[cell]; + let bg = invertForCursor ? this.screenFG[cell] : this.screenBG[cell]; + let attrs = this.screenAttrs[cell]; // HACK: ensure cursor is visible - if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0 + if (invertForCursor && fg === bg) bg = fg === 0 ? 7 : 0; this.drawCell({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs - }) + }); if (isCursor && this.cursor.blinkOn && this.cursor.style !== 'block') { - ctx.save() - ctx.beginPath() + ctx.save(); + ctx.beginPath(); if (this.cursor.style === 'bar') { // vertical bar - let barWidth = 2 + let barWidth = 2; ctx.rect(x * cellWidth, y * cellHeight, barWidth, cellHeight) } else if (this.cursor.style === 'line') { // underline - let lineHeight = 2 + let lineHeight = 2; ctx.rect(x * cellWidth, y * cellHeight + charSize.height, cellWidth, lineHeight) } - ctx.clip() + ctx.clip(); // swap foreground/background - fg = this.screenBG[cell] - bg = this.screenFG[cell] + fg = this.screenBG[cell]; + bg = this.screenFG[cell]; // HACK: ensure cursor is visible - if (fg === bg) bg = fg === 0 ? 7 : 0 + if (fg === bg) bg = fg === 0 ? 7 : 0; this.drawCell({ x, y, charSize, cellWidth, cellHeight, text, fg, bg, attrs - }, true) + }, true); ctx.restore() } } @@ -458,115 +441,119 @@ class TermScreen { loadContent (str) { // current index - let i = 0 + let i = 0; // window size - this.window.height = parse2B(str, i) - this.window.width = parse2B(str, i + 2) - this.updateSize() - i += 4 + this.window.height = parse2B(str, i); + this.window.width = parse2B(str, i + 2); + this.updateSize(); + i += 4; // cursor position - let [cursorY, cursorX] = [parse2B(str, i), parse2B(str, i + 2)] - i += 4 - let cursorMoved = (cursorX !== this.cursor.x || cursorY !== this.cursor.y) - this.cursor.x = cursorX - this.cursor.y = cursorY + let [cursorY, cursorX] = [parse2B(str, i), parse2B(str, i + 2)]; + i += 4; + let cursorMoved = (cursorX !== this.cursor.x || cursorY !== this.cursor.y); + this.cursor.x = cursorX; + this.cursor.y = cursorY; - if (cursorMoved) this.resetCursorBlink() + if (cursorMoved) this.resetCursorBlink(); // attributes - let attributes = parse2B(str, i) - i += 2 + let attributes = parse2B(str, i); + i += 2; - this.cursor.visible = !!(attributes & 1) - this.cursor.hanging = !!(attributes & 1 << 1) + this.cursor.visible = !!(attributes & 1); + this.cursor.hanging = !!(attributes & 1 << 1); Input.setAlts( !!(attributes & 1 << 2), // cursors alt !!(attributes & 1 << 3), // numpad alt !!(attributes & 1 << 4) // fn keys alt - ) + ); - let trackMouseClicks = !!(attributes & 1 << 5) - let trackMouseMovement = !!(attributes & 1 << 6) + let trackMouseClicks = !!(attributes & 1 << 5); + let trackMouseMovement = !!(attributes & 1 << 6); - Input.setMouseMode(trackMouseClicks, trackMouseMovement) - this.selection.selectable = !trackMouseMovement + Input.setMouseMode(trackMouseClicks, trackMouseMovement); + this.selection.selectable = !trackMouseMovement; this.mouseMode = { clicks: trackMouseClicks, movement: trackMouseMovement - } + }; - let showButtons = !!(attributes & 1 << 7) - let showConfigLinks = !!(attributes & 1 << 8) + let showButtons = !!(attributes & 1 << 7); + let showConfigLinks = !!(attributes & 1 << 8); - $('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks) - $('#action-buttons').toggleClass('hidden', !showButtons) + $('.x-term-conf-btn').toggleClass('hidden', !showConfigLinks); + $('#action-buttons').toggleClass('hidden', !showButtons); // content - let fg = 7 - let bg = 0 - let attrs = 0 - let cell = 0 // cell index - let text = ' ' - let screenLength = this.window.width * this.window.height - - this.screen = new Array(screenLength).fill(' ') - this.screenFG = new Array(screenLength).fill(' ') - this.screenBG = new Array(screenLength).fill(' ') - this.screenAttrs = new Array(screenLength).fill(' ') + let fg = 7; + let bg = 0; + let attrs = 0; + let cell = 0; // cell index + let text = ' '; + let screenLength = this.window.width * this.window.height; + + this.screen = new Array(screenLength).fill(' '); + this.screenFG = new Array(screenLength).fill(' '); + this.screenBG = new Array(screenLength).fill(' '); + this.screenAttrs = new Array(screenLength).fill(' '); while (i < str.length && cell < screenLength) { - let character = str[i++] - let charCode = character.charCodeAt(0) + let character = str[i++]; + let charCode = character.charCodeAt(0); if (charCode === SEQ_SET_COLOR_ATTR) { - let data = parse3B(str, i) - i += 3 - fg = data & 0xF - bg = data >> 4 & 0xF + let data = parse3B(str, i); + i += 3; + fg = data & 0xF; + bg = data >> 4 & 0xF; attrs = data >> 8 & 0xFF - } else if (charCode == SEQ_SET_COLOR) { - let data = parse2B(str, i) - i += 2 - fg = data & 0xF + } + else if (charCode == SEQ_SET_COLOR) { + let data = parse2B(str, i); + i += 2; + fg = data & 0xF; bg = data >> 4 & 0xF - } else if (charCode === SEQ_SET_ATTR) { - let data = parse2B(str, i) - i += 2 + } + else if (charCode === SEQ_SET_ATTR) { + let data = parse2B(str, i); + i += 2; attrs = data & 0xFF - } else if (charCode === SEQ_REPEAT) { - let count = parse2B(str, i) - i += 2 + } + else if (charCode === SEQ_REPEAT) { + let count = parse2B(str, i); + i += 2; for (let j = 0; j < count; j++) { - this.screen[cell] = text - this.screenFG[cell] = fg - this.screenBG[cell] = bg - this.screenAttrs[cell] = attrs + this.screen[cell] = text; + this.screenFG[cell] = fg; + this.screenBG[cell] = bg; + this.screenAttrs[cell] = attrs; if (++cell > screenLength) break } - } else { + } + else { // unique cell character - this.screen[cell] = text = character - this.screenFG[cell] = fg - this.screenBG[cell] = bg - this.screenAttrs[cell] = attrs + this.screen[cell] = text = character; + this.screenFG[cell] = fg; + this.screenBG[cell] = bg; + this.screenAttrs[cell] = attrs; cell++ } } - this.scheduleDraw() + this.scheduleDraw(); if (this.onload) this.onload() } /** Apply labels to buttons and screen title (leading T removed already) */ loadLabels (str) { - let pieces = str.split('\x01') - qs('h1').textContent = pieces[0] + let pieces = str.split('\x01'); + qs('h1').textContent = pieces[0]; $('#action-buttons button').forEach((button, i) => { - var label = pieces[i + 1].trim() + let label = pieces[i + 1].trim(); // if empty string, use the "dim" effect and put nbsp instead to // stretch the button vertically button.innerHTML = label ? e(label) : ' '; @@ -575,34 +562,33 @@ class TermScreen { } load (str) { - const content = str.substr(1) + const content = str.substr(1); switch (str[0]) { case 'S': - this.loadContent(content) - break + this.loadContent(content); + break; case 'T': - this.loadLabels(content) - break + this.loadLabels(content); + break; case 'B': - this.beep() - break + this.beep(); + break; default: - console.warn(`Bad data message type; ignoring.\n${ - JSON.stringify(content)}`) + console.warn(`Bad data message type; ignoring.\n${JSON.stringify(content)}`) } } beep () { - const audioCtx = this.audioCtx - if (!audioCtx) return + const audioCtx = this.audioCtx; + if (!audioCtx) return; - let osc, gain + let osc, gain; // main beep - osc = audioCtx.createOscillator() - gain = audioCtx.createGain() - osc.connect(gain) + osc = audioCtx.createOscillator(); + gain = audioCtx.createGain(); + osc.connect(gain); gain.connect(audioCtx.destination); gain.gain.value = 0.5; osc.frequency.value = 750; @@ -633,13 +619,16 @@ class TermScreen { } } -const Screen = new TermScreen() -let didAddScreen = false +const Screen = new TermScreen(); + +let didAddScreen = false; Screen.onload = function () { - if (didAddScreen) return - didAddScreen = true - qs('#screen').appendChild(Screen.canvas) + if (didAddScreen) return; + didAddScreen = true; + qs('#screen').appendChild(Screen.canvas); for (let item of qs('#screen').classList) { - if (item.startsWith('theme-')) Screen.colors = themes[item.substr(6)] + if (item.startsWith('theme-')) { + Screen.colors = themes[item.substr(6)] + } } -} +}; diff --git a/libesphttpd b/libesphttpd index 3479ab3..13fa224 160000 --- a/libesphttpd +++ b/libesphttpd @@ -1 +1 @@ -Subproject commit 3479ab3efcb4581669370cde6a607f936ff5515a +Subproject commit 13fa224963081e9ff298abd74a59faafcb9bf816