Merge branch 'offscale-bg-and-other-monstrosities' into work

box-drawing
Ondřej Hruška 7 years ago
commit 52bde8c266
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      js/term/demo.js
  2. 6
      js/term/index.js
  3. 1
      js/term/screen.js
  4. 59
      js/term/screen_parser.js
  5. 24
      js/term/screen_renderer.js
  6. 18
      js/term/themes.js
  7. 2
      pages/term.php

@ -294,7 +294,7 @@ class ScrollingTerminal {
scheduleLoad () { scheduleLoad () {
clearTimeout(this._scheduledLoad) clearTimeout(this._scheduledLoad)
if (this._lastLoad < Date.now() - TERM_MIN_DRAW_DELAY) { 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 this.theme = -1 // prevent useless theme setting next time
} else { } else {
this._scheduledLoad = setTimeout(() => { this._scheduledLoad = setTimeout(() => {

@ -8,7 +8,7 @@ const initSoftKeyboard = require('./soft_keyboard')
const attachDebugScreen = require('./debug_screen') const attachDebugScreen = require('./debug_screen')
/** Init the terminal sub-module - called from HTML */ /** Init the terminal sub-module - called from HTML */
module.exports = function ({ labels, theme, allFn }) { module.exports = function (opts) {
const screen = new TermScreen() const screen = new TermScreen()
const conn = new TermConnection(screen) const conn = new TermConnection(screen)
const input = TermInput(conn, 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.on('ping-success', () => { screen.window.statusScreen = { title: 'Re-connecting', loading: true } })
conn.init() conn.init()
input.init({ allFn }) input.init(opts)
termUpload.init() termUpload.init()
Notify.init() Notify.init()
@ -46,7 +46,7 @@ module.exports = function ({ labels, theme, allFn }) {
} }
qs('#screen').appendChild(screen.canvas) 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) initSoftKeyboard(screen, input)
if (attachDebugScreen) attachDebugScreen(screen) if (attachDebugScreen) attachDebugScreen(screen)

@ -99,6 +99,7 @@ module.exports = class TermScreen extends EventEmitter {
this.bracketedPaste = false this.bracketedPaste = false
this.blinkingCellCount = 0 this.blinkingCellCount = 0
this.reverseVideo = false
this.screen = [] this.screen = []
this.screenFG = [] this.screenFG = []

@ -1,6 +1,6 @@
const $ = require('../lib/chibi') const $ = require('../lib/chibi')
const { qs, parse2B, parse3B } = require('../utils') const { qs } = require('../utils')
const { themes } = require('./themes') const { themes, defThemes } = require('./themes')
// constants for decoding the update blob // constants for decoding the update blob
const SEQ_REPEAT = 2 const SEQ_REPEAT = 2
@ -23,6 +23,8 @@ module.exports = class ScreenParser {
loadContent (str) { loadContent (str) {
// current index // current index
let i = 0 let i = 0
let strArray = Array.from ? Array.from(str) : str.split('')
// Uncomment to capture screen content for the demo page // Uncomment to capture screen content for the demo page
// console.log(JSON.stringify(`S${str}`)) // console.log(JSON.stringify(`S${str}`))
@ -33,16 +35,17 @@ module.exports = class ScreenParser {
} }
// window size // window size
const newHeight = parse2B(str, i) const newHeight = strArray[i++].codePointAt(0) - 1
const newWidth = parse2B(str, i + 2) const newWidth = strArray[i++].codePointAt(0) - 1
const resized = (this.screen.window.height !== newHeight) || (this.screen.window.width !== newWidth) const resized = (this.screen.window.height !== newHeight) || (this.screen.window.width !== newWidth)
this.screen.window.height = newHeight this.screen.window.height = newHeight
this.screen.window.width = newWidth this.screen.window.width = newWidth
i += 4
// cursor position // cursor position
let [cursorY, cursorX] = [parse2B(str, i), parse2B(str, i + 2)] let [cursorY, cursorX] = [
i += 4 strArray[i++].codePointAt(0) - 1,
strArray[i++].codePointAt(0) - 1
]
let cursorMoved = (cursorX !== this.screen.cursor.x || cursorY !== this.screen.cursor.y) let cursorMoved = (cursorX !== this.screen.cursor.x || cursorY !== this.screen.cursor.y)
this.screen.cursor.x = cursorX this.screen.cursor.x = cursorX
this.screen.cursor.y = cursorY this.screen.cursor.y = cursorY
@ -53,8 +56,7 @@ module.exports = class ScreenParser {
} }
// attributes // attributes
let attributes = parse3B(str, i) let attributes = strArray[i++].codePointAt(0) - 1
i += 3
this.screen.cursor.visible = !!(attributes & 1) this.screen.cursor.visible = !!(attributes & 1)
this.screen.cursor.hanging = !!(attributes & (1 << 1)) this.screen.cursor.hanging = !!(attributes & (1 << 1))
@ -105,6 +107,7 @@ module.exports = class ScreenParser {
$('#action-buttons').toggleClass('hidden', !showButtons) $('#action-buttons').toggleClass('hidden', !showButtons)
this.screen.bracketedPaste = !!(attributes & (1 << 13)) this.screen.bracketedPaste = !!(attributes & (1 << 13))
this.screen.reverseVideo = !!(attributes & (1 << 14))
// content // content
let fg = 7 let fg = 7
@ -120,11 +123,9 @@ module.exports = class ScreenParser {
this.screen.screen = new Array(screenLength).fill(' ') this.screen.screen = new Array(screenLength).fill(' ')
this.screen.screenFG = new Array(screenLength).fill(' ') this.screen.screenFG = new Array(screenLength).fill(' ')
this.screen.screenBG = 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_LINE_ATTR = 0xC8
const MASK_BLINK = 1 << 4 const MASK_BLINK = 1 << 4
@ -157,8 +158,7 @@ module.exports = class ScreenParser {
let data let data
switch (charCode) { switch (charCode) {
case SEQ_REPEAT: case SEQ_REPEAT:
let count = parse2B(strArray[i] + strArray[i + 1]) let count = strArray[i++].codePointAt(0) - 1
i += 2
for (let j = 0; j < count; j++) { for (let j = 0; j < count; j++) {
setCellContent(cell) setCellContent(cell)
if (++cell > screenLength) break if (++cell > screenLength) break
@ -166,27 +166,23 @@ module.exports = class ScreenParser {
break break
case SEQ_SET_COLORS: case SEQ_SET_COLORS:
data = parse3B(strArray[i] + strArray[i + 1] + strArray[i + 2]) data = strArray[i++].codePointAt(0) - 1
i += 3
fg = data & 0xFF fg = data & 0xFF
bg = (data >> 8) & 0xFF bg = (data >> 8) & 0xFF
break break
case SEQ_SET_ATTRS: case SEQ_SET_ATTRS:
data = parse2B(strArray[i] + strArray[i + 1]) data = strArray[i++].codePointAt(0) - 1
i += 2 attrs = data & 0xFFFF
attrs = data & 0xFF
break break
case SEQ_SET_FG: case SEQ_SET_FG:
data = parse2B(strArray[i] + strArray[i + 1]) data = strArray[i++].codePointAt(0) - 1
i += 2
fg = data & 0xFF fg = data & 0xFF
break break
case SEQ_SET_BG: case SEQ_SET_BG:
data = parse2B(strArray[i] + strArray[i + 1]) data = strArray[i++].codePointAt(0) - 1
i += 2
bg = data & 0xFF bg = data & 0xFF
break break
@ -227,12 +223,21 @@ module.exports = class ScreenParser {
/** /**
* Loads a message from the server, and optionally a theme. * Loads a message from the server, and optionally a theme.
* @param {string} str - the message * @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) 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]) { switch (str[0]) {

@ -14,7 +14,9 @@ module.exports = class ScreenRenderer {
this.screen = screen this.screen = screen
this.ctx = screen.ctx this.ctx = screen.ctx
this._palette = null this._palette = null // colors 0-15
this.defaultBgNum = 0
this.defaultFgNum = 7
// 256color lookup table // 256color lookup table
// should not be used to look up 0-15 (will return transparent) // 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. * The color palette. Should define 16 colors in an array.
* @type {number[]} * @type {string[]}
*/ */
get palette () { get palette () {
return this._palette || themes[0] return this._palette || themes[0]
} }
/** @type {number[]} */
/** @type {string[]} */
set palette (palette) { set palette (palette) {
if (this._palette !== palette) { if (this._palette !== palette) {
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 * Schedule a draw in the next millisecond
* @param {string} why - the reason why the draw occured (for debugging) * @param {string} why - the reason why the draw occured (for debugging)
@ -79,7 +89,7 @@ module.exports = class ScreenRenderer {
*/ */
getColor (i) { getColor (i) {
// return palette color if it exists // 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 // -1 for selection foreground, -2 for selection background
if (i === -1) return SELECTION_FG if (i === -1) return SELECTION_FG
@ -418,6 +428,12 @@ module.exports = class ScreenRenderer {
let bg = this.screen.screenBG[cell] | 0 let bg = this.screen.screenBG[cell] | 0
let attrs = this.screen.screenAttrs[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) { if (attrs & (1 << 4) && !this.blinkStyleOn) {
// blinking is enabled and blink style is off // blinking is enabled and blink style is off
// set text to nothing so drawCharacter doesn't draw anything // set text to nothing so drawCharacter doesn't draw anything

@ -20,7 +20,11 @@ const themes = exports.themes = [
'#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf', '#2e3436', '#cc0000', '#4e9a06', '#c4a000', '#3465a4', '#75507b', '#06989a', '#d3d7cf',
'#555753', '#ef2929', '#8ae234', '#fce94f', '#729fcf', '#ad7fa8', '#34e2e2', '#eeeeec' '#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', '#073642', '#dc322f', '#859900', '#b58900', '#268bd2', '#d33682', '#2aa198', '#eee8d5',
'#002b36', '#cb4b16', '#586e75', '#657b83', '#839496', '#6c71c4', '#93a1a1', '#fdf6e3' '#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 let colorTable256 = null
exports.buildColorTable = function () { exports.buildColorTable = function () {

@ -75,6 +75,8 @@
termInit({ termInit({
labels: '%j:labels_seq%', labels: '%j:labels_seq%',
theme: +'%theme%', theme: +'%theme%',
defaultFg: +'%default_fg%',
defaultBg: +'%default_bg%',
allFn: !!+'%want_all_fn%', allFn: !!+'%want_all_fn%',
}); });
} catch (e) { } catch (e) {

Loading…
Cancel
Save