From 8138fc0bd79d35544a181123f01a584f6cc86fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 24 Sep 2017 03:00:57 +0200 Subject: [PATCH] offscale default fg bg support, utf8 data encoding --- js/term/demo.js | 2 +- js/term/index.js | 6 ++-- js/term/screen.js | 1 + js/term/screen_parser.js | 59 +++++++++++++++++++++----------------- js/term/screen_renderer.js | 24 +++++++++++++--- js/term/themes.js | 18 +++++++++++- pages/term.php | 34 +++++++++++----------- 7 files changed, 92 insertions(+), 52 deletions(-) diff --git a/js/term/demo.js b/js/term/demo.js index e76279b..9211f80 100644 --- a/js/term/demo.js +++ b/js/term/demo.js @@ -294,7 +294,7 @@ class ScrollingTerminal { scheduleLoad () { clearTimeout(this._scheduledLoad) if (this._lastLoad < Date.now() - TERM_MIN_DRAW_DELAY) { - this.termScreen.load(this.serialize(), this.theme) + this.termScreen.load(this.serialize(), { theme: this.theme }) this.theme = -1 // prevent useless theme setting next time } else { this._scheduledLoad = setTimeout(() => { diff --git a/js/term/index.js b/js/term/index.js index 368a29f..2ccc142 100644 --- a/js/term/index.js +++ b/js/term/index.js @@ -8,7 +8,7 @@ const initSoftKeyboard = require('./soft_keyboard') const attachDebugScreen = require('./debug_screen') /** Init the terminal sub-module - called from HTML */ -module.exports = function ({ labels, theme, allFn }) { +module.exports = function (opts) { const screen = new TermScreen() const conn = new TermConnection(screen) const input = TermInput(conn, screen) @@ -36,7 +36,7 @@ module.exports = function ({ labels, theme, allFn }) { conn.on('ping-success', () => { screen.window.statusScreen = { title: 'Re-connecting', loading: true } }) conn.init() - input.init({ allFn }) + input.init(opts) termUpload.init() Notify.init() @@ -46,7 +46,7 @@ module.exports = function ({ labels, theme, allFn }) { } qs('#screen').appendChild(screen.canvas) - screen.load(labels, theme) // load labels and theme + screen.load(opts.labels, opts) // load labels and theme initSoftKeyboard(screen, input) if (attachDebugScreen) attachDebugScreen(screen) diff --git a/js/term/screen.js b/js/term/screen.js index d0bfa86..f466939 100644 --- a/js/term/screen.js +++ b/js/term/screen.js @@ -99,6 +99,7 @@ module.exports = class TermScreen extends EventEmitter { this.bracketedPaste = false this.blinkingCellCount = 0 + this.reverseVideo = false this.screen = [] this.screenFG = [] diff --git a/js/term/screen_parser.js b/js/term/screen_parser.js index 82123ab..77e7112 100644 --- a/js/term/screen_parser.js +++ b/js/term/screen_parser.js @@ -1,6 +1,6 @@ const $ = require('../lib/chibi') -const { qs, parse2B, parse3B } = require('../utils') -const { themes } = require('./themes') +const { qs } = require('../utils') +const { themes, defThemes } = require('./themes') // constants for decoding the update blob const SEQ_REPEAT = 2 @@ -23,6 +23,8 @@ module.exports = class ScreenParser { loadContent (str) { // current index let i = 0 + let strArray = Array.from ? Array.from(str) : str.split('') + // Uncomment to capture screen content for the demo page // console.log(JSON.stringify(`S${str}`)) @@ -33,16 +35,17 @@ module.exports = class ScreenParser { } // window size - const newHeight = parse2B(str, i) - const newWidth = parse2B(str, i + 2) + const newHeight = strArray[i++].codePointAt(0) - 1 + const newWidth = strArray[i++].codePointAt(0) - 1 const resized = (this.screen.window.height !== newHeight) || (this.screen.window.width !== newWidth) this.screen.window.height = newHeight this.screen.window.width = newWidth - i += 4 // cursor position - let [cursorY, cursorX] = [parse2B(str, i), parse2B(str, i + 2)] - i += 4 + let [cursorY, cursorX] = [ + strArray[i++].codePointAt(0) - 1, + strArray[i++].codePointAt(0) - 1 + ] let cursorMoved = (cursorX !== this.screen.cursor.x || cursorY !== this.screen.cursor.y) this.screen.cursor.x = cursorX this.screen.cursor.y = cursorY @@ -53,8 +56,7 @@ module.exports = class ScreenParser { } // attributes - let attributes = parse3B(str, i) - i += 3 + let attributes = strArray[i++].codePointAt(0) - 1 this.screen.cursor.visible = !!(attributes & 1) this.screen.cursor.hanging = !!(attributes & (1 << 1)) @@ -105,6 +107,7 @@ module.exports = class ScreenParser { $('#action-buttons').toggleClass('hidden', !showButtons) this.screen.bracketedPaste = !!(attributes & (1 << 13)) + this.screen.reverseVideo = !!(attributes & (1 << 14)) // content let fg = 7 @@ -120,11 +123,9 @@ module.exports = class ScreenParser { this.screen.screen = new Array(screenLength).fill(' ') this.screen.screenFG = new Array(screenLength).fill(' ') this.screen.screenBG = new Array(screenLength).fill(' ') - this.screen.screenAttrs = new Array(screenLength).fill(' ') + this.screen.screenAttrs = new Array(screenLength).fill(0) } - let strArray = Array.from ? Array.from(str) : str.split('') - const MASK_LINE_ATTR = 0xC8 const MASK_BLINK = 1 << 4 @@ -157,8 +158,7 @@ module.exports = class ScreenParser { let data switch (charCode) { case SEQ_REPEAT: - let count = parse2B(strArray[i] + strArray[i + 1]) - i += 2 + let count = strArray[i++].codePointAt(0) - 1 for (let j = 0; j < count; j++) { setCellContent(cell) if (++cell > screenLength) break @@ -166,27 +166,23 @@ module.exports = class ScreenParser { break case SEQ_SET_COLORS: - data = parse3B(strArray[i] + strArray[i + 1] + strArray[i + 2]) - i += 3 + data = strArray[i++].codePointAt(0) - 1 fg = data & 0xFF bg = (data >> 8) & 0xFF break case SEQ_SET_ATTRS: - data = parse2B(strArray[i] + strArray[i + 1]) - i += 2 - attrs = data & 0xFF + data = strArray[i++].codePointAt(0) - 1 + attrs = data & 0xFFFF break case SEQ_SET_FG: - data = parse2B(strArray[i] + strArray[i + 1]) - i += 2 + data = strArray[i++].codePointAt(0) - 1 fg = data & 0xFF break case SEQ_SET_BG: - data = parse2B(strArray[i] + strArray[i + 1]) - i += 2 + data = strArray[i++].codePointAt(0) - 1 bg = data & 0xFF break @@ -227,12 +223,21 @@ module.exports = class ScreenParser { /** * Loads a message from the server, and optionally a theme. * @param {string} str - the message - * @param {number} [theme] - the new theme index + * @param {object} [opts] - options { [int] theme, [int] defaultFg, [int] defaultBg } */ - load (str, theme = -1) { + load (str, opts = null) { const content = str.substr(1) - if (theme >= 0 && theme < themes.length) { - this.screen.renderer.palette = themes[theme] + + if (opts) { + if (typeof opts.defaultFg !== 'undefined' && typeof opts.defaultBg !== 'undefined') { + this.screen.renderer.setDefaultColors(opts.defaultFg, opts.defaultBg) + } + + if (typeof opts.theme !== 'undefined') { + if (opts.theme >= 0 && opts.theme < themes.length) { + this.screen.renderer.palette = themes[opts.theme] + } + } } switch (str[0]) { diff --git a/js/term/screen_renderer.js b/js/term/screen_renderer.js index 452afb4..1bd54ee 100644 --- a/js/term/screen_renderer.js +++ b/js/term/screen_renderer.js @@ -14,7 +14,9 @@ module.exports = class ScreenRenderer { this.screen = screen this.ctx = screen.ctx - this._palette = null + this._palette = null // colors 0-15 + this.defaultBgNum = 0 + this.defaultFgNum = 7 // 256color lookup table // should not be used to look up 0-15 (will return transparent) @@ -44,12 +46,13 @@ module.exports = class ScreenRenderer { /** * The color palette. Should define 16 colors in an array. - * @type {number[]} + * @type {string[]} */ get palette () { return this._palette || themes[0] } - /** @type {number[]} */ + + /** @type {string[]} */ set palette (palette) { if (this._palette !== palette) { this._palette = palette @@ -58,6 +61,13 @@ module.exports = class ScreenRenderer { } } + setDefaultColors (fg, bg) { + this.defaultFgNum = fg + this.defaultBgNum = bg + this.resetDrawn() + this.scheduleDraw('defaultColors') + } + /** * Schedule a draw in the next millisecond * @param {string} why - the reason why the draw occured (for debugging) @@ -79,7 +89,7 @@ module.exports = class ScreenRenderer { */ getColor (i) { // return palette color if it exists - if (this.palette[i]) return this.palette[i] + if (i < 16) return this.palette[i] // -1 for selection foreground, -2 for selection background if (i === -1) return SELECTION_FG @@ -418,6 +428,12 @@ module.exports = class ScreenRenderer { let bg = this.screen.screenBG[cell] | 0 let attrs = this.screen.screenAttrs[cell] | 0 + if (!(attrs & (1 << 8))) fg = this.defaultFgNum + if (!(attrs & (1 << 9))) bg = this.defaultBgNum + + if (attrs & (1 << 10)) [fg, bg] = [bg, fg] // swap - reversed character colors + if (this.screen.reverseVideo) [fg, bg] = [bg, fg] // swap - reversed all screen + if (attrs & (1 << 4) && !this.blinkStyleOn) { // blinking is enabled and blink style is off // set text to nothing so drawCharacter doesn't draw anything diff --git a/js/term/themes.js b/js/term/themes.js index e8323cf..ff0e6fd 100644 --- a/js/term/themes.js +++ b/js/term/themes.js @@ -20,7 +20,11 @@ const themes = exports.themes = [ '#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec' ], - [ // Solarized + [ // Solarized light + '#073642', '#dc322f', '#859900', '#b58900', '#268bd2', '#d33682', '#2aa198', '#eee8d5', + '#002b36', '#cb4b16', '#586e75', '#657b83', '#839496', '#6c71c4', '#93a1a1', '#fdf6e3' + ], + [ // Solarized dark '#073642', '#dc322f', '#859900', '#b58900', '#268bd2', '#d33682', '#2aa198', '#eee8d5', '#002b36', '#cb4b16', '#586e75', '#657b83', '#839496', '#6c71c4', '#93a1a1', '#fdf6e3' ], @@ -42,6 +46,18 @@ const themes = exports.themes = [ ] ] +exports.fgbgThemes = [ + ['#aaaaaa', '#000000'], // grey_on_black + ['#000000', '#ffffdd'], // black_on_yellow + ['#000000', '#ffffff'], // black_on_white + ['#ffffff', '#000000'], // white_on_black + ['#00ff00', '#000000'], // green_on_black + ['#e53c00', '#000000'], // orange_on_black + ['#ffffff', '#300a24'], // ambience + ['#657b83', '#fdf6e3'], // solarized_light + ['#839496', '#002b36'] // solarized_dark +] + let colorTable256 = null exports.buildColorTable = function () { diff --git a/pages/term.php b/pages/term.php index 4ae1af0..3c0ede0 100644 --- a/pages/term.php +++ b/pages/term.php @@ -70,20 +70,22 @@