diff --git a/static/js/terminal/lib/colors.js b/static/js/terminal/lib/colors.js index d5f7c74..2fdb583 100644 --- a/static/js/terminal/lib/colors.js +++ b/static/js/terminal/lib/colors.js @@ -48,6 +48,21 @@ module.exports = function (Terminal){ return colors; })(); + Terminal.vcolors = (function (){ + var color; + var i = 0; + var out = []; + var colors = Terminal.colors; + + for (; i < 256; i++) { + color = parseInt(colors[i].substring(1), 16); + + out.push([(color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff]); + } + + return out; + })(); + // Default BG/FG Terminal.defaultColors = { bgColor: '#000000', diff --git a/static/js/terminal/lib/csi/charAttributes.js b/static/js/terminal/lib/csi/charAttributes.js index 34cabd7..3da35ef 100644 --- a/static/js/terminal/lib/csi/charAttributes.js +++ b/static/js/terminal/lib/csi/charAttributes.js @@ -5,144 +5,232 @@ 'use strict'; module.exports = function (Terminal){ - // CSI Pm m Character Attributes (SGR). - // Ps = 0 -> Normal (default). - // Ps = 1 -> Bold. - // Ps = 4 -> Underlined. - // Ps = 5 -> Blink (appears as Bold). - // Ps = 7 -> Inverse. - // Ps = 8 -> Invisible, i.e., hidden (VT300). - // Ps = 2 2 -> Normal (neither bold nor faint). - // Ps = 2 4 -> Not underlined. - // Ps = 2 5 -> Steady (not blinking). - // Ps = 2 7 -> Positive (not inverse). - // Ps = 2 8 -> Visible, i.e., not hidden (VT300). - // Ps = 3 0 -> Set foreground color to Black. - // Ps = 3 1 -> Set foreground color to Red. - // Ps = 3 2 -> Set foreground color to Green. - // Ps = 3 3 -> Set foreground color to Yellow. - // Ps = 3 4 -> Set foreground color to Blue. - // Ps = 3 5 -> Set foreground color to Magenta. - // Ps = 3 6 -> Set foreground color to Cyan. - // Ps = 3 7 -> Set foreground color to White. - // Ps = 3 9 -> Set foreground color to default (original). - // Ps = 4 0 -> Set background color to Black. - // Ps = 4 1 -> Set background color to Red. - // Ps = 4 2 -> Set background color to Green. - // Ps = 4 3 -> Set background color to Yellow. - // Ps = 4 4 -> Set background color to Blue. - // Ps = 4 5 -> Set background color to Magenta. - // Ps = 4 6 -> Set background color to Cyan. - // Ps = 4 7 -> Set background color to White. - // Ps = 4 9 -> Set background color to default (original). + function matchColor(r1, g1, b1){ + var hash = (r1 << 16) | (g1 << 8) | b1; - // If 16-color support is compiled, the following apply. Assume - // that xterm's resources are set so that the ISO color codes are - // the first 8 of a set of 16. Then the aixterm colors are the - // bright versions of the ISO colors: - // Ps = 9 0 -> Set foreground color to Black. - // Ps = 9 1 -> Set foreground color to Red. - // Ps = 9 2 -> Set foreground color to Green. - // Ps = 9 3 -> Set foreground color to Yellow. - // Ps = 9 4 -> Set foreground color to Blue. - // Ps = 9 5 -> Set foreground color to Magenta. - // Ps = 9 6 -> Set foreground color to Cyan. - // Ps = 9 7 -> Set foreground color to White. - // Ps = 1 0 0 -> Set background color to Black. - // Ps = 1 0 1 -> Set background color to Red. - // Ps = 1 0 2 -> Set background color to Green. - // Ps = 1 0 3 -> Set background color to Yellow. - // Ps = 1 0 4 -> Set background color to Blue. - // Ps = 1 0 5 -> Set background color to Magenta. - // Ps = 1 0 6 -> Set background color to Cyan. - // Ps = 1 0 7 -> Set background color to White. + if (matchColor._cache.hasOwnProperty(hash + '')) { + return matchColor._cache[hash]; + } - // If xterm is compiled with the 16-color support disabled, it - // supports the following, from rxvt: - // Ps = 1 0 0 -> Set foreground and background color to - // default. + var i = 0; + var li = -1; + var ldiff = Infinity; + var c, r2, g2, b2, diff; - // If 88- or 256-color support is compiled, the following apply. - // Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second - // Ps. - // Ps = 4 8 ; 5 ; Ps -> Set background color to the second - // Ps. + for (; i < Terminal.vcolors.length; i++) { + c = Terminal.vcolors[i]; + r2 = c[0]; + g2 = c[1]; + b2 = c[2]; + + diff = matchColor.distance(r1, g1, b1, r2, g2, b2); + + if (diff === 0) { + li = i; + break; + } + + if (diff < ldiff) { + ldiff = diff; + li = i; + } + } + + return matchColor._cache[hash] = li; + } + + matchColor._cache = {}; + + // http://stackoverflow.com/questions/1633828 + matchColor.distance = function (r1, g1, b1, r2, g2, b2){ + return Math.pow(30 * (r1 - r2), 2) + + Math.pow(59 * (g1 - g2), 2) + + Math.pow(11 * (b1 - b2), 2); + }; + + // CSI Pm m Character Attributes (SGR). + // Ps = 0 -> Normal (default). + // Ps = 1 -> Bold. + // Ps = 4 -> Underlined. + // Ps = 5 -> Blink (appears as Bold). + // Ps = 7 -> Inverse. + // Ps = 8 -> Invisible, i.e., hidden (VT300). + // Ps = 2 2 -> Normal (neither bold nor faint). + // Ps = 2 4 -> Not underlined. + // Ps = 2 5 -> Steady (not blinking). + // Ps = 2 7 -> Positive (not inverse). + // Ps = 2 8 -> Visible, i.e., not hidden (VT300). + // Ps = 3 0 -> Set foreground color to Black. + // Ps = 3 1 -> Set foreground color to Red. + // Ps = 3 2 -> Set foreground color to Green. + // Ps = 3 3 -> Set foreground color to Yellow. + // Ps = 3 4 -> Set foreground color to Blue. + // Ps = 3 5 -> Set foreground color to Magenta. + // Ps = 3 6 -> Set foreground color to Cyan. + // Ps = 3 7 -> Set foreground color to White. + // Ps = 3 9 -> Set foreground color to default (original). + // Ps = 4 0 -> Set background color to Black. + // Ps = 4 1 -> Set background color to Red. + // Ps = 4 2 -> Set background color to Green. + // Ps = 4 3 -> Set background color to Yellow. + // Ps = 4 4 -> Set background color to Blue. + // Ps = 4 5 -> Set background color to Magenta. + // Ps = 4 6 -> Set background color to Cyan. + // Ps = 4 7 -> Set background color to White. + // Ps = 4 9 -> Set background color to default (original). + + // If 16-color support is compiled, the following apply. Assume + // that xterm's resources are set so that the ISO color codes are + // the first 8 of a set of 16. Then the aixterm colors are the + // bright versions of the ISO colors: + // Ps = 9 0 -> Set foreground color to Black. + // Ps = 9 1 -> Set foreground color to Red. + // Ps = 9 2 -> Set foreground color to Green. + // Ps = 9 3 -> Set foreground color to Yellow. + // Ps = 9 4 -> Set foreground color to Blue. + // Ps = 9 5 -> Set foreground color to Magenta. + // Ps = 9 6 -> Set foreground color to Cyan. + // Ps = 9 7 -> Set foreground color to White. + // Ps = 1 0 0 -> Set background color to Black. + // Ps = 1 0 1 -> Set background color to Red. + // Ps = 1 0 2 -> Set background color to Green. + // Ps = 1 0 3 -> Set background color to Yellow. + // Ps = 1 0 4 -> Set background color to Blue. + // Ps = 1 0 5 -> Set background color to Magenta. + // Ps = 1 0 6 -> Set background color to Cyan. + // Ps = 1 0 7 -> Set background color to White. + + // If xterm is compiled with the 16-color support disabled, it + // supports the following, from rxvt: + // Ps = 1 0 0 -> Set foreground and background color to + // default. + + // If 88- or 256-color support is compiled, the following apply. + // Ps = 3 8 ; 5 ; Ps -> Set foreground color to the second + // Ps. + // Ps = 4 8 ; 5 ; Ps -> Set background color to the second + // Ps. Terminal.prototype.charAttributes = function (params){ - var l = params.length, - i = 0, - bg, fg, p; + // Optimize a single SGR0. + if (params.length === 1 && params[0] === 0) { + this.curAttr = this.defAttr; + return; + } + + var p; + var i = 0; + var l = params.length; + var flags = this.curAttr >> 18; + var fg = (this.curAttr >> 9) & 0x1ff; + var bg = this.curAttr & 0x1ff; for (; i < l; i++) { p = params[i]; + if (p >= 30 && p <= 37) { // fg color 8 - this.curAttr = (this.curAttr & ~(0x1ff << 9)) | ((p - 30) << 9); + fg = p - 30; } else if (p >= 40 && p <= 47) { // bg color 8 - this.curAttr = (this.curAttr & ~0x1ff) | (p - 40); + bg = p - 40; } else if (p >= 90 && p <= 97) { // fg color 16 p += 8; - this.curAttr = (this.curAttr & ~(0x1ff << 9)) | ((p - 90) << 9); + fg = p - 90; } else if (p >= 100 && p <= 107) { // bg color 16 p += 8; - this.curAttr = (this.curAttr & ~0x1ff) | (p - 100); + bg = p - 100; } else if (p === 0) { // default - this.curAttr = this.defAttr; + flags = this.defAttr >> 18; + fg = (this.defAttr >> 9) & 0x1ff; + bg = this.defAttr & 0x1ff; + // flags = 0; + // fg = 0x1ff; + // bg = 0x1ff; } else if (p === 1) { // bold text - this.curAttr = this.curAttr | (1 << 18); + flags |= 1; } else if (p === 4) { // underlined text - this.curAttr = this.curAttr | (2 << 18); - } else if (p === 7 || p === 27) { + flags |= 2; + } else if (p === 5) { + // blink + flags |= 4; + } else if (p === 7) { // inverse and positive // test with: echo -e '\e[31m\e[42mhello\e[7mworld\e[27mhi\e[m' - if (p === 7) { - if ((this.curAttr >> 18) & 4) continue; - this.curAttr = this.curAttr | (4 << 18); - } else if (p === 27) { - if (~(this.curAttr >> 18) & 4) continue; - this.curAttr = this.curAttr & ~(4 << 18); - } - - bg = this.curAttr & 0x1ff; - fg = (this.curAttr >> 9) & 0x1ff; - - this.curAttr = (this.curAttr & ~0x3ffff) | ((bg << 9) | fg); + flags |= 8; + } else if (p === 8) { + // invisible + flags |= 16; } else if (p === 22) { // not bold - this.curAttr = this.curAttr & ~(1 << 18); + flags &= ~1; } else if (p === 24) { // not underlined - this.curAttr = this.curAttr & ~(2 << 18); + flags &= ~2; + } else if (p === 25) { + // not blink + flags &= ~4; + } else if (p === 27) { + // not inverse + flags &= ~8; + } else if (p === 28) { + // not invisible + flags &= ~16; } else if (p === 39) { // reset fg - this.curAttr = this.curAttr & ~(0x1ff << 9); - this.curAttr = this.curAttr | (((this.defAttr >> 9) & 0x1ff) << 9); + fg = (this.defAttr >> 9) & 0x1ff; } else if (p === 49) { // reset bg - this.curAttr = this.curAttr & ~0x1ff; - this.curAttr = this.curAttr | (this.defAttr & 0x1ff); + bg = this.defAttr & 0x1ff; } else if (p === 38) { // fg color 256 - if (params[i + 1] !== 5) continue; - i += 2; - p = params[i] & 0xff; - // convert 88 colors to 256 - // if (this.is('rxvt-unicode') && p < 88) p = p * 2.9090 | 0; - this.curAttr = (this.curAttr & ~(0x1ff << 9)) | (p << 9); + if (params[i + 1] === 2) { + i += 2; + + fg = matchColor( + params[i] & 0xff, + params[i + 1] & 0xff, + params[i + 2] & 0xff); + + if (fg === -1) fg = 0x1ff; + + i += 2; + } else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + fg = p; + } } else if (p === 48) { // bg color 256 - if (params[i + 1] !== 5) continue; - i += 2; - p = params[i] & 0xff; - // convert 88 colors to 256 - // if (this.is('rxvt-unicode') && p < 88) p = p * 2.9090 | 0; - this.curAttr = (this.curAttr & ~0x1ff) | p; + if (params[i + 1] === 2) { + i += 2; + + bg = matchColor( + params[i] & 0xff, + params[i + 1] & 0xff, + params[i + 2] & 0xff); + + if (bg === -1) bg = 0x1ff; + + i += 2; + } else if (params[i + 1] === 5) { + i += 2; + p = params[i] & 0xff; + bg = p; + } + } else if (p === 100) { + // reset fg/bg + fg = (this.defAttr >> 9) & 0x1ff; + bg = this.defAttr & 0x1ff; + } else { + this.error('Unknown SGR attribute: %d.', p); } } + + this.curAttr = (flags << 18) | (fg << 9) | bg; }; }; diff --git a/static/js/terminal/lib/csi/softReset.js b/static/js/terminal/lib/csi/softReset.js index de29633..4c70573 100644 --- a/static/js/terminal/lib/csi/softReset.js +++ b/static/js/terminal/lib/csi/softReset.js @@ -11,14 +11,15 @@ module.exports = function (Terminal){ this.cursorHidden = false; this.insertMode = false; this.originMode = false; - this.wraparoundMode = false; // autowrap - this.applicationKeypad = false; // ? + // autowrap + this.wraparoundMode = false; + this.applicationKeypad = false; this.scrollTop = 0; this.scrollBottom = this.rows - 1; this.curAttr = this.defAttr; - this.x = this.y = 0; // ? + this.x = this.y = 0; this.charset = null; - this.glevel = 0; // ?? - this.charsets = [null]; // ?? + this.glevel = 0; + this.charsets = [null]; }; };