offscale default fg bg support, utf8 data encoding

box-drawing
Ondřej Hruška 7 years ago
parent c744755679
commit 8138fc0bd7
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. 34
      pages/term.php

@ -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(() => {

@ -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)

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

@ -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]) {

@ -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

@ -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 () {

@ -70,20 +70,22 @@
</nav>
<script>
try {
window.noAutoShow = true;
termInit({
labels: '%j:labels_seq%',
theme: +'%theme%',
allFn: !!+'%want_all_fn%',
});
} catch(e) {
console.error(e);
<?php if (!DEBUG): ?>
console.error("Fail, reloading in 3s…");
setTimeout(function() {
location.reload(true);
}, 3000);
<?php endif; ?>
}
try {
window.noAutoShow = true;
termInit({
labels: '%j:labels_seq%',
theme: +'%theme%',
defaultFg: +'%default_fg%',
defaultBg: +'%default_bg%',
allFn: !!+'%want_all_fn%',
});
} catch (e) {
console.error(e);
<?php if (!DEBUG): ?>
console.error("Fail, reloading in 3s…");
setTimeout(function () {
location.reload(true);
}, 3000);
<?php endif; ?>
}
</script>

Loading…
Cancel
Save