From 0da19bca30b8dd9338739e86a6d87af589075248 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Fri, 6 Oct 2017 22:37:24 +0200 Subject: [PATCH 01/13] Start on new `themes` command in demo --- js/term/demo.js | 177 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 151 insertions(+), 26 deletions(-) diff --git a/js/term/demo.js b/js/term/demo.js index 885fe04..9f41973 100644 --- a/js/term/demo.js +++ b/js/term/demo.js @@ -143,6 +143,8 @@ class ScrollingTerminal { this.cursor = { x: 0, y: 0, style: 1, visible: true } this.trackMouse = false this.theme = 0 + this.defaultFG = 7 + this.defaultBG = 0 this.rainbow = this.superRainbow = false this.parser.reset() this.clear() @@ -274,10 +276,10 @@ class ScrollingTerminal { data += encodeAsCodePoint(25) data += encodeAsCodePoint(80) data += encodeAsCodePoint(this.theme) - data += encodeAsCodePoint(7) - data += encodeAsCodePoint(0) - data += encodeAsCodePoint(0) - data += encodeAsCodePoint(0) + data += encodeAsCodePoint(this.defaultFG & 0xFFFF) + data += encodeAsCodePoint(this.defaultFG >> 16) + data += encodeAsCodePoint(this.defaultBG & 0xFFFF) + data += encodeAsCodePoint(this.defaultBG >> 16) let attributes = +this.cursor.visible attributes |= (3 << 5) * +this.trackMouse // track mouse controls both attributes |= 3 << 7 // buttons/links always visible @@ -647,37 +649,160 @@ let demoshIndex = { } }, themes: class ShowThemes extends Process { - color (hex) { - hex = parseInt(hex.substr(1), 16) - let r = hex >> 16 - let g = (hex >> 8) & 0xFF - let b = hex & 0xFF - this.emit('write', `\x1b[48;2;${r};${g};${b}m`) - if (((r + g + b) / 3) > 127) { - this.emit('write', '\x1b[38;5;16m') - } else { - this.emit('write', '\x1b[38;5;255m') - } + constructor (shell) { + super() + this.shell = shell + this.parser = new ANSIParser((...args) => this.handler(...args)) } + + destroy () { + this.shell.terminal.cursor.style = this.savedCursorStyle + this.emit('write', '\n\n') + super.destroy() + } + run (...args) { - for (let i in themes) { - let theme = themes[i] + this.savedCursorStyle = this.shell.terminal.cursor.style + this.shell.terminal.cursor.style = 3 + + this.fgType = 0 + this.bgType = 0 + + let get24FG = () => this.shell.terminal.defaultFG - 256 + let set24FG = v => { this.shell.terminal.defaultFG = v + 256 } + + this.controls = [ + { + label: 'Theme: ', + length: themes.length.toString().length, + getValue: () => this.shell.terminal.theme, + setValue: value => { + let count = themes.length + this.shell.terminal.theme = ((value % count) + count) % count + } + }, + { + label: ' Default Foreground: ', + length: 6, + getValue: () => this.fgType, + getDisplay: () => this.fgType === 0 ? '256' : '24-bit', + setValue: value => { + this.fgType = ((value % 2) + 2) % 2 + } + }, + { + label: ' ', + length: 3, + getValue: () => this.shell.terminal.defaultFG, + setValue: value => { + this.shell.terminal.defaultFG = value & 0xFF + }, + shouldShow: () => this.fgType === 0 + }, + { + label: ' ', + length: 2, + fill: '0', + getValue: () => get24FG() >> 16, + getDisplay: () => (get24FG() >> 16).toString(16), + setValue: value => set24FG(get24FG() & 0x00FFFF | ((value & 0xFF) << 16)), + shouldShow: () => this.fgType === 1 + }, + { + length: 2, + fill: '0', + getValue: () => (get24FG() >> 8) & 0xFF, + getDisplay: () => ((get24FG() >> 8) & 0xFF).toString(16), + setValue: value => set24FG(get24FG() & 0xFF00FF | ((value & 0xFF) << 8)), + shouldShow: () => this.fgType === 1 + }, + { + length: 2, + fill: '0', + getValue: () => get24FG() & 0xFF, + getDisplay: () => (get24FG() & 0xFF).toString(16), + setValue: value => set24FG(get24FG() & 0xFFFF00 | (value & 0xFF)), + shouldShow: () => this.fgType === 1 + }, + { + label: ' Default Background: ', + length: 2, + getValue: () => this.shell.terminal.defaultBG, + getDisplay: () => this.shell.terminal.defaultBG.toString(16), + setValue: value => { + this.shell.terminal.defaultBG = value & 0xFF + } + } + ] + this.selection = 0 - let name = ` ${i}`.substr(-2) + this.emit('write', '\x1b[1mThemes\x1b[m\n\n\n\n\x1b[2A') - this.emit('write', `Theme ${name}: `) + this.render() + } - for (let col = 0; col < 16; col++) { - let text = ` ${col}`.substr(-2) - this.color(theme[col]) - this.emit('write', text) - this.emit('write', '\x1b[m ') + render () { + this.emit('write', '\x1b[m\r') + // no ^[2K implementation, here's a hack + this.emit('write', ' '.repeat(this.shell.terminal.width - 1) + '\r') + + let index = 0 + let selectedX = 0 + for (let control of this.controls) { + if (control.shouldShow && !control.shouldShow()) continue + if (control.label) { + this.emit('write', `\x1b[1m${control.label}\x1b[m`) + } + // TODO: colors + this.emit('write', '\x1b[38;5;255m') + let value = control.getDisplay ? control.getDisplay() : control.getValue().toString() + this.emit('write', ((control.fill || ' ').repeat(Math.max(0, control.length - value.length))) + value) + this.emit('write', '\x1b[m') + + if (index === this.selection) { + selectedX = this.shell.terminal.cursor.x - 1 + + // draw arrows + this.emit('write', '\x1b[m\x1b[D\x1b[A▲\x1b[D\x1b[2B▼\x1b[A') + } else { + // clear arrows if they were there + this.emit('write', '\x1b[m\x1b[D\x1b[A \x1b[D\x1b[2B \x1b[A') } - this.emit('write', '\n') + index++ } - this.destroy() + this.shell.terminal.cursor.x = selectedX + } + + write (data) { + this.parser.write(data) + } + + handler (action, ...args) { + console.log(action, ...args) + + if (action === 'move-cursor-x') { + this.selection += args[0] + let count = this.controls.length + this.selection = ((this.selection % count) + count) % count + } else if (action === 'move-cursor-y') { + let selected = null + let index = 0 + for (let control of this.controls) { + if (control.shouldShow && !control.shouldShow()) continue + if (index === this.selection) { + selected = control + break + } + index++ + } + if (selected) { + selected.setValue(selected.getValue() - args[0]) + } + } + + this.render() } }, cursor: class SetCursor extends Process { From 09da0690dd5028e6aa99c1379d71e474e754ccc6 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Fri, 6 Oct 2017 23:07:01 +0200 Subject: [PATCH 02/13] Demo `themes`: Finish basic functionality --- js/term/demo.js | 135 +++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 46 deletions(-) diff --git a/js/term/demo.js b/js/term/demo.js index 9f41973..7135e83 100644 --- a/js/term/demo.js +++ b/js/term/demo.js @@ -670,6 +670,27 @@ let demoshIndex = { let get24FG = () => this.shell.terminal.defaultFG - 256 let set24FG = v => { this.shell.terminal.defaultFG = v + 256 } + let get24BG = () => this.shell.terminal.defaultBG - 256 + let set24BG = v => { this.shell.terminal.defaultBG = v + 256 } + + let make24Control = (label, index, getValue, setValue, type) => { + index *= 4 + + return { + label, + length: 1, + getValue: () => (getValue() >> index) & 0xF, + getDisplay: () => ((getValue() >> index) & 0xF).toString(16), + setValue: value => { + setValue((getValue() & (0xFFFFFF ^ (0xF << index))) | ((value & 0xF) << index)) + }, + shouldShow: () => this[type + 'Type'] === 1, + parseValue: input => { + return parseInt(input, 16) & 0xF + }, + moveAfterInput: index !== 0 + } + } this.controls = [ { @@ -682,7 +703,7 @@ let demoshIndex = { } }, { - label: ' Default Foreground: ', + label: ' Default Foreground: ', length: 6, getValue: () => this.fgType, getDisplay: () => this.fgType === 0 ? '256' : '24-bit', @@ -693,46 +714,44 @@ let demoshIndex = { { label: ' ', length: 3, - getValue: () => this.shell.terminal.defaultFG, + getValue: () => this.shell.terminal.defaultFG & 0xFF, setValue: value => { this.shell.terminal.defaultFG = value & 0xFF }, - shouldShow: () => this.fgType === 0 - }, - { - label: ' ', - length: 2, - fill: '0', - getValue: () => get24FG() >> 16, - getDisplay: () => (get24FG() >> 16).toString(16), - setValue: value => set24FG(get24FG() & 0x00FFFF | ((value & 0xFF) << 16)), - shouldShow: () => this.fgType === 1 + shouldShow: () => this.fgType === 0, + parseValue: input => parseInt(input, 16) }, + make24Control(' #', 5, get24FG, set24FG, 'fg'), + make24Control('', 4, get24FG, set24FG, 'fg'), + make24Control('', 3, get24FG, set24FG, 'fg'), + make24Control('', 2, get24FG, set24FG, 'fg'), + make24Control('', 1, get24FG, set24FG, 'fg'), + make24Control('', 0, get24FG, set24FG, 'fg'), { - length: 2, - fill: '0', - getValue: () => (get24FG() >> 8) & 0xFF, - getDisplay: () => ((get24FG() >> 8) & 0xFF).toString(16), - setValue: value => set24FG(get24FG() & 0xFF00FF | ((value & 0xFF) << 8)), - shouldShow: () => this.fgType === 1 - }, - { - length: 2, - fill: '0', - getValue: () => get24FG() & 0xFF, - getDisplay: () => (get24FG() & 0xFF).toString(16), - setValue: value => set24FG(get24FG() & 0xFFFF00 | (value & 0xFF)), - shouldShow: () => this.fgType === 1 + label: ' Default Background: ', + length: 6, + getValue: () => this.bgType, + getDisplay: () => this.bgType === 0 ? '256' : '24-bit', + setValue: value => { + this.bgType = ((value % 2) + 2) % 2 + } }, { - label: ' Default Background: ', - length: 2, - getValue: () => this.shell.terminal.defaultBG, - getDisplay: () => this.shell.terminal.defaultBG.toString(16), + label: ' ', + length: 3, + getValue: () => this.shell.terminal.defaultBG & 0xFF, setValue: value => { this.shell.terminal.defaultBG = value & 0xFF - } - } + }, + shouldShow: () => this.bgType === 0, + parseValue: input => parseInt(input, 16) + }, + make24Control(' #', 5, get24BG, set24BG, 'bg'), + make24Control('', 4, get24BG, set24BG, 'bg'), + make24Control('', 3, get24BG, set24BG, 'bg'), + make24Control('', 2, get24BG, set24BG, 'bg'), + make24Control('', 1, get24BG, set24BG, 'bg'), + make24Control('', 0, get24BG, set24BG, 'bg') ] this.selection = 0 @@ -754,9 +773,10 @@ let demoshIndex = { this.emit('write', `\x1b[1m${control.label}\x1b[m`) } // TODO: colors - this.emit('write', '\x1b[38;5;255m') + this.emit('write', '\x1b[38;5;255m\x1b[48;5;16m') let value = control.getDisplay ? control.getDisplay() : control.getValue().toString() - this.emit('write', ((control.fill || ' ').repeat(Math.max(0, control.length - value.length))) + value) + this.emit('write', (control.fill || ' ').repeat(Math.max(0, control.length - value.length))) + this.emit('write', value.substr(0, control.length)) this.emit('write', '\x1b[m') if (index === this.selection) { @@ -779,26 +799,49 @@ let demoshIndex = { this.parser.write(data) } + getControlCount () { + let count = 0 + for (let control of this.controls) { + if (control.shouldShow && !control.shouldShow()) continue + count++ + } + return count + } + + getSelectedControl () { + let selected = null + let index = 0 + for (let control of this.controls) { + if (control.shouldShow && !control.shouldShow()) continue + if (index === this.selection) { + selected = control + break + } + index++ + } + return selected + } + handler (action, ...args) { console.log(action, ...args) if (action === 'move-cursor-x') { this.selection += args[0] - let count = this.controls.length + let count = this.getControlCount() this.selection = ((this.selection % count) + count) % count } else if (action === 'move-cursor-y') { - let selected = null - let index = 0 - for (let control of this.controls) { - if (control.shouldShow && !control.shouldShow()) continue - if (index === this.selection) { - selected = control - break + let control = this.getSelectedControl() + if (control) control.setValue(control.getValue() - args[0]) + } else if (action === 'write') { + let control = this.getSelectedControl() + if (control && control.parseValue) { + let parsed = control.parseValue(args[0]) + if (Number.isFinite(parsed)) { + control.setValue(parsed) + if (control.moveAfterInput) { + if (this.selection < this.getControlCount() - 1) this.selection++ + } } - index++ - } - if (selected) { - selected.setValue(selected.getValue() - args[0]) } } From d4931c1f3125b5df1ad86c5a755f29c679a9b142 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Fri, 6 Oct 2017 23:28:36 +0200 Subject: [PATCH 03/13] Add support for background images in renderer --- js/term/screen_renderer.js | 40 +++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/js/term/screen_renderer.js b/js/term/screen_renderer.js index 270e484..ae64fc3 100644 --- a/js/term/screen_renderer.js +++ b/js/term/screen_renderer.js @@ -180,8 +180,9 @@ module.exports = class ScreenRenderer { * @param {number} options.cellWidth - cell width in pixels * @param {number} options.cellHeight - cell height in pixels * @param {number} options.bg - the background color + * @param {number} options.isDefaultBG - if true, will draw image background if available */ - drawBackground ({ x, y, cellWidth, cellHeight, bg }) { + drawBackground ({ x, y, cellWidth, cellHeight, bg, isDefaultBG }) { const ctx = this.ctx const { width, height } = this.screen.window const padding = Math.round(this.screen._padding) @@ -189,6 +190,8 @@ module.exports = class ScreenRenderer { let screenX = x * cellWidth + padding let screenY = y * cellHeight + padding let isBorderCell = x === 0 || y === 0 || x === width - 1 || y === height - 1 + + let fillX, fillY, fillWidth, fillHeight if (isBorderCell) { let left = screenX let top = screenY @@ -198,11 +201,25 @@ module.exports = class ScreenRenderer { else if (x === width - 1) right += padding if (y === 0) top -= padding else if (y === height - 1) bottom += padding - ctx.clearRect(left, top, right - left, bottom - top) - ctx.fillRect(left, top, right - left, bottom - top) + + fillX = left + fillY = top + fillWidth = right - left + fillHeight = bottom - top + } else { + fillX = screenX + fillY = screenY + fillWidth = cellWidth + fillHeight = cellHeight + } + + ctx.clearRect(fillX, fillY, fillWidth, fillHeight) + + if (isDefaultBG && bg >= 0 && this.backgroundImage) { + ctx.drawImage(this.backgroundImage, fillX, fillY, fillWidth, fillHeight, + fillX, fillY, fillWidth, fillHeight) } else { - ctx.clearRect(screenX, screenY, cellWidth, cellHeight) - ctx.fillRect(screenX, screenY, cellWidth, cellHeight) + ctx.fillRect(fillX, fillY, fillWidth, fillHeight) } } @@ -497,8 +514,13 @@ module.exports = class ScreenRenderer { let bg = this.screen.screenBG[cell] | 0 let attrs = this.screen.screenAttrs[cell] | 0 + let isDefaultBG = false + if (!(attrs & ATTR_FG)) fg = this.defaultFgNum - if (!(attrs & ATTR_BG)) bg = this.defaultBgNum + if (!(attrs & ATTR_BG)) { + bg = this.defaultBgNum + isDefaultBG = true + } if (attrs & ATTR_INVERSE) [fg, bg] = [bg, fg] // swap - reversed character colors if (this.screen.reverseVideo) [fg, bg] = [bg, fg] // swap - reversed all screen @@ -525,7 +547,7 @@ module.exports = class ScreenRenderer { let font = attrs & FONT_MASK if (!fontGroups.has(font)) fontGroups.set(font, []) - fontGroups.get(font).push({ cell, x, y, text, fg, bg, attrs, isCursor, inSelection }) + fontGroups.get(font).push({ cell, x, y, text, fg, bg, attrs, isCursor, inSelection, isDefaultBG }) updateMap.set(cell, didUpdate) } @@ -595,10 +617,10 @@ module.exports = class ScreenRenderer { // pass 1: backgrounds for (let font of fontGroups.keys()) { for (let data of fontGroups.get(font)) { - let { cell, x, y, text, bg } = data + let { cell, x, y, text, bg, isDefaultBG } = data if (redrawMap.get(cell)) { - this.drawBackground({ x, y, cellWidth, cellHeight, bg }) + this.drawBackground({ x, y, cellWidth, cellHeight, bg, isDefaultBG }) if (this.screen.window.debug && this.screen._debug) { // set cell flags From 7fbe736ce2e4d159afd3c85eb790dae9b6155f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 7 Oct 2017 00:50:59 +0200 Subject: [PATCH 04/13] fix charset parsing code to work with new format in back-end sources --- base.php | 11 ++++++++++- pages/help/charsets.php | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/base.php b/base.php index 57ce7fb..d62edbe 100644 --- a/base.php +++ b/base.php @@ -173,9 +173,18 @@ if (!function_exists('load_esp_charsets')) { $rows = array_map('trim', $rows); foreach($rows as $j => $v) { + $literal = false; if (strpos($v, '0x') === 0) { + // hexa codes $v = substr($v, 2); $v = hexdec($v); + } else if (strpos($v, 'u\'\\0\'') === 0) { + // zero + $v = 0; + } else if (strpos($v, 'u\'') === 0) { + // utf8 literals + $v = mb_substr($v, 2, 1, 'utf-8'); + $literal = true; } else { $v = intval($v); } @@ -183,7 +192,7 @@ if (!function_exists('load_esp_charsets')) { $table[] = [ $ascii, chr($ascii), - utf8($v==0? $ascii :$v), + $literal ? $v : utf8($v==0? $ascii :$v), ]; } $cps[$name] = $table; diff --git a/pages/help/charsets.php b/pages/help/charsets.php index 961eda6..da28fa1 100644 --- a/pages/help/charsets.php +++ b/pages/help/charsets.php @@ -21,6 +21,8 @@
  • `A` - UK ASCII: # replaced with £
  • `0` - Symbols and basic line drawing (standard DEC alternate character set)
  • `1` - Symbols and advanced line drawing (based on DOS codepage 437, ESPTerm specific)
  • +
  • `2` - Block characters and thick line drawing (ESPTerm specific)
  • +
  • `3` - Extra line drawing (ESPTerm specific)
  • From f28fc5094ccdb601cebd71dded42c4a55bfbd731 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sat, 7 Oct 2017 08:24:43 +0200 Subject: [PATCH 05/13] Draw nothing if backgroundImage is true --- js/term/screen_renderer.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/js/term/screen_renderer.js b/js/term/screen_renderer.js index ae64fc3..dc579ad 100644 --- a/js/term/screen_renderer.js +++ b/js/term/screen_renderer.js @@ -215,10 +215,7 @@ module.exports = class ScreenRenderer { ctx.clearRect(fillX, fillY, fillWidth, fillHeight) - if (isDefaultBG && bg >= 0 && this.backgroundImage) { - ctx.drawImage(this.backgroundImage, fillX, fillY, fillWidth, fillHeight, - fillX, fillY, fillWidth, fillHeight) - } else { + if (!isDefaultBG || bg < 0 || !this.backgroundImage) { ctx.fillRect(fillX, fillY, fillWidth, fillHeight) } } From 3e7a2164506740266cb1e4b3a74f54176edac5af Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sat, 7 Oct 2017 08:32:02 +0200 Subject: [PATCH 06/13] Add TermScreen#backgroundImage --- js/term/screen.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/js/term/screen.js b/js/term/screen.js index 4a28355..f049049 100644 --- a/js/term/screen.js +++ b/js/term/screen.js @@ -305,6 +305,19 @@ module.exports = class TermScreen extends EventEmitter { this._scheduledSizeUpdate = setTimeout(() => this.updateSize(), 1) } + get backgroundImage () { + return this.canvas.style.backgroundImage + } + + set backgroundImage (value) { + this.canvas.style.backgroundImage = value ? `url(${value})` : '' + if (this.renderer.backgroundImage !== !!value) { + this.renderer.backgroundImage = !!value + this.renderer.resetDrawn() + this.scheduleDraw('background-image') + } + } + /** * Returns a CSS font string with this TermScreen's font settings and the * font modifiers. From af5f47d890b9d30ee7a35730afb216e04f8a53a7 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sat, 7 Oct 2017 08:37:56 +0200 Subject: [PATCH 07/13] Fix call to non-existent method --- js/term/screen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/term/screen.js b/js/term/screen.js index f049049..2fb13eb 100644 --- a/js/term/screen.js +++ b/js/term/screen.js @@ -314,7 +314,7 @@ module.exports = class TermScreen extends EventEmitter { if (this.renderer.backgroundImage !== !!value) { this.renderer.backgroundImage = !!value this.renderer.resetDrawn() - this.scheduleDraw('background-image') + this.renderer.scheduleDraw('background-image') } } From 75fb70c0833af519e2f4af1a3f44a46ca4908ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 7 Oct 2017 21:59:20 +0200 Subject: [PATCH 08/13] move attr bits to own file, make Load Failed text look nicer --- js/appcommon.js | 1 + js/term/screen_attr_bits.js | 15 +++++++++++++++ js/term/screen_parser.js | 24 +++++++++++++----------- js/term/screen_renderer.js | 35 +++++++++++++++++++---------------- sass/pages/_term.scss | 8 +++++++- 5 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 js/term/screen_attr_bits.js diff --git a/js/appcommon.js b/js/appcommon.js index 963bc5a..7b99806 100644 --- a/js/appcommon.js +++ b/js/appcommon.js @@ -169,6 +169,7 @@ $.ready(function () { 'Server connection failed! Trying again' + '.' qs('#screen').appendChild(bnr) + qs('#screen').classList.add('failed') showPage() } }, 2000) diff --git a/js/term/screen_attr_bits.js b/js/term/screen_attr_bits.js new file mode 100644 index 0000000..abb976b --- /dev/null +++ b/js/term/screen_attr_bits.js @@ -0,0 +1,15 @@ +// Bits in the cell attribs word + +/* eslint-disable no-multi-spaces */ +exports.ATTR_FG = (1 << 0) // 1 if not using default background color (ignore cell bg) - color extension bit +exports.ATTR_BG = (1 << 1) // 1 if not using default foreground color (ignore cell fg) - color extension bit +exports.ATTR_BOLD = (1 << 2) // Bold font +exports.ATTR_UNDERLINE = (1 << 3) // Underline decoration +exports.ATTR_INVERSE = (1 << 4) // Invert colors - this is useful so we can clear then with SGR manipulation commands +exports.ATTR_BLINK = (1 << 5) // Blinking +exports.ATTR_ITALIC = (1 << 6) // Italic font +exports.ATTR_STRIKE = (1 << 7) // Strike-through decoration +exports.ATTR_OVERLINE = (1 << 8) // Over-line decoration +exports.ATTR_FAINT = (1 << 9) // Faint foreground color (reduced alpha) +exports.ATTR_FRAKTUR = (1 << 10) // Fraktur font (unicode substitution) +/* eslint-enable no-multi-spaces */ diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js index 1e9f197..a60a10b 100644 --- a/js/term/screen_parser.js +++ b/js/term/screen_parser.js @@ -1,6 +1,17 @@ const $ = require('../lib/chibi') const { qs } = require('../utils') +const { + ATTR_FG, + ATTR_BG, + ATTR_BOLD, + ATTR_UNDERLINE, + ATTR_BLINK, + ATTR_STRIKE, + ATTR_OVERLINE, + ATTR_FAINT +} = require('./screen_attr_bits') + // constants for decoding the update blob const SEQ_SKIP = 1 const SEQ_REPEAT = 2 @@ -39,17 +50,6 @@ const OPT_CRLF_MODE = (1 << 12) const OPT_BRACKETED_PASTE = (1 << 13) const OPT_REVERSE_VIDEO = (1 << 14) -const ATTR_FG = (1 << 0) // 1 if not using default background color (ignore cell bg) - color extension bit -const ATTR_BG = (1 << 1) // 1 if not using default foreground color (ignore cell fg) - color extension bit -const ATTR_BOLD = (1 << 2) // Bold font -const ATTR_UNDERLINE = (1 << 3) // Underline decoration -const ATTR_INVERSE = (1 << 4) // Invert colors - this is useful so we can clear then with SGR manipulation commands -const ATTR_BLINK = (1 << 5) // Blinking -const ATTR_ITALIC = (1 << 6) // Italic font -const ATTR_STRIKE = (1 << 7) // Strike-through decoration -const ATTR_OVERLINE = (1 << 8) // Over-line decoration -const ATTR_FAINT = (1 << 9) // Faint foreground color (reduced alpha) -const ATTR_FRAKTUR = (1 << 10) // Fraktur font (unicode substitution) /* eslint-enable no-multi-spaces */ module.exports = class ScreenParser { @@ -65,7 +65,9 @@ module.exports = class ScreenParser { */ hideLoadFailedMsg () { if (!this.contentLoaded) { + let scr = qs('#screen') let errmsg = qs('#load-failed') + if (scr) scr.classList.remove('failed') if (errmsg) errmsg.parentNode.removeChild(errmsg) this.contentLoaded = true } diff --git a/js/term/screen_renderer.js b/js/term/screen_renderer.js index dc579ad..66986f5 100644 --- a/js/term/screen_renderer.js +++ b/js/term/screen_renderer.js @@ -1,4 +1,22 @@ -const { themes, buildColorTable, SELECTION_FG, SELECTION_BG } = require('./themes') +const { + themes, + buildColorTable, + SELECTION_FG, SELECTION_BG +} = require('./themes') + +const { + ATTR_FG, + ATTR_BG, + ATTR_BOLD, + ATTR_UNDERLINE, + ATTR_INVERSE, + ATTR_BLINK, + ATTR_ITALIC, + ATTR_STRIKE, + ATTR_OVERLINE, + ATTR_FAINT, + ATTR_FRAKTUR +} = require('./screen_attr_bits') // Some non-bold Fraktur symbols are outside the contiguous block const frakturExceptions = { @@ -9,21 +27,6 @@ const frakturExceptions = { 'Z': '\u2128' } -// TODO do not repeat - this is also defined in screen_parser ... -/* eslint-disable no-multi-spaces */ -const ATTR_FG = (1 << 0) // 1 if not using default background color (ignore cell bg) - color extension bit -const ATTR_BG = (1 << 1) // 1 if not using default foreground color (ignore cell fg) - color extension bit -const ATTR_BOLD = (1 << 2) // Bold font -const ATTR_UNDERLINE = (1 << 3) // Underline decoration -const ATTR_INVERSE = (1 << 4) // Invert colors - this is useful so we can clear then with SGR manipulation commands -const ATTR_BLINK = (1 << 5) // Blinking -const ATTR_ITALIC = (1 << 6) // Italic font -const ATTR_STRIKE = (1 << 7) // Strike-through decoration -const ATTR_OVERLINE = (1 << 8) // Over-line decoration -const ATTR_FAINT = (1 << 9) // Faint foreground color (reduced alpha) -const ATTR_FRAKTUR = (1 << 10) // Fraktur font (unicode substitution) -/* eslint-enable no-multi-spaces */ - module.exports = class ScreenRenderer { constructor (screen) { this.screen = screen diff --git a/sass/pages/_term.scss b/sass/pages/_term.scss index c269de9..3b82cb5 100644 --- a/sass/pages/_term.scss +++ b/sass/pages/_term.scss @@ -140,7 +140,13 @@ body.term { color: red; font-size: 18px; font-weight: bold; - margin: 10px 5px 14px 5px; + margin: 20px 15px; +} + +#screen.failed { + canvas, .screen-margin { + display: none; + } } #term-nav { From 608a393b6329c09f8597d846851be9c44345ad1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 7 Oct 2017 22:08:06 +0200 Subject: [PATCH 09/13] added backdrop url topic W --- js/term/screen_parser.js | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js index a60a10b..9aa68f4 100644 --- a/js/term/screen_parser.js +++ b/js/term/screen_parser.js @@ -35,6 +35,7 @@ const TOPIC_BUTTONS = 'B' const TOPIC_CURSOR = 'C' const TOPIC_INTERNAL = 'D' const TOPIC_BELL = '!' +const TOPIC_BACKDROP = 'W' const OPT_CURSOR_VISIBLE = (1 << 0) const OPT_DEBUGBAR = (1 << 1) @@ -84,6 +85,19 @@ module.exports = class ScreenParser { const topics = du(strArray[ci++]) // this.screen.cursor.hanging = !!(attributes & (1 << 1)) + let collectOneTerminatedString = () => { + // TODO optimize this + text = '' + while (ci < strArray.length) { + let c = strArray[ci++] + if (c !== '\x01') { + text += c + } else { + break + } + } + } + while (ci < strArray.length) { const topic = strArray[ci++] @@ -179,17 +193,7 @@ module.exports = class ScreenParser { this.screen.renderer.scheduleDraw('cursor-moved') } else if (topic === TOPIC_TITLE) { - // TODO optimize this - text = '' - while (ci < strArray.length) { - let c = strArray[ci++] - if (c !== '\x01') { - text += c - } else { - break - } - } - + text = collectOneTerminatedString() qs('#screen-title').textContent = text if (text.length === 0) text = 'Terminal' qs('title').textContent = `${text} :: ESPTerm` @@ -199,16 +203,16 @@ module.exports = class ScreenParser { let labels = [] for (let j = 0; j < count; j++) { - text = '' - while (ci < strArray.length) { - let c = strArray[ci++] - if (c === '\x01') break - text += c - } + text = collectOneTerminatedString() labels.push(text) } this.screen.emit('button-labels', labels) + } else if (topic === TOPIC_BACKDROP) { + + text = collectOneTerminatedString() + this.screen.backgroundImage = text + } else if (topic === TOPIC_BELL) { this.screen.beep() From 80f0ca7202c0bf657103ce0765d440542450adaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 7 Oct 2017 23:46:06 +0200 Subject: [PATCH 10/13] fix a megabug --- js/term/screen_parser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js index 9aa68f4..93f4b09 100644 --- a/js/term/screen_parser.js +++ b/js/term/screen_parser.js @@ -96,6 +96,7 @@ module.exports = class ScreenParser { break } } + return text } while (ci < strArray.length) { From 9e62a8ddbb8876eb0fb926d8787626c6186df038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 8 Oct 2017 00:02:58 +0200 Subject: [PATCH 11/13] make it so default bg is used as canvas bg behind the image --- js/term/screen_renderer.js | 3 +++ sass/pages/_term.scss | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/js/term/screen_renderer.js b/js/term/screen_renderer.js index 66986f5..0a174bd 100644 --- a/js/term/screen_renderer.js +++ b/js/term/screen_renderer.js @@ -92,6 +92,9 @@ module.exports = class ScreenRenderer { this.defaultFgNum = fg this.defaultBgNum = bg this.scheduleDraw('default-colors') + + // full bg with default color (goes behind the image) + this.screen.canvas.style.backgroundColor = this.getColor(bg) } } diff --git a/sass/pages/_term.scss b/sass/pages/_term.scss index 3b82cb5..61e68f9 100644 --- a/sass/pages/_term.scss +++ b/sass/pages/_term.scss @@ -25,6 +25,12 @@ body.term { cursor: default; + canvas { + background-repeat: no-repeat; + background-position: center center; + background-size: contain; + } + canvas.selectable { cursor: text; } From 7322035fd752da55c559ed559ef9ae748dcdcbef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 8 Oct 2017 00:18:03 +0200 Subject: [PATCH 12/13] add form field for bg image url default value --- lang/cs.php | 1 + lang/en.php | 1 + pages/cfg_term.php | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lang/cs.php b/lang/cs.php index 31c21aa..9e3945a 100644 --- a/lang/cs.php +++ b/lang/cs.php @@ -80,6 +80,7 @@ return [ 'term.colors_preview' => '', 'term.debugbar' => 'Rozšířené ladění', 'term.ascii_debug' => 'Ladění vstupních dat', + 'term.backdrop' => 'URL obrázku na pozadí', 'cursor.block_blink' => 'Blok, blikající', 'cursor.block_steady' => 'Blok, stálý', diff --git a/lang/en.php b/lang/en.php index ad6bfb7..c200871 100644 --- a/lang/en.php +++ b/lang/en.php @@ -79,6 +79,7 @@ return [ 'term.colors_preview' => '', 'term.debugbar' => 'Debug internal state', 'term.ascii_debug' => 'Display control codes', + 'term.backdrop' => 'Background image URL', 'cursor.block_blink' => 'Block, blinking', 'cursor.block_steady' => 'Block, steady', diff --git a/pages/cfg_term.php b/pages/cfg_term.php index 2f90bae..ad2bc8b 100644 --- a/pages/cfg_term.php +++ b/pages/cfg_term.php @@ -172,6 +172,11 @@ +

    + + +
    +
    @@ -282,7 +287,6 @@
    -
    From bd933657f453586cd837c84b410d081f2fd958ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 8 Oct 2017 00:53:09 +0200 Subject: [PATCH 13/13] updated help --- lang/cs.php | 2 +- pages/help/cmd_system.php | 41 ++++++++++++++++++++++++++++----------- pages/help/sgr_colors.php | 4 ++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lang/cs.php b/lang/cs.php index 9e3945a..fb10e7e 100644 --- a/lang/cs.php +++ b/lang/cs.php @@ -4,7 +4,7 @@ return [ 'menu.cfg_wifi' => 'Nastavení WiFi', 'menu.cfg_network' => 'Nastavení sítě', 'menu.cfg_term' => 'Nastavení terminalu', - 'menu.about' => 'About', + 'menu.about' => 'O programu', 'menu.help' => 'Nápověda', 'menu.term' => 'Zpět k terminálu', 'menu.cfg_system' => 'Nastavení systému', diff --git a/pages/help/cmd_system.php b/pages/help/cmd_system.php index 28989d3..796082f 100644 --- a/pages/help/cmd_system.php +++ b/pages/help/cmd_system.php @@ -11,11 +11,28 @@ + + + + + + + + @@ -29,14 +46,6 @@ Can be used to check if the terminal has booted up and is ready to receive commands. - - - - + + + + diff --git a/pages/help/sgr_colors.php b/pages/help/sgr_colors.php index b504c7c..2252239 100644 --- a/pages/help/sgr_colors.php +++ b/pages/help/sgr_colors.php @@ -16,6 +16,10 @@ can be selected in Terminal Settings.

    +

    + Background image can be set using `\e]70;url\a` (see section System Functions). +

    +

    Foreground colors

    CodeMeaning
    _CAN_ (24) + This ASCII code is sent by ESPTerm when it becomes ready to receive commands. + When this code is received on the UART, it means ESPTerm has restarted and is ready. + Use this to detect spontaneous restarts which require a full screen repaint. + As a control character sent to ESPTerm, CAN aborts any currently received commands + and clears the parser. +
    _ENQ_ (5) + ESPTerm responds to this control characters with an "answerback message". + This message contains the curretn version, unique ID, and the IP address if in Client mode. +
    `\ec` Clear screen, reset attributes and cursor. This command also restores the default - screen size, title, button labels and messages. + screen size, title, button labels and messages and the background URL.
    _CAN_ (24) - This ASCII code is not a command, but is sent by ESPTerm when it becomes ready to receive commands. - When this code is received on the UART, it means ESPTerm has restarted and is ready. Use this to detect - spontaneous restarts which require a full screen repaint. -
    `\e[n q` @@ -50,6 +59,16 @@ `\e]0;t\a` Set screen title to _t_ (this is a standard OSC command)
    `\e]70;u\a` + Set background image to URL _u_ (including protocol) + that can be resolved by the user's browser. The image will be scaled + to fit the screen, preserving aspect ratio. A certain border must be added + to account for the screen margins. Use empty string to disable the image feature. + Note that this *won't work for users connected to the built-in AP*. +
    @@ -68,8 +87,8 @@ - Set message for button 1-5 (code 91-95) to _m_ - e.g.`\e]94;*\a` - sets the 3rd button to send "*" when pressed. The message can be up to + Set message for button 1-5 (code 91-95) to _m_ - e.g.`\e]94;+\a` + sets the 3rd button to send "+" when pressed. The message can be up to 10 bytes long.