diff --git a/com/html-as-texture-in-xr.js b/com/html-as-texture-in-xr.js
index abf0766..afb0e8d 100644
--- a/com/html-as-texture-in-xr.js
+++ b/com/html-as-texture-in-xr.js
@@ -21,7 +21,7 @@ if( !AFRAME.components['html-as-texture-in-xr'] ){
this.el.setAttribute("html",`html: ${this.data.domid}; cursor:#cursor; xrlayer: true`)
this.el.setAttribute("visible", AFRAME.utils.XD() == '3D' ? 'true' : 'false' )
if( this.data.faceuser ){
- this.el.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.8) )
+ this.el.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.4) )
}
},
diff --git a/com/isoterminal.js b/com/isoterminal.js
index 2e4ca41..ba31565 100644
--- a/com/isoterminal.js
+++ b/com/isoterminal.js
@@ -40,7 +40,6 @@ if( typeof AFRAME != 'undefined '){
depth: { type: 'number',"default": 0.03 },
lineHeight: { type: 'number',"default": 18 },
padding: { type: 'number',"default": 18 },
- minimized: { type: 'boolean',"default":false},
maximized: { type: 'boolean',"default":true},
muteUntilPrompt:{ type: 'boolean',"default":true}, // mute stdout until a prompt is detected in ISO
HUD: { type: 'boolean',"default":false}, // link to camera movement
@@ -97,11 +96,11 @@ if( typeof AFRAME != 'undefined '){
css: (me) => `.isoterminal{
padding: ${me.com.data.padding}px;
width:100%;
- height:100%;
+ height:90%;
position:relative;
}
.isoterminal div{
- display:block;
+ display:inline-block;
position:relative;
line-height: ${me.com.data.lineHeight}px;
}
@@ -133,6 +132,17 @@ if( typeof AFRAME != 'undefined '){
box-shadow:none;
}
+ .cursor {
+ background: #70F !important;
+ animation:fade 1000ms infinite;
+ -webkit-animation:fade 1000ms infinite;
+ }
+
+ .XR .cursor {
+ animation:none;
+ -webkit-animation:none;
+ }
+
.wb-body:has(> .isoterminal){
background: #000C;
overflow:hidden;
@@ -259,10 +269,10 @@ if( typeof AFRAME != 'undefined '){
instance.addEventListener('window.onmaximize', resize )
const focus = (showdom) => (e) => {
+ this.el.emit('focus',e.detail)
if( this.el.components.window && this.data.renderer == 'canvas'){
this.el.components.window.show( showdom )
}
- this.el.emit('focus',e.detail)
}
this.el.addEventListener('obbcollisionstarted', focus(false) )
@@ -296,17 +306,18 @@ if( typeof AFRAME != 'undefined '){
cols: this.cols,
rows: this.rows,
el_or_id: el,
- max_scroll_lines: 100,
- nodim: true
+ max_scroll_lines: this.rows,
+ nodim: true,
+ rainbow: [VT100.COLOR_MAGENTA, VT100.COLOR_CYAN ],
+ xr: AFRAME.scenes[0].renderer.xr
}
this.vt100 = new VT100( opts )
this.vt100.el = el
this.vt100.curs_set( 1, true)
- el.focus()
- this.el.addEventListener('focus', () => el.focus())
+ this.vt100.focus()
+ this.el.addEventListener('focus', () => this.vt100.focus() )
this.vt100.getch( (ch,t) => {
this.term.send( ch )
- this.vt100.curs_set( 0, true)
})
this.el.addEventListener('serial-output-byte', (e) => {
@@ -317,14 +328,6 @@ if( typeof AFRAME != 'undefined '){
this.el.addEventListener('serial-output-string', (e) => {
this.vt100.write(e.detail)
})
-
-
- //this.el.dom.querySelector('input').addEventListener('keyup', (e) => {
- // VT100.handle_onkeypress_( {charCode : e.charCode || e.keyCode, keyCode: e.keyCode}, (chars) => {
- // debugger
- // chars.map( (c) => this.term.send(str) )
- // })
- //})
},
setupBox: function(){
@@ -339,13 +342,13 @@ if( typeof AFRAME != 'undefined '){
},
calculateDimension: function(){
- if( this.data.width == -1 ) this.data.width = document.body.offsetWidth
- if( this.data.height == -1 ) this.data.height = document.body.offsetHeight
+ if( this.data.width == -1 ) this.data.width = document.body.offsetWidth;
+ if( this.data.height == -1 ) this.data.height = Math.floor( document.body.offsetHeight - 30 )
if( this.data.height > this.data.width ) this.data.height = this.data.width // mobile smartphone fix
this.data.width -= this.data.padding*2
this.data.height -= this.data.padding*2
- this.cols = Math.floor(this.data.width/this.data.lineHeight*1.9)
- this.rows = Math.floor(this.data.height*0.5/this.data.lineHeight*1.7) // keep extra height for mobile browser bottom-bar (android)
+ this.cols = Math.floor(this.data.width/this.data.lineHeight*2)
+ this.rows = Math.floor(this.data.height*0.53/this.data.lineHeight*1.7)
},
events:{
diff --git a/com/isoterminal/VT100.js b/com/isoterminal/VT100.js
index e3bdd0e..551d91c 100644
--- a/com/isoterminal/VT100.js
+++ b/com/isoterminal/VT100.js
@@ -13,6 +13,8 @@
//
// Released under the GNU LGPL v2.1, by Frank Bi
//
+//
+// 2024-08-xx upgraded things to work in WebXR (xterm.js too heavy)
// 2007-08-12 - refresh():
// - factor out colour code to html_colours_()
// - fix handling of A_REVERSE | A_DIM
@@ -118,6 +120,8 @@ function VT100(opts)
this.redraw_[r] = 1;
}
this.scr_ = scr;
+ this.scr_.style.display = 'inline'
+ this.setupTouchInputFallback() // smartphone
this.cursor_vis_ = true;
this.cursor_key_mode_ = VT100.CK_CURSOR;
this.grab_events_ = false;
@@ -131,8 +135,6 @@ function VT100(opts)
// rate limit this.refresh
this.refresh = this.throttleSmart( VT100.prototype.refresh.bind(this), 100)
-
- this.setupTouchInputFallback() // smartphone
}
// public constants -- colours and colour pairs
@@ -552,8 +554,9 @@ VT100.prototype.clearpos = function VT100_clearpos(row, col)
VT100.prototype.curs_set = function(vis, grab, eventist)
{
this.info("curs_set:: vis: " + vis + ", grab: " + grab);
- if (vis !== undefined)
+ if (vis !== undefined){
this.cursor_vis_ = (vis > 0);
+ }
if (eventist === undefined)
eventist = this.scr_;
if (grab === true || grab === false) {
@@ -656,7 +659,8 @@ VT100.prototype.refresh = function VT100_refresh()
for (c = 0; c < wd; ++c) {
added_end_tag = false;
n_at = this.attr_[r][c];
- if (cv && r == cr && c == cc) {
+ const drawCursor = cv && r == cr && c == cc
+ if (drawCursor){
// Draw the cursor here.
n_at = this._cloneAttr(n_at);
n_at.mode ^= VT100.A_REVERSE;
@@ -681,7 +685,9 @@ VT100.prototype.refresh = function VT100_refresh()
start_tag += ';font-weight: bolder';
if (n_at.mode & VT100.A_UNDERLINE)
start_tag += ';text-decoration:underline';
- start_tag += ';">';
+ if ( drawCursor )
+ start_tag += '" class="cursor'
+ start_tag += '">';
row_html += start_tag;
end_tag = "" + end_tag;
at = n_at;
@@ -721,6 +727,7 @@ VT100.prototype.refresh = function VT100_refresh()
div_element.innerHTML = row_html;
//dump("adding row html: " + row_html + "\n");
}
+ this.curs_set(1)
}
VT100.prototype.set_max_scroll_lines = function(max_lines)
@@ -816,455 +823,460 @@ VT100.prototype.standout = function()
VT100.prototype.write = function VT100_write(stuff)
{
- var ch, x, r, c, i, j, cv;
- var ht = this.ht_;
- var codes = "";
- var prev_esc_state_ = 0;
- var undrawn_rows;
- var ht_minus1 = ht - 1;
- var start_row_offset = ht - this.row_;
- var start_num_rows = this.num_rows_;
- for (i = 0; i < stuff.length; ++i) {
- // Refresh when there are undrawn rows that are about to be
- // scrolled off the screen, need to draw these rows before
- // the scrolling occurs, otherwise they will never be visible.
- undrawn_rows = (this.num_rows_ - start_num_rows) + start_row_offset;
- if (undrawn_rows >= ht) {
- cv = this.cursor_vis_;
- this.cursor_vis_ = false;
- this.refresh();
- this.cursor_vis_ = cv;
- start_row_offset = ht - this.row_;
- start_num_rows = this.num_rows_;
- //dump("refreshed\n");
- }
- ch = stuff.charAt(i);
- //alert(this.esc_state_);
+ var ch, x, r, c, i, j, cv;
+ var ht = this.ht_;
+ var codes = "";
+ var prev_esc_state_ = 0;
+ var undrawn_rows;
+ var ht_minus1 = ht - 1;
+ var start_row_offset = ht - this.row_;
+ var start_num_rows = this.num_rows_;
+ for (i = 0; i < stuff.length; ++i) {
+ // Refresh when there are undrawn rows that are about to be
+ // scrolled off the screen, need to draw these rows before
+ // the scrolling occurs, otherwise they will never be visible.
+ undrawn_rows = (this.num_rows_ - start_num_rows) + start_row_offset;
+ if (undrawn_rows >= ht) {
+ cv = this.cursor_vis_;
+ this.cursor_vis_ = false;
+ this.refresh();
+ this.cursor_vis_ = cv;
+ start_row_offset = ht - this.row_;
+ start_num_rows = this.num_rows_;
+ //dump("refreshed\n");
+ }
+ ch = stuff.charAt(i);
+ //alert(this.esc_state_);
- if (this.log_level_ >= VT100.INFO) {
- if (ch == '\x1b') {
- code = "ESC";
- } else {
- code = this.escape(ch);
- }
+ if (this.log_level_ >= VT100.INFO) {
+ if (ch == '\x1b') {
+ code = "ESC";
+ } else {
+ code = this.escape(ch);
+ }
this.debug(" write:: ch: " + ch.charCodeAt(0) + ", '" + code + "'");
- codes += code;
- }
+ codes += code;
+ }
- switch (ch) {
- case '\x00':
- case '\x7f':
- continue;
- case '\x07': /* bell, ignore it (UNLESS waiting for OSC terminator, see below */
- if (this.esc_state_ != 8) {
- this.debug(" ignoring bell character: " + ch);
- continue;
- }
- break;
- // This is NOT an Escape sequence
- //case '\a':
- case '\b':
- case '\t':
- case '\r':
- this.addch(ch);
- continue;
- case '\n':
- case '\v':
- case '\f': // what a mess
- r = this.row_;
- if (r >= this.scroll_region_[1]) {
- this.scroll();
- this.move(this.scroll_region_[1], 0);
- } else {
- this.move(r + 1, 0);
- }
- continue;
- case '\x18':
- case '\x1a':
- this.esc_state_ = 0;
- this.debug(" set escape state: 0");
- continue;
- case '\x1b':
- this.esc_state_ = 1;
- this.debug(" set escape state: 1");
- continue;
- case '\x9b':
- this.esc_state_ = 2;
- this.debug(" set escape state: 2");
- continue;
- case '\x9d':
- this.osc_Ps = this.osc_Pt = "";
- this.esc_state_ = 7;
- this.debug(" set escape state: 7");
- continue;
- }
- prev_esc_state_ = this.esc_state_;
- // not a recognized control character
- switch (this.esc_state_) {
- case 0: // not in escape sequence
- this.addch(ch);
- break;
- case 1: // just saw ESC
- switch (ch) {
- case '[':
- this.esc_state_ = 2;
- this.debug(" set escape state: 2");
- break;
- case ']':
- this.osc_Ps = this.osc_Pt = "";
- this.esc_state_ = 7;
- this.debug(" set escape state: 7");
- break;
- case '(':
- case ')':
- this.esc_state_ = 10;
- this.debug(" set escape state: 10");
- break;
- case '=':
- /* Set keypade mode (ignored) */
- this.info(" set keypade mode: ignored");
- this.esc_state_ = 0;
- break;
- case '>':
- /* Reset keypade mode (ignored) */
- this.info(" reset keypade mode: ignored");
- this.esc_state_ = 0;
- break;
- case 'H':
- /* Set tab at cursor column (ignored) */
- this.info(" set tab cursor column: ignored");
- this.esc_state_ = 0;
- break;
- case 'D':
- /* Scroll display down one line */
- this.scroll();
- this.esc_state_ = 0;
- break;
- case 'D':
- /* Scroll display down one line */
- this.scroll();
- this.esc_state_ = 0;
- case 'M':
- /* Scroll display up one line */
- this.scrollup();
- this.esc_state_ = 0;
- break;
- }
- break;
- case 2: // just saw CSI
- switch (ch) {
- case 'K':
- /* Erase in Line */
- this.esc_state_ = 0;
- this.clrtoeol();
- continue;
- case 'H':
- /* Move to (0,0). */
- this.esc_state_ = 0;
- this.move(0, 0);
- continue;
- case 'J':
- /* Clear to the bottom. */
- this.esc_state_ = 0;
- this.clrtobot();
- continue;
- case 'r':
- /* Reset scrolling region. */
- this.esc_state_ = 0;
- this.set_scrolling_region(0, this.ht_ - 1);
- continue;
- case '?':
- /* Special VT100 mode handling. */
- this.esc_state_ = 5;
- this.debug(" special vt100 mode");
- continue;
- }
- // Drop through to next case.
- this.csi_parms_ = [0];
- //this.debug(" set escape state: 3");
- this.esc_state_ = 3;
- case 3: // saw CSI and parameters
- switch (ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- x = this.csi_parms_.pop();
- this.csi_parms_.push(x * 10 + ch * 1);
- this.debug(" csi_parms_: " + this.csi_parms_);
- continue;
- case ';':
- if (this.csi_parms_.length < 17)
- this.csi_parms_.push(0);
- continue;
- }
- this.esc_state_ = 0;
- switch (ch) {
- case 'A':
- // Cursor Up [{COUNT}A
- this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
- this.col_);
- break;
- case 'B':
- // Cursor Down [{COUNT}B
- this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
- this.col_);
- break;
- case 'C':
- // Cursor Forward [{COUNT}C
- this.move(this.row_,
- this.col_ + Math.max(1, this.csi_parms_[0]));
- break;
- case 'D':
- // Cursor Backward [{COUNT}D
- this.move(this.row_,
- this.col_ - Math.max(1, this.csi_parms_[0]));
- break;
- /* TODO: E and F are untested, G and d are not tested thoroughly */
- case 'E':
- // Cursor Next Line
- this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
- 0);
- break;
- case 'F':
- // Cursor Previous Line
- this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
- 0);
- break;
- case 'G':
- // Cursor Horizontal Absolute
- this.move(this.row_,
- this.csi_parms_[0] - 1);
- break;
- case 'd':
- // Line Position Absolute
- this.move(this.csi_parms_[0] - 1,
- this.col_);
- break;
- case 'f':
- case 'H':
- // Cursor Home [{ROW};{COLUMN}H
- this.csi_parms_.push(0);
- this.move(this.csi_parms_[0] - 1,
- this.csi_parms_[1] - 1);
- break;
- case 'J':
- switch (this.csi_parms_[0]) {
- case 0:
- this.clrtobot();
- break;
- case 2:
- this.clear();
- this.move(0, 0);
- }
- break;
- case 'm':
- for (j=0; j[?
- // Expect a number - the reset type
- this.csi_parms_ = [ch];
- this.esc_state_ = 6;
- break;
- case 6: // Reset mode handling, saw [?1
- // Expect a letter - the mode target, example:
- // [?1h : Set cursor key mode to application
- // [?3h : Set number of columns to 132
- // [?4h : Set smooth scrolling
- // [?5h : Set reverse video on screen
- // [?6h : Set origin to relative
- // [?7h : Set auto-wrap mode
- // [?8h : Set auto-repeat mode
- // [?9h : Set interlacing mode
- // [?1l : Set cursor key mode to cursor
- // [?2l : Set VT52 (versus ANSI) compatible
- // [?3l : Set number of columns to 80
- // [?4l : Set jump scrolling
- // [?5l : Set normal video on screen
- // [?6l : Set origin to absolute
- // [?7l : Reset auto-wrap mode
- // [?8l : Reset auto-repeat mode
- // [?9l : Reset interlacing mode
- // XXX: Ignored for now.
- //dump("Saw reset mode: [?" + this.csi_parms_[0] + ch + "\n");
- if (ch != 'h' && ch != 'l') {
- this.csi_parms_.push(ch);
- continue;
- }
- var command = this.csi_parms_.join('') + ch;
- if (command == '1h') {
- this.cursor_key_mode_ = VT100.CK_APPLICATION;
- } else if (command == '1l') {
- this.cursor_key_mode_ = VT100.CK_CURSOR;
- }
- this.esc_state_ = 0;
- //this.debug(" set escape state: 0");
- break;
- /*
- * OSC commands (http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
- * There are two of them:
- * OSC Ps ; Pt ST
- * OSC Ps ; Pt BEL
- *
- * OSC is 0x9d, ST is either 0x9c or 0x1b \
- * esc_state_ == 7 OSC found
- * == 8 ; found
- * == 9 ESC occured in OSC, awaiting \
- * Ps and Pt are stored in osc_Ps and osc_Pt, respectively
- */
- case 7:
- if (ch == ';') {
- this.debug(" set escape state: 8");
- this.esc_state_ = 8;
- }
- else {
- this.osc_Ps += ch;
- }
- break;
- case 8:
- if (ch == '\x07' || ch == '\x9c') {
- this.esc_state_ = 0;
- //alert(this.osc_Ps + ' ' + this.osc_Pt);
- }
- else if (ch == '\x1b') {
- this.debug(" set escape state: 8");
- this.esc_state_ = 9;
- }
- else {
- this.osc_Pt += ch;
- }
- break;
- case 9:
- if (ch != '\\') {
- this.warn(" unknown command: " + ch)
- } else {
- this.esc_state_ = 0;
- //alert(this.osc_Ps + ' ' + this.osc_Pt);
- }
- break;
- case 10:
- /* Just ignore them for now */
- this.esc_state = 0;
- break;
- }
- if ((prev_esc_state_ > 0 && this.esc_state_ == 0) ||
- (prev_esc_state_ == 0 && this.esc_state_ > 0)) {
- this.info("codes: " + this.escape(codes));
- codes = "";
- }
- }
- this.refresh();
+ switch (ch) {
+ case '\x00':
+ case '\x7f':
+ continue;
+ case '\x07': /* bell, ignore it (UNLESS waiting for OSC terminator, see below */
+ if (this.esc_state_ != 8) {
+ this.debug(" ignoring bell character: " + ch);
+ continue;
+ }
+ break;
+ // This is NOT an Escape sequence
+ //case '\a':
+ case '\b':
+ case '\t':
+ case '\r':
+ this.addch(ch);
+ continue;
+ case '\n':
+ case '\v':
+ case '\f': // what a mess
+ r = this.row_;
+ if (r >= this.scroll_region_[1]) {
+ this.scroll();
+ this.move(this.scroll_region_[1], 0);
+ } else {
+ this.move(r + 1, 0);
+ }
+ continue;
+ case '\x18':
+ case '\x1a':
+ this.esc_state_ = 0;
+ this.debug(" set escape state: 0");
+ continue;
+ case '\x1b':
+ this.esc_state_ = 1;
+ this.debug(" set escape state: 1");
+ continue;
+ case '\x9b':
+ this.esc_state_ = 2;
+ this.debug(" set escape state: 2");
+ continue;
+ case '\x9d':
+ this.osc_Ps = this.osc_Pt = "";
+ this.esc_state_ = 7;
+ this.debug(" set escape state: 7");
+ continue;
+ }
+ prev_esc_state_ = this.esc_state_;
+ // not a recognized control character
+ switch (this.esc_state_) {
+ case 0: // not in escape sequence
+ this.addch(ch);
+ break;
+ case 1: // just saw ESC
+ switch (ch) {
+ case '[':
+ this.esc_state_ = 2;
+ this.debug(" set escape state: 2");
+ break;
+ case ']':
+ this.osc_Ps = this.osc_Pt = "";
+ this.esc_state_ = 7;
+ this.debug(" set escape state: 7");
+ break;
+ case '(':
+ case ')':
+ this.esc_state_ = 10;
+ this.debug(" set escape state: 10");
+ break;
+ case '=':
+ /* Set keypade mode (ignored) */
+ this.info(" set keypade mode: ignored");
+ this.esc_state_ = 0;
+ break;
+ case '>':
+ /* Reset keypade mode (ignored) */
+ this.info(" reset keypade mode: ignored");
+ this.esc_state_ = 0;
+ break;
+ case 'H':
+ /* Set tab at cursor column (ignored) */
+ this.info(" set tab cursor column: ignored");
+ this.esc_state_ = 0;
+ break;
+ case 'D':
+ /* Scroll display down one line */
+ this.scroll();
+ this.esc_state_ = 0;
+ break;
+ case 'D':
+ /* Scroll display down one line */
+ this.scroll();
+ this.esc_state_ = 0;
+ case 'M':
+ /* Scroll display up one line */
+ this.scrollup();
+ this.esc_state_ = 0;
+ break;
+ }
+ break;
+ case 2: // just saw CSI
+ switch (ch) {
+ case 'K':
+ /* Erase in Line */
+ this.esc_state_ = 0;
+ this.clrtoeol();
+ continue;
+ case 'H':
+ /* Move to (0,0). */
+ this.esc_state_ = 0;
+ this.move(0, 0);
+ continue;
+ case 'J':
+ /* Clear to the bottom. */
+ this.esc_state_ = 0;
+ this.clrtobot();
+ continue;
+ case 'r':
+ /* Reset scrolling region. */
+ this.esc_state_ = 0;
+ this.set_scrolling_region(0, this.ht_ - 1);
+ continue;
+ case '?':
+ /* Special VT100 mode handling. */
+ this.esc_state_ = 5;
+ this.debug(" special vt100 mode");
+ continue;
+ }
+ // Drop through to next case.
+ this.csi_parms_ = [0];
+ //this.debug(" set escape state: 3");
+ this.esc_state_ = 3;
+ case 3: // saw CSI and parameters
+ switch (ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ x = this.csi_parms_.pop();
+ this.csi_parms_.push(x * 10 + ch * 1);
+ this.debug(" csi_parms_: " + this.csi_parms_);
+ continue;
+ case ';':
+ if (this.csi_parms_.length < 17)
+ this.csi_parms_.push(0);
+ continue;
+ }
+ this.esc_state_ = 0;
+ switch (ch) {
+ case 'A':
+ // Cursor Up [{COUNT}A
+ this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
+ this.col_);
+ break;
+ case 'B':
+ // Cursor Down [{COUNT}B
+ this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
+ this.col_);
+ break;
+ case 'C':
+ // Cursor Forward [{COUNT}C
+ this.move(this.row_,
+ this.col_ + Math.max(1, this.csi_parms_[0]));
+ break;
+ case 'D':
+ // Cursor Backward [{COUNT}D
+ this.move(this.row_,
+ this.col_ - Math.max(1, this.csi_parms_[0]));
+ break;
+ /* TODO: E and F are untested, G and d are not tested thoroughly */
+ case 'E':
+ // Cursor Next Line
+ this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
+ 0);
+ break;
+ case 'F':
+ // Cursor Previous Line
+ this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
+ 0);
+ break;
+ case 'G':
+ // Cursor Horizontal Absolute
+ this.move(this.row_,
+ this.csi_parms_[0] - 1);
+ break;
+ case 'd':
+ // Line Position Absolute
+ this.move(this.csi_parms_[0] - 1,
+ this.col_);
+ break;
+ case 'f':
+ case 'H':
+ // Cursor Home [{ROW};{COLUMN}H
+ this.csi_parms_.push(0);
+ this.move(this.csi_parms_[0] - 1,
+ this.csi_parms_[1] - 1);
+ break;
+ case 'J':
+ switch (this.csi_parms_[0]) {
+ case 0:
+ this.clrtobot();
+ break;
+ case 2:
+ this.clear();
+ this.move(0, 0);
+ }
+ break;
+ case 'm':
+ for (j=0; j 89 && x < 98 && this.opts.rainbow ){
+ const rainbow = this.opts.rainbow
+ this.fgset( rainbow[ Math.floor( Math.random() * 1000 ) % rainbow.length ] )
+ }
+ switch (x) {
+ case 0:
+ this.standend();
+ this.fgset(this.bkgd_.fg);
+ this.bgset(this.bkgd_.bg);
+ break;
+ case 1:
+ this.attron(VT100.A_BOLD);
+ break;
+ case 2:
+ this.attroff(VT100.A_BOLD);
+ break;
+ case 4:
+ this.attron(VT100.A_UNDERLINE);
+ break;
+ case 5:
+ this.attron(VT100.A_BLINK);
+ break;
+ case 7:
+ this.attron(VT100.A_REVERSE);
+ break;
+ case 8:
+ this.attron(VT100.A_INVIS);
+ break;
+ case 30:
+ this.fgset(VT100.COLOR_BLACK);
+ break;
+ case 31:
+ this.fgset(VT100.COLOR_RED);
+ break;
+ case 32:
+ this.fgset(VT100.COLOR_GREEN);
+ break;
+ case 33:
+ this.fgset(VT100.COLOR_YELLOW);
+ break;
+ case 34:
+ this.fgset(VT100.COLOR_BLUE);
+ break;
+ case 35:
+ this.fgset(VT100.COLOR_MAGENTA);
+ break;
+ case 36:
+ this.fgset(VT100.COLOR_CYAN);
+ break;
+ case 37:
+ this.fgset(VT100.COLOR_WHITE);
+ break;
+ case 39:
+ this.fgset(this.bkgd_.fg);
+ break;
+ case 40:
+ this.bgset(VT100.COLOR_BLACK);
+ break;
+ case 41:
+ this.bgset(VT100.COLOR_RED);
+ break;
+ case 42:
+ this.bgset(VT100.COLOR_GREEN);
+ break;
+ case 43:
+ this.bgset(VT100.COLOR_YELLOW);
+ break;
+ case 44:
+ this.bgset(VT100.COLOR_BLUE);
+ break;
+ case 45:
+ this.bgset(VT100.COLOR_MAGENTA);
+ break;
+ case 46:
+ this.bgset(VT100.COLOR_CYAN);
+ break;
+ case 47:
+ this.bgset(VT100.COLOR_WHITE);
+ break;
+ case 49:
+ this.bgset(this.bkgd_.bg);
+ break;
+ }
+ }
+ break;
+ case 'r':
+ // 1,24r - set scrolling region
+ this.set_scrolling_region(this.csi_parms_[0] - 1,
+ this.csi_parms_[1] - 1);
+ break;
+ case '[':
+ this.debug(" set escape state: 4");
+ this.esc_state_ = 4;
+ break;
+ case 'g':
+ // 0g: clear tab at cursor (ignored)
+ // 3g: clear all tabs (ignored)
+ if (this.csi_parms_[0] == 3)
+ this.clear_all();
+ break;
+ default:
+ this.warn(" unknown command: " + ch);
+ this.csi_parms_ = [];
+ return
+ break;
+ }
+ break;
+ case 4: // saw CSI [
+ this.esc_state_ = 0; // gobble char.
+ break;
+ case 5: // Special mode handling, saw [?
+ // Expect a number - the reset type
+ this.csi_parms_ = [ch];
+ this.esc_state_ = 6;
+ break;
+ case 6: // Reset mode handling, saw [?1
+ // Expect a letter - the mode target, example:
+ // [?1h : Set cursor key mode to application
+ // [?3h : Set number of columns to 132
+ // [?4h : Set smooth scrolling
+ // [?5h : Set reverse video on screen
+ // [?6h : Set origin to relative
+ // [?7h : Set auto-wrap mode
+ // [?8h : Set auto-repeat mode
+ // [?9h : Set interlacing mode
+ // [?1l : Set cursor key mode to cursor
+ // [?2l : Set VT52 (versus ANSI) compatible
+ // [?3l : Set number of columns to 80
+ // [?4l : Set jump scrolling
+ // [?5l : Set normal video on screen
+ // [?6l : Set origin to absolute
+ // [?7l : Reset auto-wrap mode
+ // [?8l : Reset auto-repeat mode
+ // [?9l : Reset interlacing mode
+ // XXX: Ignored for now.
+ //dump("Saw reset mode: [?" + this.csi_parms_[0] + ch + "\n");
+ if (ch != 'h' && ch != 'l') {
+ this.csi_parms_.push(ch);
+ continue;
+ }
+ var command = this.csi_parms_.join('') + ch;
+ if (command == '1h') {
+ this.cursor_key_mode_ = VT100.CK_APPLICATION;
+ } else if (command == '1l') {
+ this.cursor_key_mode_ = VT100.CK_CURSOR;
+ }
+ this.esc_state_ = 0;
+ //this.debug(" set escape state: 0");
+ break;
+ /*
+ * OSC commands (http://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
+ * There are two of them:
+ * OSC Ps ; Pt ST
+ * OSC Ps ; Pt BEL
+ *
+ * OSC is 0x9d, ST is either 0x9c or 0x1b \
+ * esc_state_ == 7 OSC found
+ * == 8 ; found
+ * == 9 ESC occured in OSC, awaiting \
+ * Ps and Pt are stored in osc_Ps and osc_Pt, respectively
+ */
+ case 7:
+ if (ch == ';') {
+ this.debug(" set escape state: 8");
+ this.esc_state_ = 8;
+ }
+ else {
+ this.osc_Ps += ch;
+ }
+ break;
+ case 8:
+ if (ch == '\x07' || ch == '\x9c') {
+ this.esc_state_ = 0;
+ //alert(this.osc_Ps + ' ' + this.osc_Pt);
+ }
+ else if (ch == '\x1b') {
+ this.debug(" set escape state: 8");
+ this.esc_state_ = 9;
+ }
+ else {
+ this.osc_Pt += ch;
+ }
+ break;
+ case 9:
+ if (ch != '\\') {
+ this.warn(" unknown command: " + ch)
+ } else {
+ this.esc_state_ = 0;
+ //alert(this.osc_Ps + ' ' + this.osc_Pt);
+ }
+ break;
+ case 10:
+ /* Just ignore them for now */
+ this.esc_state = 0;
+ break;
+ }
+ if ((prev_esc_state_ > 0 && this.esc_state_ == 0) ||
+ (prev_esc_state_ == 0 && this.esc_state_ > 0)) {
+ this.info("codes: " + this.escape(codes));
+ codes = "";
+ }
+ }
+ this.refresh();
}
@@ -1309,38 +1321,52 @@ VT100.prototype.throttleSmart = function throttleSmart(fn, wait) {
}
VT100.prototype.setupTouchInputFallback = function(){
- this.scr_.addEventListener('touchend', () => {
- if( !this.input ){
- this.form = document.createElement("form")
- this.form.addEventListener("submit", (e) => {
- e.preventDefault()
- this.key_buf_.push('\n')
- setTimeout(VT100.go_getch_, 0);
- })
- this.input = document.createElement("input")
- this.input.setAttribute("cols", this.opts.cols )
- this.input.setAttribute("rows", this.opts.rows )
- this.input.style.opacity = '0'
- this.input.style.position = 'absolute'
- this.input.style.left = '-9999px'
- this.form.appendChild(this.input)
- this.scr_.parentElement.appendChild(this.form)
+ if( !this.input ){
+ this.input = document.createElement("input")
+ this.input.setAttribute("cols", this.opts.cols )
+ this.input.setAttribute("rows", this.opts.rows )
+ this.input.style.opacity = '0'
+ this.input.style.position = 'absolute'
+ this.input.style.left = '-9999px'
+ this.form = document.createElement("form")
+ this.form.addEventListener("submit", (e) => {
+ e.preventDefault()
+ this.key_buf_.push('\n')
+ setTimeout(VT100.go_getch_, 0);
+ })
+ this.form.appendChild(this.input)
+ this.scr_.parentElement.appendChild(this.form)
- this.input.handler = () => {
- let ch = this.input.value
- // detect backspace
- //if( e.inputType == 'deleteContentBackward' ) ch = '\b'
- this.input.value = ''
- if( !ch ) return
- this.key_buf_.push(ch);
- setTimeout(VT100.go_getch_, 0);
- this.input.valueLast = this.input.value
- }
- this.input.addEventListener('input', this.input.handler )
+ this.input.addEventListener('blur', () => {
+ this.key_buf_.push('\n')
+ setTimeout(VT100.go_getch_, 0);
+ })
+ this.input.addEventListener("keydown", VT100.handle_onkeypress_, false);
+
+ this.input.handler = (e) => {
+ let ch
+ let isEnter = String(e?.code).toLowerCase() == "enter" || e?.code == 13
+ ch = isEnter ? '\n' : this.input.value.substr(-1)
+ if( this.input.lastValue && this.input.value.length < this.input.lastValue.length ) ch = '\b' // naive
+ // detect backspace
+ if( !ch ) return
+ this.key_buf_.push(ch);
+ setTimeout(VT100.go_getch_, 0);
+ this.input.lastValue = this.input.value
}
- setTimeout( () => this.input.focus(), 10 )
- })
+ this.input.addEventListener('input', (e) => this.input.handler(e) )
+
+ this.scr_.addEventListener('touchend', (e) => this.focus() )
+ this.scr_.addEventListener('click', (e) => this.focus() )
+ }
+ this.focus()
+}
+
+VT100.prototype.focus = function(){
+ setTimeout( () => {
+ this.input.focus()
+ }, 10 )
}
function dump(x) {