From b9d374affa5333786b9665b94e6196e6d1ee5230 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 3 Jan 2017 11:55:54 -0800 Subject: [PATCH] Add XON/XOFF and eparate write from processing Part of #425 --- demo/app.js | 3 +++ src/xterm.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/demo/app.js b/demo/app.js index a4122ace..b6bde384 100644 --- a/demo/app.js +++ b/demo/app.js @@ -60,6 +60,9 @@ app.ws('/terminals/:pid', function (ws, req) { term.on('data', function(data) { try { + // XOFF - stop pty pipe + // XON will be triggered by emulator before processing data chunk + term.write('\x13'); ws.send(data); } catch (ex) { // The WebSocket is not open, ignore diff --git a/src/xterm.js b/src/xterm.js index cd304186..a29412e6 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -196,6 +196,11 @@ function Terminal(options) { this.prefix = ''; this.postfix = ''; + // user input states + this.writeBuffer = []; + this.writeInProgress = false; + this.user_xoff = false; // user pressed XOFF + // leftover surrogate high from previous write invocation this.surrogate_high = ''; @@ -1341,8 +1346,27 @@ Terminal.prototype.scrollToBottom = function() { * @param {string} text The text to write to the terminal. */ Terminal.prototype.write = function(data) { + this.writeBuffer.push(data); + if (!this.writeInProgress) { + // Kick off a write which will write all data in sequence recursively + this.writeInProgress = true; + // Kick off an async innerWrite so more writes can come in while processing data + setTimeout(() => this.innerWrite(this.writeBuffer.shift())); + } +} + +Terminal.prototype.innerWrite = function(data) { var l = data.length, i = 0, j, cs, ch, code, low, ch_width, row; + // TODO: Need to have another buffer where data is held where write can grab lines from + // When this hits a certain threshold it should send this.write('\x13') + + // XON - about to process data, thus we can get more + // dont lift XOFF if user pressed it + if (!this.user_xoff) { + this.send('\x11'); + } + this.refreshStart = this.y; this.refreshEnd = this.y; @@ -2380,6 +2404,12 @@ Terminal.prototype.write = function(data) { this.updateRange(this.y); this.queueRefresh(this.refreshStart, this.refreshEnd); + + if (this.writeBuffer.length > 0) { + this.innerWrite(this.writeBuffer.shift()); + } else { + this.writeInProgress = false; + } }; /** @@ -2423,6 +2453,12 @@ Terminal.prototype.keyDown = function(ev) { var self = this; var result = this.evaluateKeyEscapeSequence(ev); + if (result.key === '\x13') { // XOFF + this.user_xoff = true; + } else if (result.key === '\x11') { // XON + this.user_xoff = false; + } + if (result.scrollDisp) { this.scrollDisp(result.scrollDisp); return this.cancel(ev, true); @@ -2728,6 +2764,7 @@ Terminal.prototype.evaluateKeyEscapeSequence = function(ev) { } break; } + return result; };