unicode detect. docs. device attr. focus/blur. smacs checks.
This commit is contained in:
parent
8aa718c280
commit
ccf3794be2
|
@ -194,6 +194,9 @@ The screen on which every other node renders.
|
|||
- **keypress** - received on key events.
|
||||
- **element [name]** - global events received for all elements.
|
||||
- **key [name]** - received on key event for [name].
|
||||
- **focus, blur** - when the terminal window focuses/blurs. requires a terminal
|
||||
supporting the focus protocol and focus needs to be passed to
|
||||
program.enableMouse().
|
||||
|
||||
##### Methods:
|
||||
|
||||
|
|
142
lib/program.js
142
lib/program.js
|
@ -50,6 +50,8 @@ function Program(options) {
|
|||
|
||||
this.terminal = options.terminal || process.env.TERM || 'xterm';
|
||||
|
||||
this.unicode = this.detectUnicode();
|
||||
|
||||
// if (!Program.global) {
|
||||
// Program._write = process.stdout.write;
|
||||
// process.stdout.write = function() {};
|
||||
|
@ -499,6 +501,110 @@ Program.prototype._bindResponse = function(s) {
|
|||
}
|
||||
}
|
||||
|
||||
// CSI P s c
|
||||
// Send Device Attributes (Primary DA).
|
||||
// CSI > P s c
|
||||
// Send Device Attributes (Secondary DA).
|
||||
if (parts = /^\x1b\[(\?|>)(\d*(?:;\d*)*)c/.exec(s)) {
|
||||
var primary = parts[1] === '?'
|
||||
, parts = parts[2].split(';').map(function(ch) { return +ch || 0; })
|
||||
, out = {};
|
||||
|
||||
if (primary) {
|
||||
out.type = 'primary-attribute';
|
||||
// VT100-style params:
|
||||
if (parts[0] === 1 && parts[2] === 2) {
|
||||
out.term = 'vt100';
|
||||
out.advancedVideo = true;
|
||||
} else if (parts[0] === 1 && parts[2] === 0) {
|
||||
out.term = 'vt101';
|
||||
} else if (parts[0] === 6) {
|
||||
out.term = 'vt102';
|
||||
} else if (parts[0] === 60
|
||||
&& parts[1] === 1 && parts[2] === 2
|
||||
&& parts[3] === 6 && parts[4] === 8
|
||||
&& parts[5] === 9 && parts[6] === 15) {
|
||||
out.term = 'vt220';
|
||||
} else {
|
||||
// VT200-style params:
|
||||
parts.forEach(function(attr) {
|
||||
switch (attr) {
|
||||
case 1:
|
||||
out.132cols = true;
|
||||
break;
|
||||
case 2:
|
||||
out.printer = true;
|
||||
break;
|
||||
case 6:
|
||||
out.selectiveErase = true;
|
||||
break;
|
||||
case 8:
|
||||
out.userDefinedKeys = true;
|
||||
break;
|
||||
case 9:
|
||||
out.nationalReplacementCharsets = true;
|
||||
break;
|
||||
case 15:
|
||||
out.technicalCharacters = true;
|
||||
break;
|
||||
case 18:
|
||||
out.userWindows = true;
|
||||
break;
|
||||
case 21:
|
||||
out.horizontalScrolling = true;
|
||||
break;
|
||||
case 22:
|
||||
out.ansiColor = true;
|
||||
break;
|
||||
case 29:
|
||||
out.ansiTextLocator = true;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
out.type = 'secondary-attribute';
|
||||
switch (parts[0]) {
|
||||
case 0:
|
||||
out.term = 'vt100';
|
||||
break;
|
||||
case 1:
|
||||
out.term = 'vt220';
|
||||
break;
|
||||
case 2:
|
||||
out.term = 'vt240';
|
||||
break;
|
||||
case 18:
|
||||
out.term = 'vt330';
|
||||
break;
|
||||
case 19:
|
||||
out.term = 'vt340';
|
||||
break;
|
||||
case 24:
|
||||
out.term = 'vt320';
|
||||
break;
|
||||
case 41:
|
||||
out.term = 'vt420';
|
||||
break;
|
||||
case 61:
|
||||
out.term = 'vt510';
|
||||
break;
|
||||
case 64:
|
||||
out.term = 'vt520';
|
||||
break;
|
||||
case 65:
|
||||
out.term = 'vt525';
|
||||
break;
|
||||
}
|
||||
out.firmwareVersion = parts[1];
|
||||
out.romCartridgeRegistrationNumber = parts[2];
|
||||
}
|
||||
|
||||
return this.emit('response', {
|
||||
deviceAttributes: out
|
||||
});
|
||||
}
|
||||
|
||||
// CSI Ps n Device Status Report (DSR).
|
||||
// Ps = 5 -> Status Report. Result (``OK'') is
|
||||
// CSI 0 n
|
||||
|
@ -673,6 +779,42 @@ Program.prototype._bindResponse = function(s) {
|
|||
}
|
||||
};
|
||||
|
||||
// Not as foolproof as I'd like it to be.
|
||||
Program.prototype.detectUnicode = function() {
|
||||
var LANG = process.env.LANG
|
||||
+ ':' + process.env.LANGUAGE
|
||||
+ ':' + process.env.LC_ALL
|
||||
+ ':' + process.env.LC_CTYPE;
|
||||
|
||||
return /utf-?8/i.test(LANG);
|
||||
};
|
||||
|
||||
// Could do something goofy like this:
|
||||
Program.prototype.detectUnicode_ = function(callback) {
|
||||
var out = String.fromCharCode((0x1b << 8) | '['.charCodeAt(0)) + 'c'
|
||||
, done;
|
||||
|
||||
this.once('response', function(data) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
if (data.deviceAttributes) {
|
||||
return callback(null, false);
|
||||
}
|
||||
});
|
||||
|
||||
this.write(out);
|
||||
|
||||
this.cub(2);
|
||||
this.write(' ');
|
||||
this.cub(2);
|
||||
|
||||
setTimeout(function() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
return callback(null, true);
|
||||
}, 100);
|
||||
};
|
||||
|
||||
Program.prototype.receive = function(text, callback) {
|
||||
var listeners = (this._events && this._events['keypress']) || []
|
||||
, bak = listeners.slice()
|
||||
|
|
|
@ -306,6 +306,14 @@ function Screen(options) {
|
|||
self._resizeTimer = setTimeout(resize, time);
|
||||
});
|
||||
|
||||
this.program.on('focus', function() {
|
||||
self.emit('focus');
|
||||
});
|
||||
|
||||
this.program.on('blur', function() {
|
||||
self.emit('blur');
|
||||
});
|
||||
|
||||
this.program.alternateBuffer();
|
||||
this.program.hideCursor();
|
||||
|
||||
|
@ -758,8 +766,13 @@ Screen.prototype.draw = function(start, end) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Figure out a way to detect utf8 terminals.
|
||||
if (this.tput && this.tput.strings.enter_alt_charset_mode && SCLD[ch]) {
|
||||
if (!this.program.unicode && this.tput
|
||||
&& this.tput.strings.enter_alt_charset_mode && SCLD[ch]
|
||||
&& this.tput.strings.enter_alt_charset_mode !== '\x1b[11m') {
|
||||
// TODO: Possibly do not check for unicode above.
|
||||
// For some reason TERM=linux has smacs/rmacs, but it maps to `^[[11m`
|
||||
// and it does not switch to the DEC SCLD character set. What the hell?
|
||||
// xterm: \x1b(0, screen: \x0e
|
||||
ch = this.tput.smacs() + SCLD[ch] + this.tput.rmacs();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue