diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bebbdb..33ed3d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,7 +141,7 @@ set(SOURCE_FILES user/apars_osc.c user/apars_osc.h user/apars_dcs.c - user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h) + user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h user/character_sets.h) include_directories(include) include_directories(user) diff --git a/build_web.sh b/build_web.sh index b794ccd..72ad0eb 100755 --- a/build_web.sh +++ b/build_web.sh @@ -19,3 +19,8 @@ rm html/css/app.css.map cp html_orig/img/* html/img/ cp html_orig/favicon.ico html/favicon.ico + +# cleanup +find html/ -name "*.orig" -delete +find html/ -name "*.xcf" -delete +find html/ -name "*~" -delete diff --git a/html_orig/_debug_replacements.php b/html_orig/_debug_replacements.php index e154ce0..b02463f 100644 --- a/html_orig/_debug_replacements.php +++ b/html_orig/_debug_replacements.php @@ -15,10 +15,9 @@ return [ 'btn5' => '5', 'labels_seq' => 'TESPTerm local debug1235', - 'screenData' => '  HELLOx NRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //, - 'parser_tout_ms' => 10, - 'display_tout_ms' => 20, + 'display_tout_ms' => 15, + 'display_cooldown_ms' => 35, 'fn_alt_mode' => '1', 'opmode' => '2', @@ -61,6 +60,8 @@ return [ 'term_height' => '10', 'default_bg' => '0', 'default_fg' => '7', + 'show_buttons' => '1', + 'show_config_links' => '1', 'uart_baud' => 115200, 'uart_stopbits' => 1, diff --git a/html_orig/base.php b/html_orig/base.php index 925d057..c4531b1 100644 --- a/html_orig/base.php +++ b/html_orig/base.php @@ -69,3 +69,78 @@ function include_str($code) fclose($tmp); return $ret; } + +if (!function_exists('utf8')) { + function utf8($num) + { + if($num<=0x7F) return chr($num); + if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128); + if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128); + if($num<=0x1FFFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128); + return ''; + } +} + +if (!function_exists('load_esp_charsets')) { + function load_esp_charsets() { + $chsf = __DIR__ . '/../user/character_sets.h'; + $re_table = '/\/\/ %%BEGIN:(.)%%\s*(.*?)\s*\/\/ %%END:\1%%/s'; + preg_match_all($re_table, file_get_contents($chsf), $m_tbl); + + $re_bounds = '/#define CODEPAGE_(.)_BEGIN\s+(\d+)\n#define CODEPAGE_\1_END\s+(\d+)/'; + preg_match_all($re_bounds, file_get_contents($chsf), $m_bounds); + + $cps = []; + + foreach ($m_tbl[2] as $i => $str) { + $name = $m_tbl[1][$i]; + $start = intval($m_bounds[2][$i]); + $table = []; + $str = preg_replace('/,\s*\/\/[^\n]*/', '', $str); + $rows = explode("\n", $str); + $rows = array_map('trim', $rows); + + foreach($rows as $j => $v) { + if (strpos($v, '0x') === 0) { + $v = substr($v, 2); + $v = hexdec($v); + } else { + $v = intval($v); + } + $ascii = $start+$j; + $table[] = [ + $ascii, + chr($ascii), + utf8($v==0? $ascii :$v), + ]; + } + $cps[$name] = $table; + } + return $cps; + } +} + +if (!function_exists('tplSubs')) { + function tplSubs($str, $reps) + { + return preg_replace_callback('/%(j:|js:|h:|html:)?([a-z0-9-_.]+)%/i', function ($m) use ($reps) { + $key = $m[2]; + if (array_key_exists($key, $reps)) { + $val = $reps[$key]; + } else { + $val = ''; + } + switch ($m[1]) { + case 'j:': + case 'js:': + $v = json_encode($val); + return substr($v, 1, strlen($v) - 2); + case 'h:': + case 'html:': + return htmlspecialchars($val); + default: + return $val; + } + }, $str); + } +} diff --git a/html_orig/css/app.css b/html_orig/css/app.css index 2c759a8..0518663 100644 --- a/html_orig/css/app.css +++ b/html_orig/css/app.css @@ -570,10 +570,13 @@ ul { #loader.show { opacity: 1; } +.botpad { + display: block; + height: 5em; } + .Box { display: block; max-width: 900px; - line-height: 1.35em; margin-top: 1rem; padding: 0.61805rem 1rem; border-radius: 3px; @@ -904,6 +907,7 @@ form { vertical-align: middle; margin: 12px auto; text-align: left; + line-height: 1.35em; display: flex; flex-direction: row; align-items: center; } @@ -1147,50 +1151,58 @@ body.term #content { @media screen and (max-width: 544px) { body.term #content h1 { font-size: 1.42383em; } } -body.term #screen { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - font-family: monospace; - font-size: 20px; + +#screen { white-space: nowrap; background: #111213; padding: 6px; display: inline-block; - border: 2px solid #3983CD; } - body.term #screen span { - white-space: pre; - cursor: pointer; - display: inline-block; - line-height: 1.15em; - width: 0.6em; - overflow: visible; } -body.term #buttons { + border: 2px solid #3983CD; + font-size: 24px; + font-family: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace; } + #screen span { + white-space: pre; } + #screen > span { + position: relative; + cursor: pointer; } + #screen > span::before { + content: " "; } + #screen > span > span { + position: absolute; + left: 0; + z-index: 1; } + #screen.noselect { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +#action-buttons { margin-top: 10px; white-space: nowrap; } - body.term #buttons button { + #action-buttons button { margin: 0 3px; padding: 8px 5px; min-width: 62px; cursor: pointer; font-weight: bold; } -body.term #botnav { + +#term-nav { padding-top: 1.5em; text-align: center; } - body.term #botnav a { + #term-nav a { padding: 0 0.38198rem; text-decoration: underline; } - body.term #botnav a, body.term #botnav a:visited, body.term #botnav a:link { + #term-nav a, #term-nav a:visited, #term-nav a:link { color: #336085; } - body.term #botnav a:hover { + #term-nav a:hover { color: #5abfff; } - body.term #botnav .icn-keyboard { + #term-nav .icn-keyboard { text-decoration: none; font-size: 150%; vertical-align: middle; } -#termwrap { +#term-wrap { text-align: center; } #softkb-input { @@ -1677,6 +1689,39 @@ body.term #botnav { .tscroll { overflow-x: auto; } +.charset { + line-height: 1; } + .charset div { + display: inline-block; + width: 2.5em; + border: 1px solid #666; + height: 3em; + margin: 1px; + position: relative; } + .charset div span { + display: block; + position: absolute; } + .charset div span:nth-child(1) { + left: .2em; + top: .2em; + height: 1em; + font-size: 85%; + color: #999; } + .charset div span:nth-child(2) { + right: .2em; + top: .2em; + height: 1em; + font-size: 85%; + color: #999; } + .charset div span:nth-child(3) { + width: 100%; + font-size: 105%; + text-align: center; + bottom: .4em; + font-family: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace; } + .charset div.none { + opacity: .4; } + @media screen and (min-width: 545px) { .mq-phone { display: none !important; } } diff --git a/html_orig/dump_js_lang.php b/html_orig/dump_js_lang.php index 14b0db6..ab2f976 100755 --- a/html_orig/dump_js_lang.php +++ b/html_orig/dump_js_lang.php @@ -8,6 +8,7 @@ $selected = [ 'wifi.connected_ip_is', 'wifi.not_conn', 'wifi.enter_passwd', + 'wifi.passwd_saved', ]; $out = []; diff --git a/html_orig/img/adapter.jpg b/html_orig/img/adapter.jpg.orig similarity index 100% rename from html_orig/img/adapter.jpg rename to html_orig/img/adapter.jpg.orig diff --git a/html_orig/img/vt100.jpg b/html_orig/img/vt100.jpg index 909461a..7046042 100644 Binary files a/html_orig/img/vt100.jpg and b/html_orig/img/vt100.jpg differ diff --git a/html_orig/img/vt100.jpg.orig b/html_orig/img/vt100.jpg.orig new file mode 100644 index 0000000..909461a Binary files /dev/null and b/html_orig/img/vt100.jpg.orig differ diff --git a/html_orig/index.php b/html_orig/index.php index 2ce2622..fbd94a4 100644 --- a/html_orig/index.php +++ b/html_orig/index.php @@ -7,46 +7,35 @@ if (!isset($_GET['page'])) $_GET['page'] = 'term'; $_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME; $_GET['BODYCLASS'] = $_pages[$_GET['page']]->bodyclass; -if (!function_exists('tplSubs')) { - function tplSubs($str, $reps) - { - return preg_replace_callback('/%(j:|js:|h:|html:)?([a-z0-9-_.]+)%/i', function ($m) use ($reps) { - $key = $m[2]; - if (array_key_exists($key, $reps)) { - $val = $reps[$key]; - } else { - $val = ''; - } - switch ($m[1]) { - case 'j:': - case 'js:': - $v = json_encode($val); - return substr($v, 1, strlen($v) - 2); - case 'h:': - case 'html:': - return htmlspecialchars($val); - default: - return $val; - } - }, $str); - } -} - require __DIR__ . '/pages/_head.php'; $_pf = __DIR__ . '/pages/'.$_GET['page'].'.php'; + +$include_re = '/<\?php\s*(require|include)\s*\(?\s*?(?:__DIR__\s*\.)?\s*(["\'])(.*?)\2\s*\)?;\s*\?>/'; + if (file_exists($_pf)) { $f = file_get_contents($_pf); + // Resolve requires inline - they wont work after dumping the resulting file to /tmp for eval + $f = preg_replace_callback($include_re, function ($m) use ($_pf) { + $n = dirname($_pf).'/'.$m[3]; + if (file_exists($n)) { + return file_get_contents($n); + } else { + return "

NOT FOUND: $n

"; + } + }, $f); + if (DEBUG) $str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php')); else $str = $f; // special symbols $str = str_replace('\,', ' ', $str); - $str = preg_replace('/(?<=[^ ])~(?=[^ ])/', ' ', $str); - $str = preg_replace('/(?$1', $str); - $str = preg_replace('/(?$1', $str); - $str = preg_replace('/(?$1', $str); + $str = preg_replace('/(?<=[^ \\\\])~(?=[^ ])/', ' ', $str); + $str = str_replace('\~', '~', $str); + $str = preg_replace('/(?$1', $str); + $str = preg_replace('/(?$1', $str); + $str = preg_replace('/(?$1', $str); $str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '
', $str); include_str($str); diff --git a/html_orig/js/app.js b/html_orig/js/app.js index 6095ede..c1980f7 100644 --- a/html_orig/js/app.js +++ b/html_orig/js/app.js @@ -1134,6 +1134,41 @@ function jsp() { return null; } } + +/** Decode two-byte number */ +function parse2B(s, i) { + return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127; +} + +/** Decode three-byte number */ +function parse3B(s, i) { + return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127; +} + +function Chr(n) { + return String.fromCharCode(n); +} + +function encode2B(n) { + var lsb, msb; + lsb = (n % 127); + n = ((n - lsb) / 127); + lsb += 1; + msb = (n + 1); + return Chr(lsb) + Chr(msb); +} + +function encode3B(n) { + var lsb, msb, xsb; + lsb = (n % 127); + n = (n - lsb) / 127; + lsb += 1; + msb = (n % 127); + n = (n - msb) / 127; + msb += 1; + xsb = (n + 1); + return Chr(lsb) + Chr(msb) + Chr(xsb); +} /** Module for toggling a modal overlay */ (function () { var modal = {}; @@ -1423,7 +1458,6 @@ function tr(key) { return _tr[key] || '?'+key+'?'; } $('#sta-nw .essid').html(e(name)); var nopw = undef(password) || password.length == 0; - $('#sta-nw .x-passwd').html(e(password)); $('#sta-nw .passwd').toggleClass('hidden', nopw); $('#sta-nw .nopasswd').toggleClass('hidden', !nopw); $('#sta-nw .ip').html(ip.length>0 ? tr('wifi.connected_ip_is')+ip : tr('wifi.not_conn')); @@ -1564,41 +1598,6 @@ function tr(key) { return _tr[key] || '?'+key+'?'; } w.init = wifiInit; w.startScanning = startScanning; })(window.WiFi = {}); -/** Decode two-byte number */ -function parse2B(s, i) { - return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127; -} - -/** Decode three-byte number */ -function parse3B(s, i) { - return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127; -} - -function Chr(n) { - return String.fromCharCode(n); -} - -function encode2B(n) { - var lsb, msb; - lsb = (n % 127); - n = ((n - lsb) / 127); - lsb += 1; - msb = (n + 1); - return Chr(lsb) + Chr(msb); -} - -function encode3B(n) { - var lsb, msb, xsb; - lsb = (n % 127); - n = (n - lsb) / 127; - lsb += 1; - msb = (n % 127); - n = (n - msb) / 127; - msb += 1; - xsb = (n + 1); - return Chr(lsb) + Chr(msb) + Chr(xsb); -} - var Screen = (function () { var W = 0, H = 0; // dimensions var inited = false; @@ -1611,15 +1610,16 @@ var Screen = (function () { bg: 0, attrs: 0, suppress: false, // do not turn on in blink interval (for safe moving) - forceOn: false, - hidden: false, // do not show - hanging: false, // xenl + forceOn: false, // force on unless hanging: used to keep cursor visible during move + hidden: false, // do not show (DEC opt) + hanging: false, // cursor at column "W+1" - not visible }; var screen = []; var blinkIval; var cursorFlashStartIval; + // Some non-bold Fraktur symbols are outside the contiguous block var frakturExceptions = { 'C': '\u212d', 'H': '\u210c', @@ -1633,7 +1633,7 @@ var Screen = (function () { try { audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)(); } catch (er) { - console.error("Browser does not support AudioContext, can't beep.", er); + console.error("No AudioContext!", er); } /** Get cell under cursor */ @@ -1653,6 +1653,22 @@ var Screen = (function () { _draw(_curCell()); } + function alpha2fraktur(t) { + // perform substitution + if (t >= 'a' && t <= 'z') { + t = String.fromCodePoint(0x1d51e - 97 + t.charCodeAt(0)); + } + else if (t >= 'A' && t <= 'Z') { + // this set is incomplete, some exceptions are needed + if (frakturExceptions.hasOwnProperty(t)) { + t = frakturExceptions[t]; + } else { + t = String.fromCodePoint(0x1d504 - 65 + t.charCodeAt(0)); + } + } + return t; + } + /** Update cell on display. inv = invert (for cursor) */ function _draw(cell, inv) { if (!cell) return; @@ -1660,44 +1676,28 @@ var Screen = (function () { inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y; } - var elem = cell.e, fg, bg, cn, t; - // Colors + var fg, bg, cn, t; + fg = inv ? cell.bg : cell.fg; bg = inv ? cell.fg : cell.bg; - // Update - elem.textContent = t = (cell.t + ' ')[0]; + + t = cell.t; + if (!t.length) t = ' '; cn = 'fg' + fg + ' bg' + bg; if (cell.attrs & (1<<0)) cn += ' bold'; + if (cell.attrs & (1<<1)) cn += ' faint'; if (cell.attrs & (1<<2)) cn += ' italic'; if (cell.attrs & (1<<3)) cn += ' under'; if (cell.attrs & (1<<4)) cn += ' blink'; if (cell.attrs & (1<<5)) { cn += ' fraktur'; - // perform substitution - if (t >= 'a' && t <= 'z') { - t = String.fromCodePoint(0x1d51e - 97 + t.charCodeAt(0)); - } - else if (t >= 'A' && t <= 'Z') { - // this set is incomplete, some exceptions are needed - if (frakturExceptions.hasOwnProperty(t)) { - t = frakturExceptions[t]; - } else { - t = String.fromCodePoint(0x1d504 - 65 + t.charCodeAt(0)); - } - } - elem.textContent = t; + t = alpha2fraktur(t); } if (cell.attrs & (1<<6)) cn += ' strike'; - if (cell.attrs & (1<<1)) { - cn += ' faint'; - // faint requires special html - otherwise it would also dim the background. - // we use opacity on the text... - elem.innerHTML = '' + e(elem.textContent) + ''; - } - - elem.className = cn; + cell.slot.textContent = t; + cell.elem.className = cn; } /** Show entire screen */ @@ -1712,32 +1712,34 @@ var Screen = (function () { H = rows; /* Build screen & show */ - var e, cell, scr = qs('#screen'); + var cOuter, cInner, cell, screenDiv = qs('#screen'); // Empty the screen node - while (scr.firstChild) scr.removeChild(scr.firstChild); + while (screenDiv.firstChild) screenDiv.removeChild(screenDiv.firstChild); screen = []; for(var i = 0; i < W*H; i++) { - e = mk('span'); + cOuter = mk('span'); + cInner = mk('span'); + /* Mouse tracking */ (function() { var x = i % W; var y = Math.floor(i / W); - e.addEventListener('mouseenter', function (evt) { + cOuter.addEventListener('mouseenter', function (evt) { Input.onMouseMove(x, y); }); - e.addEventListener('mousedown', function (evt) { + cOuter.addEventListener('mousedown', function (evt) { Input.onMouseDown(x, y, evt.button+1); }); - e.addEventListener('mouseup', function (evt) { + cOuter.addEventListener('mouseup', function (evt) { Input.onMouseUp(x, y, evt.button+1); }); - e.addEventListener('contextmenu', function (evt) { + cOuter.addEventListener('contextmenu', function (evt) { evt.preventDefault(); }); - e.addEventListener('mousewheel', function (evt) { + cOuter.addEventListener('mousewheel', function (evt) { Input.onMouseWheel(x, y, evt.deltaY>0?1:-1); return false; }); @@ -1745,17 +1747,19 @@ var Screen = (function () { /* End of line */ if ((i > 0) && (i % W == 0)) { - scr.appendChild(mk('br')); + screenDiv.appendChild(mk('br')); } /* The cell */ - scr.appendChild(e); + cOuter.appendChild(cInner); + screenDiv.appendChild(cOuter); cell = { t: ' ', fg: 7, bg: 0, // the colors will be replaced immediately as we receive data (user won't see this) attrs: 0, - e: e, + elem: cOuter, + slot: cInner, x: i % W, y: Math.floor(i / W), }; @@ -1770,7 +1774,6 @@ var Screen = (function () { clearInterval(blinkIval); blinkIval = setInterval(function () { cursor.a = !cursor.a; - // TODO try to invent a new way to indicate "hanging" - this is copied from gtkterm if (cursor.hidden || cursor.hanging) { cursor.a = false; } @@ -1780,7 +1783,7 @@ var Screen = (function () { } }, 500); - // blink attribute + /* blink attribute animation */ setInterval(function () { $('#screen').removeClass('blink-hide'); setTimeout(function () { @@ -1791,11 +1794,13 @@ var Screen = (function () { inited = true; } + // constants for decoding the update blob var SEQ_SET_COLOR_ATTR = 1; var SEQ_REPEAT = 2; var SEQ_SET_COLOR = 3; var SEQ_SET_ATTR = 4; + /** Parse received screen update object (leading S removed already) */ function _load_content(str) { var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, attrs, cell; @@ -1819,17 +1824,30 @@ var Screen = (function () { // console.log("Cursor at ",num, num2); // Attributes - num = parse2B(str, i); i += 2; // fg bg bold hidden - cursor.hidden = !(num & 0x0001); - cursor.hanging = !!(num & 0x0002); + num = parse2B(str, i); i += 2; // fg bg attribs + cursor.hidden = !(num & (1<<0)); // DEC opt "visible" + cursor.hanging = !!(num & (1<<1)); // console.log("Attributes word ",num.toString(16)+'h'); Input.setAlts( - !!(num & 0x0004), // cu - !!(num & 0x0008), // np - !!(num & 0x0010) // fn + !!(num & (1<<2)), // cursors alt + !!(num & (1<<3)), // numpad alt + !!(num & (1<<4)) // fn keys alt ); + var mt_click = !!(num & (1<<5)); + var mt_move = !!(num & (1<<6)); + Input.setMouseMode( + mt_click, + mt_move + ); + $('#screen').toggleClass('noselect', mt_move); + + var show_buttons = !!(num & (1<<7)); + var show_config_links = !!(num & (1<<8)); + $('.x-term-conf-btn').toggleClass('hidden', !show_config_links); + $('#action-buttons').toggleClass('hidden', !show_buttons); + fg = 7; bg = 0; attrs = 0; @@ -1892,10 +1910,11 @@ var Screen = (function () { } } + /** Apply labels to buttons and screen title (leading T removed already) */ function _load_labels(str) { var pieces = str.split('\x01'); qs('h1').textContent = pieces[0]; - qsa('#buttons button').forEach(function(x, i) { + qsa('#action-buttons button').forEach(function(x, i) { var s = pieces[i+1].trim(); // if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically x.innerHTML = s.length > 0 ? e(s) : " "; @@ -1903,8 +1922,8 @@ var Screen = (function () { }); } - function _beep() - { + /** Audible beep for ASCII 7 */ + function _beep() { var osc, gain; if (!audioCtx) return; @@ -1946,6 +1965,7 @@ var Screen = (function () { break; default: console.warn("Bad data message type, ignoring."); + console.log(str); } } @@ -2071,24 +2091,31 @@ var Input = (function() { np_alt: false, cu_alt: false, fn_alt: false, + mt_click: false, + mt_move: false, }; + /** Send a literal message */ function sendStrMsg(str) { Conn.send("s"+str); } + /** Send a button event */ function sendBtnMsg(n) { Conn.send("b"+Chr(n)); } + /** Fn alt choice for key message */ function fa(alt, normal) { return opts.fn_alt ? alt : normal; } + /** Cursor alt choice for key message */ function ca(alt, normal) { return opts.cu_alt ? alt : normal; } + /** Numpad alt choice for key message */ function na(alt, normal) { return opts.np_alt ? alt : normal; } @@ -2159,6 +2186,7 @@ var Input = (function() { } } + /** Bind a keystroke to message */ function bind(combo, str) { // mac fix - allow also cmd if (combo.indexOf('ctrl+') !== -1) { @@ -2174,6 +2202,7 @@ var Input = (function() { }); } + /** Bind/rebind key messages */ function _initKeys() { // This takes care of text characters typed window.addEventListener('keypress', function(evt) { @@ -2199,10 +2228,12 @@ var Input = (function() { _bindFnKeys(); } + // mouse button states var mb1 = 0; var mb2 = 0; var mb3 = 0; + /** Init the Input module */ function init() { _initKeys(); @@ -2213,6 +2244,7 @@ var Input = (function() { }); }); + // global mouse state tracking - for motion reporting window.addEventListener('mousedown', function(evt) { if (evt.button == 0) mb1 = 1; if (evt.button == 1) mb2 = 1; @@ -2226,6 +2258,7 @@ var Input = (function() { }); } + /** Prepare modifiers byte for mouse message */ function packModifiersForMouse() { return (key.isModifier('ctrl')?1:0) | (key.isModifier('shift')?2:0) | @@ -2234,9 +2267,13 @@ var Input = (function() { } return { + /** Init the Input module */ init: init, - // onTap: sendPosMsg, + + /** Send a literal string message */ sendString: sendStrMsg, + + /** Enable alternate key modes (cursors, numpad, fn) */ setAlts: function(cu, np, fn) { if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { opts.cu_alt = cu; @@ -2247,34 +2284,46 @@ var Input = (function() { _bindFnKeys(); } }, + + setMouseMode: function(click, move) { + opts.mt_click = click; + opts.mt_move = move; + }, + + // Mouse events onMouseMove: function (x, y) { + if (!opts.mt_move) return; var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0; var m = packModifiersForMouse(); Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); }, onMouseDown: function (x, y, b) { + if (!opts.mt_click) return; if (b > 3 || b < 1) return; var m = packModifiersForMouse(); Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, onMouseUp: function (x, y, b) { + if (!opts.mt_click) return; if (b > 3 || b < 1) return; var m = packModifiersForMouse(); Conn.send("r" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, onMouseWheel: function (x, y, dir) { + if (!opts.mt_click) return; // -1 ... btn 4 (away from user) // +1 ... btn 5 (towards user) var m = packModifiersForMouse(); var b = (dir < 0 ? 4 : 5); Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, }; })(); +/** Init the terminal sub-module - called from HTML */ window.termInit = function () { Conn.init(); Input.init(); diff --git a/html_orig/jssrc/term.js b/html_orig/jssrc/term.js index 8f90db6..1f3f277 100644 --- a/html_orig/jssrc/term.js +++ b/html_orig/jssrc/term.js @@ -1,38 +1,3 @@ -/** Decode two-byte number */ -function parse2B(s, i) { - return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127; -} - -/** Decode three-byte number */ -function parse3B(s, i) { - return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127; -} - -function Chr(n) { - return String.fromCharCode(n); -} - -function encode2B(n) { - var lsb, msb; - lsb = (n % 127); - n = ((n - lsb) / 127); - lsb += 1; - msb = (n + 1); - return Chr(lsb) + Chr(msb); -} - -function encode3B(n) { - var lsb, msb, xsb; - lsb = (n % 127); - n = (n - lsb) / 127; - lsb += 1; - msb = (n % 127); - n = (n - msb) / 127; - msb += 1; - xsb = (n + 1); - return Chr(lsb) + Chr(msb) + Chr(xsb); -} - var Screen = (function () { var W = 0, H = 0; // dimensions var inited = false; @@ -45,15 +10,16 @@ var Screen = (function () { bg: 0, attrs: 0, suppress: false, // do not turn on in blink interval (for safe moving) - forceOn: false, - hidden: false, // do not show - hanging: false, // xenl + forceOn: false, // force on unless hanging: used to keep cursor visible during move + hidden: false, // do not show (DEC opt) + hanging: false, // cursor at column "W+1" - not visible }; var screen = []; var blinkIval; var cursorFlashStartIval; + // Some non-bold Fraktur symbols are outside the contiguous block var frakturExceptions = { 'C': '\u212d', 'H': '\u210c', @@ -67,7 +33,7 @@ var Screen = (function () { try { audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)(); } catch (er) { - console.error("Browser does not support AudioContext, can't beep.", er); + console.error("No AudioContext!", er); } /** Get cell under cursor */ @@ -87,6 +53,22 @@ var Screen = (function () { _draw(_curCell()); } + function alpha2fraktur(t) { + // perform substitution + if (t >= 'a' && t <= 'z') { + t = String.fromCodePoint(0x1d51e - 97 + t.charCodeAt(0)); + } + else if (t >= 'A' && t <= 'Z') { + // this set is incomplete, some exceptions are needed + if (frakturExceptions.hasOwnProperty(t)) { + t = frakturExceptions[t]; + } else { + t = String.fromCodePoint(0x1d504 - 65 + t.charCodeAt(0)); + } + } + return t; + } + /** Update cell on display. inv = invert (for cursor) */ function _draw(cell, inv) { if (!cell) return; @@ -94,44 +76,28 @@ var Screen = (function () { inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y; } - var elem = cell.e, fg, bg, cn, t; - // Colors + var fg, bg, cn, t; + fg = inv ? cell.bg : cell.fg; bg = inv ? cell.fg : cell.bg; - // Update - elem.textContent = t = (cell.t + ' ')[0]; + + t = cell.t; + if (!t.length) t = ' '; cn = 'fg' + fg + ' bg' + bg; if (cell.attrs & (1<<0)) cn += ' bold'; + if (cell.attrs & (1<<1)) cn += ' faint'; if (cell.attrs & (1<<2)) cn += ' italic'; if (cell.attrs & (1<<3)) cn += ' under'; if (cell.attrs & (1<<4)) cn += ' blink'; if (cell.attrs & (1<<5)) { cn += ' fraktur'; - // perform substitution - if (t >= 'a' && t <= 'z') { - t = String.fromCodePoint(0x1d51e - 97 + t.charCodeAt(0)); - } - else if (t >= 'A' && t <= 'Z') { - // this set is incomplete, some exceptions are needed - if (frakturExceptions.hasOwnProperty(t)) { - t = frakturExceptions[t]; - } else { - t = String.fromCodePoint(0x1d504 - 65 + t.charCodeAt(0)); - } - } - elem.textContent = t; + t = alpha2fraktur(t); } if (cell.attrs & (1<<6)) cn += ' strike'; - if (cell.attrs & (1<<1)) { - cn += ' faint'; - // faint requires special html - otherwise it would also dim the background. - // we use opacity on the text... - elem.innerHTML = '' + e(elem.textContent) + ''; - } - - elem.className = cn; + cell.slot.textContent = t; + cell.elem.className = cn; } /** Show entire screen */ @@ -146,32 +112,34 @@ var Screen = (function () { H = rows; /* Build screen & show */ - var e, cell, scr = qs('#screen'); + var cOuter, cInner, cell, screenDiv = qs('#screen'); // Empty the screen node - while (scr.firstChild) scr.removeChild(scr.firstChild); + while (screenDiv.firstChild) screenDiv.removeChild(screenDiv.firstChild); screen = []; for(var i = 0; i < W*H; i++) { - e = mk('span'); + cOuter = mk('span'); + cInner = mk('span'); + /* Mouse tracking */ (function() { var x = i % W; var y = Math.floor(i / W); - e.addEventListener('mouseenter', function (evt) { + cOuter.addEventListener('mouseenter', function (evt) { Input.onMouseMove(x, y); }); - e.addEventListener('mousedown', function (evt) { + cOuter.addEventListener('mousedown', function (evt) { Input.onMouseDown(x, y, evt.button+1); }); - e.addEventListener('mouseup', function (evt) { + cOuter.addEventListener('mouseup', function (evt) { Input.onMouseUp(x, y, evt.button+1); }); - e.addEventListener('contextmenu', function (evt) { + cOuter.addEventListener('contextmenu', function (evt) { evt.preventDefault(); }); - e.addEventListener('mousewheel', function (evt) { + cOuter.addEventListener('mousewheel', function (evt) { Input.onMouseWheel(x, y, evt.deltaY>0?1:-1); return false; }); @@ -179,17 +147,19 @@ var Screen = (function () { /* End of line */ if ((i > 0) && (i % W == 0)) { - scr.appendChild(mk('br')); + screenDiv.appendChild(mk('br')); } /* The cell */ - scr.appendChild(e); + cOuter.appendChild(cInner); + screenDiv.appendChild(cOuter); cell = { t: ' ', fg: 7, bg: 0, // the colors will be replaced immediately as we receive data (user won't see this) attrs: 0, - e: e, + elem: cOuter, + slot: cInner, x: i % W, y: Math.floor(i / W), }; @@ -204,7 +174,6 @@ var Screen = (function () { clearInterval(blinkIval); blinkIval = setInterval(function () { cursor.a = !cursor.a; - // TODO try to invent a new way to indicate "hanging" - this is copied from gtkterm if (cursor.hidden || cursor.hanging) { cursor.a = false; } @@ -214,7 +183,7 @@ var Screen = (function () { } }, 500); - // blink attribute + /* blink attribute animation */ setInterval(function () { $('#screen').removeClass('blink-hide'); setTimeout(function () { @@ -225,11 +194,13 @@ var Screen = (function () { inited = true; } + // constants for decoding the update blob var SEQ_SET_COLOR_ATTR = 1; var SEQ_REPEAT = 2; var SEQ_SET_COLOR = 3; var SEQ_SET_ATTR = 4; + /** Parse received screen update object (leading S removed already) */ function _load_content(str) { var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, attrs, cell; @@ -253,17 +224,30 @@ var Screen = (function () { // console.log("Cursor at ",num, num2); // Attributes - num = parse2B(str, i); i += 2; // fg bg bold hidden - cursor.hidden = !(num & 0x0001); - cursor.hanging = !!(num & 0x0002); + num = parse2B(str, i); i += 2; // fg bg attribs + cursor.hidden = !(num & (1<<0)); // DEC opt "visible" + cursor.hanging = !!(num & (1<<1)); // console.log("Attributes word ",num.toString(16)+'h'); Input.setAlts( - !!(num & 0x0004), // cu - !!(num & 0x0008), // np - !!(num & 0x0010) // fn + !!(num & (1<<2)), // cursors alt + !!(num & (1<<3)), // numpad alt + !!(num & (1<<4)) // fn keys alt ); + var mt_click = !!(num & (1<<5)); + var mt_move = !!(num & (1<<6)); + Input.setMouseMode( + mt_click, + mt_move + ); + $('#screen').toggleClass('noselect', mt_move); + + var show_buttons = !!(num & (1<<7)); + var show_config_links = !!(num & (1<<8)); + $('.x-term-conf-btn').toggleClass('hidden', !show_config_links); + $('#action-buttons').toggleClass('hidden', !show_buttons); + fg = 7; bg = 0; attrs = 0; @@ -326,10 +310,11 @@ var Screen = (function () { } } + /** Apply labels to buttons and screen title (leading T removed already) */ function _load_labels(str) { var pieces = str.split('\x01'); qs('h1').textContent = pieces[0]; - qsa('#buttons button').forEach(function(x, i) { + qsa('#action-buttons button').forEach(function(x, i) { var s = pieces[i+1].trim(); // if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically x.innerHTML = s.length > 0 ? e(s) : " "; @@ -337,8 +322,8 @@ var Screen = (function () { }); } - function _beep() - { + /** Audible beep for ASCII 7 */ + function _beep() { var osc, gain; if (!audioCtx) return; @@ -380,6 +365,7 @@ var Screen = (function () { break; default: console.warn("Bad data message type, ignoring."); + console.log(str); } } @@ -505,24 +491,31 @@ var Input = (function() { np_alt: false, cu_alt: false, fn_alt: false, + mt_click: false, + mt_move: false, }; + /** Send a literal message */ function sendStrMsg(str) { Conn.send("s"+str); } + /** Send a button event */ function sendBtnMsg(n) { Conn.send("b"+Chr(n)); } + /** Fn alt choice for key message */ function fa(alt, normal) { return opts.fn_alt ? alt : normal; } + /** Cursor alt choice for key message */ function ca(alt, normal) { return opts.cu_alt ? alt : normal; } + /** Numpad alt choice for key message */ function na(alt, normal) { return opts.np_alt ? alt : normal; } @@ -593,6 +586,7 @@ var Input = (function() { } } + /** Bind a keystroke to message */ function bind(combo, str) { // mac fix - allow also cmd if (combo.indexOf('ctrl+') !== -1) { @@ -608,6 +602,7 @@ var Input = (function() { }); } + /** Bind/rebind key messages */ function _initKeys() { // This takes care of text characters typed window.addEventListener('keypress', function(evt) { @@ -633,10 +628,12 @@ var Input = (function() { _bindFnKeys(); } + // mouse button states var mb1 = 0; var mb2 = 0; var mb3 = 0; + /** Init the Input module */ function init() { _initKeys(); @@ -647,6 +644,7 @@ var Input = (function() { }); }); + // global mouse state tracking - for motion reporting window.addEventListener('mousedown', function(evt) { if (evt.button == 0) mb1 = 1; if (evt.button == 1) mb2 = 1; @@ -660,6 +658,7 @@ var Input = (function() { }); } + /** Prepare modifiers byte for mouse message */ function packModifiersForMouse() { return (key.isModifier('ctrl')?1:0) | (key.isModifier('shift')?2:0) | @@ -668,9 +667,13 @@ var Input = (function() { } return { + /** Init the Input module */ init: init, - // onTap: sendPosMsg, + + /** Send a literal string message */ sendString: sendStrMsg, + + /** Enable alternate key modes (cursors, numpad, fn) */ setAlts: function(cu, np, fn) { if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { opts.cu_alt = cu; @@ -681,34 +684,46 @@ var Input = (function() { _bindFnKeys(); } }, + + setMouseMode: function(click, move) { + opts.mt_click = click; + opts.mt_move = move; + }, + + // Mouse events onMouseMove: function (x, y) { + if (!opts.mt_move) return; var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0; var m = packModifiersForMouse(); Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); }, onMouseDown: function (x, y, b) { + if (!opts.mt_click) return; if (b > 3 || b < 1) return; var m = packModifiersForMouse(); Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, onMouseUp: function (x, y, b) { + if (!opts.mt_click) return; if (b > 3 || b < 1) return; var m = packModifiersForMouse(); Conn.send("r" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, onMouseWheel: function (x, y, dir) { + if (!opts.mt_click) return; // -1 ... btn 4 (away from user) // +1 ... btn 5 (towards user) var m = packModifiersForMouse(); var b = (dir < 0 ? 4 : 5); Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m)); - console.log("B ",b," M ",m); + // console.log("B ",b," M ",m); }, }; })(); +/** Init the terminal sub-module - called from HTML */ window.termInit = function () { Conn.init(); Input.init(); diff --git a/html_orig/jssrc/utils.js b/html_orig/jssrc/utils.js index 6fa4b7d..dd1cd07 100755 --- a/html_orig/jssrc/utils.js +++ b/html_orig/jssrc/utils.js @@ -121,3 +121,38 @@ function jsp() { return null; } } + +/** Decode two-byte number */ +function parse2B(s, i) { + return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127; +} + +/** Decode three-byte number */ +function parse3B(s, i) { + return (s.charCodeAt(i) - 1) + (s.charCodeAt(i+1) - 1) * 127 + (s.charCodeAt(i+2) - 1) * 127 * 127; +} + +function Chr(n) { + return String.fromCharCode(n); +} + +function encode2B(n) { + var lsb, msb; + lsb = (n % 127); + n = ((n - lsb) / 127); + lsb += 1; + msb = (n + 1); + return Chr(lsb) + Chr(msb); +} + +function encode3B(n) { + var lsb, msb, xsb; + lsb = (n % 127); + n = (n - lsb) / 127; + lsb += 1; + msb = (n % 127); + n = (n - msb) / 127; + msb += 1; + xsb = (n + 1); + return Chr(lsb) + Chr(msb) + Chr(xsb); +} diff --git a/html_orig/jssrc/wifi.js b/html_orig/jssrc/wifi.js index 71fb574..8ab541b 100644 --- a/html_orig/jssrc/wifi.js +++ b/html_orig/jssrc/wifi.js @@ -17,7 +17,6 @@ $('#sta-nw .essid').html(e(name)); var nopw = undef(password) || password.length == 0; - $('#sta-nw .x-passwd').html(e(password)); $('#sta-nw .passwd').toggleClass('hidden', nopw); $('#sta-nw .nopasswd').toggleClass('hidden', !nopw); $('#sta-nw .ip').html(ip.length>0 ? tr('wifi.connected_ip_is')+ip : tr('wifi.not_conn')); diff --git a/html_orig/lang/en.php b/html_orig/lang/en.php index bd0d117..7836b0a 100644 --- a/html_orig/lang/en.php +++ b/html_orig/lang/en.php @@ -28,11 +28,15 @@ return [ 'net.details' => 'MAC addresses', 'term.defaults' => 'Initial Settings', + 'term.expert' => 'Expert Options', 'term.explain_initials' => ' - Those are the initial settings used after ESPTerm powers on. - The selected colors will also be used after receiving a - screen- or attributes-reset command. Those settings will be - applied immediately after saving to preview the changes live.', + Those are the initial settings used after ESPTerm powers on or when the screen + reset command is received. Some options can be changed by the application via escape sequences, + those changes won\'t be saved in Flash. + ', + 'term.explain_expert' => ' + Those are advanced config options that usually don\'t need to be changed. + Edit them only if you know what you\'re doing.', 'term.example' => 'Default colors preview', @@ -45,6 +49,8 @@ return [ 'term.display_tout_ms' => 'Redraw delay', 'term.display_cooldown_ms' => 'Redraw cooldown', 'term.fn_alt_mode' => 'SS3 Fn keys', + 'term.show_config_links' => 'Show nav links', + 'term.show_buttons' => 'Show buttons', // terminal color labels 'color.0' => 'Black', @@ -94,7 +100,7 @@ return [ 'wifi.not_conn' => 'Not connected.', 'wifi.sta_none' => 'None', - 'wifi.sta_active_pw' => '๐Ÿ”’', + 'wifi.sta_active_pw' => '๐Ÿ”’ Password saved', 'wifi.sta_active_nopw' => '๐Ÿ”“ Open access', 'wifi.connected_ip_is' => 'Connected, IP is ', 'wifi.sta_password' => 'Password:', diff --git a/html_orig/pages/_tail.php b/html_orig/pages/_tail.php index dfdca17..a450375 100644 --- a/html_orig/pages/_tail.php +++ b/html_orig/pages/_tail.php @@ -1,4 +1,8 @@ + +
+ + diff --git a/html_orig/pages/cfg_term.php b/html_orig/pages/cfg_term.php index 68cf2e7..1292dac 100644 --- a/html_orig/pages/cfg_term.php +++ b/html_orig/pages/cfg_term.php @@ -104,6 +104,18 @@ +
+ +
+ + +
+

+ +
+ +
+
@@ -128,8 +140,20 @@
+
+ + +
+ +
+ + +
+
- +
diff --git a/html_orig/pages/cfg_wifi.php b/html_orig/pages/cfg_wifi.php index 555ced7..804f383 100644 --- a/html_orig/pages/cfg_wifi.php +++ b/html_orig/pages/cfg_wifi.php @@ -65,7 +65,7 @@
-
 
+
diff --git a/html_orig/pages/help.php b/html_orig/pages/help.php index eaf670d..a99cd93 100644 --- a/html_orig/pages/help.php +++ b/html_orig/pages/help.php @@ -1,865 +1,20 @@ -
-

Tips & Troubleshooting

- -
- ESPTerm v2 -
    -
  • *Communication UART (Rx, Tx)* can be configured in the System Settings. - -
  • *Boot log and debug messages* are available on pin *GPIO2* (P2) at 115200\,baud, 1 stop bit, no parity. - Those messages may be disabled through compile flags. - -
  • *Loopback test*: Connect the Rx and Tx pins with a piece of wire. Anything you type in the browser should - appear on the screen. Set _Parser Timeout = 0_ in Terminal Settings - to be able to manually enter escape sequences. - -
  • There is very little RAM available to the webserver, and it can support at most 4 connections at the same time. - Each terminal session (open window with the terminal screen) uses one persistent connection for screen updates. - *Avoid leaving unused windows open*, or either the RAM or connections may be exhausted. - -
  • *For best performance*, use the module in Client mode (connected to external network) and minimize the number - of simultaneous connections. Enabling AP consumes extra RAM because the DHCP server and Captive Portal - DNS server are started. - -
  • In AP mode, *check that the WiFi channel used is clear*; interference may cause flaky connection. - A good mobile app to use for this is - WiFi Analyzer (Google Play). - Adjust the hotspot strength and range using the _Tx Power setting_. - -
  • Hold the BOOT button (GPIO0 to GND) for ~1 second to force enable AP. Hold it for ~6 seconds to restore default settings. - (This is indicated by the blue LED rapidly flashing). Default settings can be overwritten in the - System Settings. -
-
-
- -
-

Basic Intro & Nomenclature

- -
- VT102 - -

- ESPTerm emulates VT102 (pictured) with some additions from later VT models and Xterm. - All commonly used attributes and commands are supported. - ESPTerm is capable of displaying ncurses applications such as _Midnight Commander_ using _agetty_. -

- -

- ESPTerm accepts UTF-8 characters received on the communication UART and displays them on the screen, - interpreting some codes as Control Characters. Those are e.g. _Carriage Return_ (13), _Line Feed_ (10), - _Tab_ (9), _Backspace_ (8) and _Bell_ (7). -

- -

- Escape sequences start with the control character _ESC_ (27), - followed by any number of ASCII characters forming the body of the command. -

- -

Nomenclature & Command Types

- -

- Examples on this help page use the following symbols for special characters and command types:\\ - (spaces are for clarity only, _DO NOT_ include them in the commands!) -

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameSymbolASCIIC stringFunction
*ESC*`\e``ESC` (27)`"\e"`, `"\x1b"`, `"\033"`Introduces an escape sequence. _(Note: `\e` is a GCC extension)_
*Bell*`\a``BEL`~(7)`"\a"`, `"\x7"`, `"\07"`Audible beep
*String Terminator*`ST``ESC \`~(27~92)
_or_~`\a`~(7)
`"\x1b\\"`, `"\a"`Terminates a string command (`\a` can be used as an alternative)
*Control Sequence Introducer*`CSI``ESC [``"\x1b["`Starts a CSI command. Examples: `\e[?7;10h`, `\e[2J`
*Operating System Command*`OSC``ESC ]``"\x1b]"`Starts an OSC command. Is followed by a command string terminated by `ST`. Example: `\e]0;My Screen Title\a`
*Select Graphic Rendition*`SGR``CSI n;n;nm``"\x1b[1;2;3m"`Set text attributes, like color or style. 0 to 10 numbers can be used, `\e[m` is treated as `\e[0m`
-
- -

There are also some other commands that don't follow the CSI, SGR or OSC pattern, such as `\e7` or - `\e#8`. A list of the most important escape sequences is presented in the following sections.

-
-
- -
-

Screen Behavior & Refreshing

- -
-

- The initial screen size, title text and button labels can be configured in Terminal Settings. -

- -

- Screen updates are sent to the browser through a WebSocket after some time of inactivity on the communication UART - (called "Redraw Delay"). After an update is sent, at least a time of "Redraw Cooldown" must elapse before the next - update can be sent. Those delays are used is to avoid burdening the server with tiny updates during a large screen - repaint. If you experience issues (broken image due to dropped bytes), try adjusting those config options. It may also - be useful to try different baud rates. -

-
-
- -
-

Text Attributes

- -
-

- All text attributes are set using SGR commands like `\e[10;20;30m`, with up to 10 numbers separated by semicolons. - To restore all attributes to their default states, use SGR 0: `\e[0m` or `\e[m`. -

- -

Those are the supported text attributes SGR codes:

- - - - - - - - - - - - - -
StyleEnableDisable
Bold121, 22
Faint222
Italic323
Underlined424
Blink525
Inverse727
Striked929
๐”‰๐”ฏ๐”ž๐”จ๐”ฑ๐”ฒ๐”ฏ2023
-
-
- -
-

Colors

- -
-

- Colors are set using SGR commands (like `\e[10;20;30m`). The following tables list the SGR codes to use. - Selected colors are used for any new text entered, as well as for empty space when using line and screen clearing commands. - The configured default colors can be restored using SGR 39 for foreground and SGR 49 for background. -

- -

- The actual color representation depends on a color theme which - can be selected in Terminal Settings. -

- -

Foreground colors

- -
- 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 -
- -
- 90 - 91 - 92 - 93 - 94 - 95 - 96 - 97 -
- -

Background colors

- -
- 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 -
- -
- 100 - 101 - 102 - 103 - 104 - 105 - 106 - 107 -
-
-
- -
-

User Input: Keyboard, Mouse

- -
-

Keyboard

- -

- The user can input text using their keyboard, or on Android, using the on-screen keyboard which is open using - a button beneath the screen. Supported are all printable characters, as well as many control keys, such as arrows, _Ctrl+letters_ - and function keys. Sequences sent by function keys are based on VT102 and Xterm. -

- -

- The codes sent by _Home_, _End_, _F1-F4_ and cursor keys are affected by various keyboard modes (_Application Cursor Keys_, - _Application Numpad Mode_, _SS3 Fn Keys Mode_). - Some can be set in the Terminal Settings, others via commands. -

- -

- Here are some examples of control key codes: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyCodeKeyCode
Up`\e[A`F1`\eOP`
Down`\e[B`F2`\eOQ`
Right`\e[C`F3`\eOR`
Left`\e[D`F4`\eOS`
Home`\eOH`F5`\e[15~`
End`\eOF`F6`\e[17~`
Insert`\e[2~`F7`\e[18~`
Delete`\e[3~`F8`\e[19~`
Page Up`\e[5~`F9`\e[20~`
Page Down`\e[6~`F10`\e[21~`
Enter`\r` (13)F11`\e[23~`
Ctrl+Enter`\n` (10)F12`\e[24~`
Tab`\t` (9)ESC`\e` (27)
Backspace`\b` (8)Ctrl+A..ZASCII 1-26
- -

Action buttons

- -

- The blue buttons under the screen send ASCII codes 1, 2, 3, 4, 5, which incidentally - correspond to _Ctrl+A,B,C,D,E_. This choice was made to make button press parsing as simple as possible. -

- -

Mouse

- -

- ESPTerm implements standard mouse tracking modes based on Xterm. Mouse tracking can be used to implement - powerful user interactions such as on-screen buttons, draggable sliders or dials, menus etc. ESPTerm's - mouse tracking was tested using VTTest and should be compatible with all terminal applications - that request mouse tracking. -

- -

- Mouse can be tracked in different ways; some are easier to parse, others more powerful. The coordinates - can also be encoded in different ways. All mouse tracking options are set using option commands: - `CSI ? _n_ h` to enable, `CSI ? _n_ l` to disable option _n_. -

- -

Mouse Tracking Modes

- -

- All tracking modes produce three numbers which are then encoded and send to the application. - First is the _event number_ N, then the _X and Y coordinates_, 1-based. -

- -

- Mouse buttons are numbered: 1=left, 2=middle, 3=right. - Wheel works as two buttons (4 and 5) which generate only press events (no release). -

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionNameDescription
`9`*X10~mode* - This is the most basic tracking mode, in which only button presses are reported. - N = button - 1: (0 left, 1 middle, 2 right, 3, 4 wheel). -
`1000`*Normal~mode* - In Normal mode, both button presses and releases are reported. - The lower two bits of N indicate the button pressed: - `00b` (0) left, `01b` (1) middle, `10b` (2) right, `11b` (3) button release. - Wheel buttons are reported as 0 and 1 with added 64 (e.g. 64 and 65). - Normal mode also supports tracking of modifier keys, which are added to N as bit masks: - 4=_Shift_, 8=_Meta/Alt_, 16=_Control/Cmd_. Example: middle button with _Shift_ = 1 + 4 = `101b` (5). -
`1002`*Button-Event tracking* - This is similar to Normal mode (`1000`), but mouse motion with a button held is also reported. - A motion event is generated when the mouse cursor moves between screen character cells. - A motion event has the same N as a press event, but 32 is added. - For example, drag-drop event with the middle button will produce N = 1 (press), 33 (dragging) and 3 (release). -
`1003`*Any-Event tracking* - This mode is almost identical to Button Event tracking (1002), but motion events - are sent even when no mouse buttons are held. This could be used to draw on-screen mouse cursor, for example. - Motion events with no buttons will use N = 32 + _11b_ (35). -
`1004`*Focus~tracking* - Focus tracking is a separate function from the other mouse tracking modes, therefore they can be enabled together. - Focus tracking reports when the terminal window (in Xterm) gets or loses focus, or in ESPTerm's case, when any - user is connected. This can be used to pause/resume a game or on-screen animations. - Focus tracking mode sends `CSI I` when the terminal receives, and `CSI O` when it loses focus. -
-
- -

Mouse Report Encoding

- -

- The following encoding schemes can be used with any of the tracking modes (except Focus tracking, which is not affected). -

- -
- - - - - - - - - - - - - - - - - - - - - - -
OptionNameDescription
--*Normal~encoding* - This is the default encoding scheme used when no other option is selected. - In this mode, a mouse report has the format `CSI M _n_ _x_ _y_`, - where _n_, _x_ and _y_ are characters with ASCII value = 32 (space) + the respective number, e.g. - 0 becomes 32 (space), 1 becomes 33 (!). The reason for adding 32 is to avoid producing control characters. - Example: `\e[M !!` - left button press at coordinates 1,1 when using X10 mode. -
`1005`*UTF-8~encoding* - This scheme should encode each of the numbers as a UTF-8 code point, expanding the maximum possible value. - Since ESPTerm's screen size is limited and this has no practical benefit, this serves simply as an alias - to the normal scheme. -
`1006`*SGR~encoding* - In SGR encoding, the response looks like a SGR sequence with the three numbers as semicolon-separated - ASCII values. In this case 32 is not added like in the Normal and UTF-8 schemes, because - it would serve nor purpose here. Also, button release is not reported as 11b, - but using the normal button code while changing the final SGR character: `M` for button press - and `m` for button release. Example: `\e[2;80;24m` - the right button was released - at row 80, column 24. -
`1015`*URXVT~encoding* - This is similar to SGR encoding, but the final character is always `M` and the numbers are - like in the Normal scheme, with 32 added. This scheme has no real advantage over the previous schemes and - was added solely for completeness. -
-
-
-
- -
-

Cursor Commands

- -
-

- The coordinates are 1-based, origin is top left. The cursor can move within the entire screen, - or in the active Scrolling Region if Origin Mode is enabled. -

- -

After writing a character, the cursor advances to the right. If it has reached the end of the row, - it stays on the same line, but writing the next character makes it jump to the start of the next - line first, scrolling up if needed. If Auto-wrap mode is disabled, the cursor never wraps or scrolls - the screen. -

- -

- *Legend:* - Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon. - If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command. -

- -

Movement

- - - - - - - - - - - - - - - - - - - - - -
CodeMeaning
- - \e[nA \\ - \e[nB \\ - \e[nC \\ - \e[nD - - Move cursor up (`A`), down (`B`), right (`C`), left (`D`)
- - \e[nF \\ - \e[nE - - Go _n_ lines up (`F`) or down (`E`), start of line
- - \e[rd \\ - \e[cG \\ - \e[r;cH - - - Go to absolute position - row (`d`), column (`G`), or both (`H`). Use `\e[H` to go to 1,1. -
- `\e[6n` - - Query cursor position. Sent back as `\e[r;cR`. -
- -

Save / restore

- - - - - - - - - - - - - -
CodeMeaning
- - \e[s \\ - \e[u - - Save (`s`) or restore (`u`) cursor position
- - \e7 \\ - \e8 - - Save (`7`) or restore (`8`) cursor position and attributes
- -

Scrolling Region

- - - - - - - - - - - - - - - - - -
CodeMeaning
- `\e[a;br` - - Set scrolling region to rows _a_ through _b_ and go to 1,1. By default, the - scrolling region spans the entire screen height. The cursor can leave the region using - absolute position commands, unless Origin Mode (see below) is active. -
- - \e[?6h \\ - \e[?6l - - - Enable (`h`) or disable (`l`) Origin Mode and go to 1,1. In Origin Mode, all coordinates - are relative to the Scrolling Region and the cursor can't leave the region. -
- - \e[nS \\ - \e[nT - - - Move contents of the Scrolling Region up (`S`) or down (`T`), pad with empty - lines of the current background color. -
- -

Tab stops

- - - - - - - - - - - - - - - - - -
CodeMeaning
- `\eH` - - Set tab stop at the current column. There are, by default, tabs every 8 columns. -
- - \e[nI \\ - \e[nZ - - Advance (`I`) or go back (`Z`) _n_ tab stops or end/start of line. ASCII _TAB_ (9) is equivalent to \e[1I
- - \e[0g \\ - \e[3g \\ - - Clear tab stop at the current column (`0`), or all columns (`3`).
- -

Other options

- - - - - - - - - - - - - -
CodeMeaning
- - \e[?7h \\ - \e[?7l - - Enable (`h`) or disable (`l`) cursor auto-wrap and screen auto-scroll
- - \e[?25h \\ - \e[?25l - - Show (`h`) or hide (`l`) the cursor
-
-
- -
-

Screen Content Manipulation

- -
-

- Legend: - Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon. - If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command. -

- - - - - - - - - - - - - - - - - - - - - - - - - -
CodeMeaning
- `\e[mJ` - - Clear part of screen. _m_: 0 - from cursor, 1 - to cursor, 2 - all -
- `\e[mK` - - Erase part of line. _m_: 0 - from cursor, 1 - to cursor, 2 - all -
- `\e[nX` - Erase _n_ characters in line. -
- - \e[nL \\ - \e[nM - - - Insert (`L`) or delete (`M`) _n_ lines. Following lines are pulled up or pushed down. -
- - \e[n@ \\ - \e[nP - - - Insert (`@`) or delete (`P`) _n_ characters. The rest of the line is pulled left or pushed right. - Characters going past the end of line are lost. -
-
-
- -
-

Alternate Character Sets

- -
-

- ESPTerm implements Alternate Character Sets as a way to print box drawing characters - and special symbols. A character set can change what each received ASCII character - is printed as on the screen (eg. "{" is "ฯ€" in codepage `0`). The implementation is based - on the original VT devices. - Since ESPTerm also fully supports UTF-8, you can probably ignore this feature and use - Unicode directly. It's added for compatibility with some programs that use this. -

- -

The following codepages are implemented:

- -
    -
  • `B` - US ASCII (default)
  • -
  • `A` - UK ASCII: # replaced with ยฃ
  • -
  • `0` - Symbols and basic line drawing (standard DEC alternate character set)
  • -
  • `1` - Symbols and advanced line drawing (based on DOS codepage 437)
  • -
- -

To see what character maps to which symbol, look in the source code or try it. All codepages use codes 32-127, 32 being space.

- -

- There are two character set slots, G0 and G1. - Those slots are selected as active using ASCII codes Shift In and Shift Out (those originally served for shifting - a red-black typewriter tape). Each slot (G0 and G1) can have a different codepage assigned. G0 and G1 and the active slot number are - saved and restored with the cursor and cleared with a screen reset (\ec). -

- -

The following commands are used:

- - - - - - - - - - - - - - - - - - - - -
CodeMeaning
`\e(x`Set G0 = codepage x
`\e)x`Set G1 = codepage x
_SO_ (14)Activate G0
_SI_ (15)Activate G1
-
-
- -
-

System Commands

- -
-

- It's possible to dynamically change the screen title text and action button labels. - Setting an empty label to a button makes it look disabled. The buttons send ASCII 1-5 when clicked. - Those changes are not retained after restart. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CodeMeaning
`\ec` - Clear screen, reset attributes and cursor. - The screen size, title and button labels remain unchanged. -
`\e[5n` - Query device status, ESPTerm replies with `\e[0n` "device is OK". - Can be used to check if the terminal has booted up and is ready to receive commands. -
_CAN_ (24) - This ASCII code is not a command, but is sent by ESPTerm when it becomes ready to receive commands. - When this code is received on the UART, it means ESPTerm has restarted and is ready. Use this to detect - spontaneous restarts which require a full screen repaint. -
`\e]0;title\a`Set screen title (this is a standard OSC command)
- - \e]81;btn1\a \\ - \e]82;btn2\a \\ - \e]83;btn3\a \\ - \e]84;btn4\a \\ - \e]85;btn5\a \\ - - - Set button 1-5 label - eg.`\e]81;Yes\a` - sets the first button text to "Yes". -
`\e[8;r;ct`Set screen size (this is a command borrowed from xterm)
-
-
+
+ Expand all | Collapse all +
+ + + + + + + + + + + + + diff --git a/html_orig/pages/help/charsets.php b/html_orig/pages/help/charsets.php new file mode 100644 index 0000000..c21b1dc --- /dev/null +++ b/html_orig/pages/help/charsets.php @@ -0,0 +1,80 @@ +
+

Alternate Character Sets

+ +
+

+ ESPTerm implements Alternate Character Sets as a way to print box drawing characters + and special symbols. A character set can change what each received ASCII character + is printed as on the screen (eg. "{" is "ฯ€" in codepage `0`). The implementation is based + on the original VT devices. +

+ +

+ Since ESPTerm also supports UTF-8, this feature is the most useful for applications + which can't print UTF-8 or already use alternate character sets for historical reasons. +

+ +

Supported codepages

+ +
    +
  • `B` - US ASCII (default)
  • +
  • `A` - UK ASCII: # replaced with ยฃ
  • +
  • `0` - Symbols and basic line drawing (standard DEC alternate character set)
  • +
  • `1` - Symbols and advanced line drawing (based on DOS codepage 437, ESPTerm specific)
  • +
+ +

+ All codepages use codes 32-127, 32 being space. A character with no entry in the active codepage + stays unchanged. +

+ + $cp) { + echo "

Codepage `$name`

\n"; + echo '
'; + foreach($cp as $point) { + $dis = $point[1]==$point[2]?' class="none"' : ''; + echo "$point[0]$point[1]$point[2]
"; + } + echo '
'; + } + ?> + +

Switching commands

+ +

+ There are two character set slots, G0 and G1. + Those slots are selected as active using ASCII codes Shift In and Shift Out (those originally served for shifting + a red-black typewriter tape). Often only G0 is used for simplicity. +

+ +

+ Each slot (G0 and G1) can have a different codepage assigned. G0 and G1 and the active slot number are + saved and restored with the cursor and cleared with a screen reset (\ec). +

+ +

The following commands are used:

+ + + + + + + + + + + + + + + + + + + + +
CodeMeaning
`\e(x`Set G0 = codepage x
`\e)x`Set G1 = codepage x
_SO_ (14)Activate G0
_SI_ (15)Activate G1
+
+
diff --git a/html_orig/pages/help/cmd_cursor.php b/html_orig/pages/help/cmd_cursor.php new file mode 100644 index 0000000..4dd0d13 --- /dev/null +++ b/html_orig/pages/help/cmd_cursor.php @@ -0,0 +1,199 @@ +
+

Commands: Cursor Functions

+ +
+

+ The coordinates are 1-based, origin is top left. The cursor can move within the entire screen, + or in the active Scrolling Region if Origin Mode is enabled. +

+ +

After writing a character, the cursor advances to the right. If it has reached the end of the row, + it stays on the same line, but writing the next character makes it jump to the start of the next + line first, scrolling up if needed. If Auto-wrap mode is disabled, the cursor never wraps or scrolls + the screen. +

+ +

+ *Legend:* + Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon. + If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command. +

+ +

Movement

+ + + + + + + + + + + + + + + + + + + + + +
CodeMeaning
+ + \e[nA \\ + \e[nB \\ + \e[nC \\ + \e[nD + + Move cursor up (`A`), down (`B`), right (`C`), left (`D`)
+ + \e[nF \\ + \e[nE + + Go _n_ lines up (`F`) or down (`E`), start of line
+ + \e[rd \\ + \e[cG \\ + \e[r;cH + + + Go to absolute position - row (`d`), column (`G`), or both (`H`). Use `\e[H` to go to 1,1. +
+ `\e[6n` + + Query cursor position. Sent back as `\e[r;cR`. +
+ +

Save / restore

+ + + + + + + + + + + + + +
CodeMeaning
+ + \e[s \\ + \e[u + + Save (`s`) or restore (`u`) cursor position
+ + \e7 \\ + \e8 + + Save (`7`) or restore (`8`) cursor position and attributes
+ +

Scrolling Region

+ + + + + + + + + + + + + + + + + +
CodeMeaning
+ `\e[a;br` + + Set scrolling region to rows _a_ through _b_ and go to 1,1. By default, the + scrolling region spans the entire screen height. The cursor can leave the region using + absolute position commands, unless Origin Mode (see below) is active. +
+ + \e[?6h \\ + \e[?6l + + + Enable (`h`) or disable (`l`) Origin Mode and go to 1,1. In Origin Mode, all coordinates + are relative to the Scrolling Region and the cursor can't leave the region. +
+ + \e[nS \\ + \e[nT + + + Move contents of the Scrolling Region up (`S`) or down (`T`), pad with empty + lines of the current background color. This is similar to what happens when AutoWrap + is enabled and some text is printed at the very end of the screen. +
+ +

Tab stops

+ + + + + + + + + + + + + + + + + +
CodeMeaning
+ `\eH` + + Set tab stop at the current column. There are, by default, tabs every 8 columns. +
+ + \e[nI \\ + \e[nZ + + Advance (`I`) or go back (`Z`) _n_ tab stops or end/start of line. ASCII _TAB_ (9) is equivalent to \e[1I
+ + \e[0g \\ + \e[3g \\ + + Clear tab stop at the current column (`0`), or all columns (`3`).
+ +

Other options

+ + + + + + + + + + + + + +
CodeMeaning
+ + \e[?7h \\ + \e[?7l + + Enable (`h`) or disable (`l`) cursor auto-wrap and screen auto-scroll
+ + \e[?25h \\ + \e[?25l + + Show (`h`) or hide (`l`) the cursor
+
+
diff --git a/html_orig/pages/help/cmd_screen.php b/html_orig/pages/help/cmd_screen.php new file mode 100644 index 0000000..948b8a8 --- /dev/null +++ b/html_orig/pages/help/cmd_screen.php @@ -0,0 +1,63 @@ +
+

Commands: Screen Functions

+ +
+

+ Legend: + Italic letters such as _n_ are ASCII numbers that serve as arguments, separated with a semicolon. + If an argument is left out, it's treated as 0 or 1, depending on what makes sense for the command. +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
CodeMeaning
+ `\e[mJ` + + Clear part of screen. _m_: 0 - from cursor, 1 - to cursor, 2 - all +
+ `\e[mK` + + Erase part of line. _m_: 0 - from cursor, 1 - to cursor, 2 - all +
+ `\e[nX` + Erase _n_ characters in line. +
+ + \e[nL \\ + \e[nM + + + Insert (`L`) or delete (`M`) _n_ lines. Following lines are pulled up or pushed down. +
+ + \e[n@ \\ + \e[nP + + + Insert (`@`) or delete (`P`) _n_ characters. The rest of the line is pulled left or pushed right. + Characters going past the end of line are lost. +
+
+
diff --git a/html_orig/pages/help/cmd_system.php b/html_orig/pages/help/cmd_system.php new file mode 100644 index 0000000..a03fbe6 --- /dev/null +++ b/html_orig/pages/help/cmd_system.php @@ -0,0 +1,84 @@ +
+

Commands: System Functions

+ +
+

+ It's possible to dynamically change the screen title text and action button labels. + Setting an empty label to a button makes it look disabled. The buttons send ASCII 1-5 when clicked. + Those changes are not retained after restart. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CodeMeaning
`\ec` + Clear screen, reset attributes and cursor. + The screen size, title and button labels remain unchanged. +
`\e[5n` + Query device status, ESPTerm replies with `\e[0n` "device is OK". + Can be used to check if the terminal has booted up and is ready to receive commands. +
_CAN_ (24) + This ASCII code is not a command, but is sent by ESPTerm when it becomes ready to receive commands. + When this code is received on the UART, it means ESPTerm has restarted and is ready. Use this to detect + spontaneous restarts which require a full screen repaint. +
`\e]0;title\a`Set screen title (this is a standard OSC command)
+ + \e]81;btn1\a \\ + \e]82;btn2\a \\ + \e]83;btn3\a \\ + \e]84;btn4\a \\ + \e]85;btn5\a \\ + + + Set button 1-5 label - eg.`\e]81;Yes\a` + sets the first button text to "Yes". +
+ + \e[?800h \\ + \e[?800l + + + Show (`h`) or hide (`l`) action buttons (the blue buttons under the screen). +
+ + \e[?801h \\ + \e[?801l + + + Show (`h`) or hide (`l`) menu/help links under the screen. +
`\e[8;r;ct`Set screen size (this is a command borrowed from xterm)
+
+
diff --git a/html_orig/pages/help/input.php b/html_orig/pages/help/input.php new file mode 100644 index 0000000..d4fcdd4 --- /dev/null +++ b/html_orig/pages/help/input.php @@ -0,0 +1,254 @@ + +
+

User Input: Keyboard, Mouse

+ +
+

Keyboard

+ +

+ The user can input text using their keyboard, or on Android, using the on-screen keyboard which is open using + a button beneath the screen. Supported are all printable characters, as well as many control keys, such as arrows, _Ctrl+letters_ + and function keys. Sequences sent by function keys are based on VT102 and Xterm. +

+ +

+ The codes sent by _Home_, _End_, _F1-F4_ and cursor keys are affected by various keyboard modes (_Application Cursor Keys_, + _Application Numpad Mode_, _SS3 Fn Keys Mode_). Some can be set in the Terminal Settings, + others via commands. +

+ +

+ Here are some examples of control key codes: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyCodeKeyCode
Up`\e[A`,~`\eOA`F1`\eOP`,~`\e[11\~`
Down`\e[B`,~`\eOB`F2`\eOQ`,~`\e[12\~`
Right`\e[C`,~`\eOC`F3`\eOR`,~`\e[13\~`
Left`\e[D`,~`\eOD`F4`\eOS`,~`\e[14\~`
Home`\eOH`,~`\e[H`,~`\e[1\~`F5`\e[15~`
End`\eOF`,~`\e[F`,~`\e[4\~`F6`\e[17\~`
Insert`\e[2\~`F7`\e[18\~`
Delete`\e[3\~`F8`\e[19\~`
Page Up`\e[5\~`F9`\e[20\~`
Page Down`\e[6\~`F10`\e[21\~`
Enter`\r` (13)F11`\e[23\~`
Ctrl+Enter`\n` (10)F12`\e[24\~`
Tab`\t` (9)ESC`\e` (27)
Backspace`\b` (8)Ctrl+A..ZASCII 1-26
+ +

Action buttons

+ +

+ The blue buttons under the screen send ASCII codes 1, 2, 3, 4, 5, which incidentally + correspond to _Ctrl+A,B,C,D,E_. This choice was made to make button press parsing as simple as possible. +

+ +

Mouse

+ +

+ ESPTerm implements standard mouse tracking modes based on Xterm. Mouse tracking can be used to implement + powerful user interactions such as on-screen buttons, draggable sliders or dials, menus etc. ESPTerm's + mouse tracking was tested using VTTest and should be compatible with all terminal applications + that request mouse tracking. +

+ +

+ Mouse can be tracked in different ways; some are easier to parse, others more powerful. The coordinates + can also be encoded in different ways. All mouse tracking options are set using option commands: + `CSI ? _n_ h` to enable, `CSI ? _n_ l` to disable option _n_. +

+ +

Mouse Tracking Modes

+ +

+ All tracking modes produce three numbers which are then encoded and send to the application. + First is the _event number_ N, then the _X and Y coordinates_, 1-based. +

+ +

+ Mouse buttons are numbered: 1=left, 2=middle, 3=right. + Wheel works as two buttons (4 and 5) which generate only press events (no release). +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionNameDescription
`9`*X10~mode* + This is the most basic tracking mode, in which only button presses are reported. + N = button - 1: (0 left, 1 middle, 2 right, 3, 4 wheel). +
`1000`*Normal~mode* + In Normal mode, both button presses and releases are reported. + The lower two bits of N indicate the button pressed: + `00b` (0) left, `01b` (1) middle, `10b` (2) right, `11b` (3) button release. + Wheel buttons are reported as 0 and 1 with added 64 (e.g. 64 and 65). + Normal mode also supports tracking of modifier keys, which are added to N as bit masks: + 4=_Shift_, 8=_Meta/Alt_, 16=_Control/Cmd_. Example: middle button with _Shift_ = 1 + 4 = `101b` (5). +
`1002`*Button-Event tracking* + This is similar to Normal mode (`1000`), but mouse motion with a button held is also reported. + A motion event is generated when the mouse cursor moves between screen character cells. + A motion event has the same N as a press event, but 32 is added. + For example, drag-drop event with the middle button will produce N = 1 (press), 33 (dragging) and 3 (release). +
`1003`*Any-Event tracking* + This mode is almost identical to Button Event tracking (1002), but motion events + are sent even when no mouse buttons are held. This could be used to draw on-screen mouse cursor, for example. + Motion events with no buttons will use N = 32 + _11b_ (35). +
`1004`*Focus~tracking* + Focus tracking is a separate function from the other mouse tracking modes, therefore they can be enabled together. + Focus tracking reports when the terminal window (in Xterm) gets or loses focus, or in ESPTerm's case, when any + user is connected. This can be used to pause/resume a game or on-screen animations. + Focus tracking mode sends `CSI I` when the terminal receives, and `CSI O` when it loses focus. +
+
+ +

Mouse Report Encoding

+ +

+ The following encoding schemes can be used with any of the tracking modes (except Focus tracking, which is not affected). +

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionNameDescription
--*Normal~encoding* + This is the default encoding scheme used when no other option is selected. + In this mode, a mouse report has the format `CSI M _n_ _x_ _y_`, + where _n_, _x_ and _y_ are characters with ASCII value = 32 (space) + the respective number, e.g. + 0 becomes 32 (space), 1 becomes 33 (!). The reason for adding 32 is to avoid producing control characters. + Example: `\e[M !!` - left button press at coordinates 1,1 when using X10 mode. +
`1005`*UTF-8~encoding* + This scheme should encode each of the numbers as a UTF-8 code point, expanding the maximum possible value. + Since ESPTerm's screen size is limited and this has no practical benefit, this serves simply as an alias + to the normal scheme. +
`1006`*SGR~encoding* + In SGR encoding, the response looks like a SGR sequence with the three numbers as semicolon-separated + ASCII values. In this case 32 is not added like in the Normal and UTF-8 schemes, because + it would serve nor purpose here. Also, button release is not reported as 11b, + but using the normal button code while changing the final SGR character: `M` for button press + and `m` for button release. Example: `\e[2;80;24m` - the right button was released + at row 80, column 24. +
`1015`*URXVT~encoding* + This is similar to SGR encoding, but the final character is always `M` and the numbers are + like in the Normal scheme, with 32 added. This scheme has no real advantage over the previous schemes and + was added solely for completeness. +
+
+
+
diff --git a/html_orig/pages/help/nomenclature.php b/html_orig/pages/help/nomenclature.php new file mode 100644 index 0000000..d5020a0 --- /dev/null +++ b/html_orig/pages/help/nomenclature.php @@ -0,0 +1,84 @@ +
+

Basic Intro & Nomenclature

+ +
+ VT102 + +

+ ESPTerm emulates VT102 (pictured) with some additions from later VT models and Xterm. + All commonly used attributes and commands are supported. + ESPTerm is capable of displaying ncurses applications such as _Midnight Commander_ using _agetty_. +

+ +

+ ESPTerm accepts UTF-8 characters received on the communication UART and displays them on the screen, + interpreting some codes as Control Characters. Those are e.g. _Carriage Return_ (13), _Line Feed_ (10), + _Tab_ (9), _Backspace_ (8) and _Bell_ (7). +

+ +

+ Escape sequences start with the control character _ESC_ (27), + followed by any number of ASCII characters forming the body of the command. +

+ +

Nomenclature & Command Types

+ +

+ Examples on this help page use the following symbols for special characters and command types:\\ + (spaces are for clarity only, _DO NOT_ include them in the commands!) +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameSymbolASCIIC stringFunction
*ESC*`\e``ESC` (27)`"\e"`, `"\x1b"`, `"\033"`Introduces an escape sequence. _(Note: `\e` is a GCC extension)_
*Bell*`\a``BEL`~(7)`"\a"`, `"\x7"`, `"\07"`Audible beep
*String Terminator*`ST``ESC \`~(27~92)
_or_~`\a`~(7)
`"\x1b\\"`, `"\a"`Terminates a string command (`\a` can be used as an alternative)
*Control Sequence Introducer*`CSI``ESC [``"\x1b["`Starts a CSI command. Examples: `\e[?7;10h`, `\e[2J`
*Operating System Command*`OSC``ESC ]``"\x1b]"`Starts an OSC command. Is followed by a command string terminated by `ST`. Example: `\e]0;My Screen Title\a`
*Select Graphic Rendition*`SGR``CSI n;n;nm``"\x1b[1;2;3m"`Set text attributes, like color or style. 0 to 10 numbers can be used, `\e[m` is treated as `\e[0m`
+
+ +

There are also some other commands that don't follow the CSI, SGR or OSC pattern, such as `\e7` or + `\e#8`. A list of the most important escape sequences is presented in the following sections.

+
+
diff --git a/html_orig/pages/help/screen_behavior.php b/html_orig/pages/help/screen_behavior.php new file mode 100644 index 0000000..68e3641 --- /dev/null +++ b/html_orig/pages/help/screen_behavior.php @@ -0,0 +1,17 @@ +
+

Screen Behavior & Refreshing

+ +
+

+ The initial screen size, title text and button labels can be configured in Terminal Settings. +

+ +

+ Screen updates are sent to the browser through a WebSocket after some time of inactivity on the communication UART + (called "Redraw Delay"). After an update is sent, at least a time of "Redraw Cooldown" must elapse before the next + update can be sent. Those delays are used is to avoid burdening the server with tiny updates during a large screen + repaint. If you experience issues (broken image due to dropped bytes), try adjusting those config options. It may also + be useful to try different baud rates. +

+
+
diff --git a/html_orig/pages/help/sgr_colors.php b/html_orig/pages/help/sgr_colors.php new file mode 100644 index 0000000..85a1047 --- /dev/null +++ b/html_orig/pages/help/sgr_colors.php @@ -0,0 +1,65 @@ + +
+

Commands: Color SGR

+ +
+

+ Colors are set using SGR commands (like `\e[10;20;30m`). The following tables list the SGR codes to use. + Selected colors are used for any new text entered, as well as for empty space when using line and screen clearing commands. + The configured default colors can be restored using SGR 39 for foreground and SGR 49 for background. +

+ +

+ The actual color representation depends on a color theme which + can be selected in Terminal Settings. +

+ +

Foreground colors

+ +
+ 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 +
+ +
+ 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 +
+ +

Background colors

+ +
+ 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 +
+ +
+ 100 + 101 + 102 + 103 + 104 + 105 + 106 + 107 +
+
+
diff --git a/html_orig/pages/help/sgr_styles.php b/html_orig/pages/help/sgr_styles.php new file mode 100644 index 0000000..a1e5237 --- /dev/null +++ b/html_orig/pages/help/sgr_styles.php @@ -0,0 +1,26 @@ +
+

Commands: Style SGR

+ +
+

+ All text attributes are set using SGR commands like `\e[10;20;30m`, with up to 10 numbers separated by semicolons. + To restore all attributes to their default states, use SGR 0: `\e[0m` or `\e[m`. +

+ +

Those are the supported text attributes SGR codes:

+ + + + + + + + + + + + + +
StyleEnableDisable
Bold121, 22
Faint222
Italic323
Underlined424
Blink525
Inverse727
Striked929
๐”‰๐”ฏ๐”ž๐”จ๐”ฑ๐”ฒ๐”ฏ2023
+
+
diff --git a/html_orig/pages/help/troubleshooting.php b/html_orig/pages/help/troubleshooting.php new file mode 100644 index 0000000..49173d5 --- /dev/null +++ b/html_orig/pages/help/troubleshooting.php @@ -0,0 +1,33 @@ +
+

Tips & Troubleshooting

+ +
+ +
+
diff --git a/html_orig/pages/term.php b/html_orig/pages/term.php index d81980c..4bafecd 100644 --- a/html_orig/pages/term.php +++ b/html_orig/pages/term.php @@ -8,12 +8,12 @@ }, 2000); -

+

-
+
-
+
+ -->