help page improvements, opt to hide botnav and buttons, DECOPT for those: 800 and 801, charset tables added to help page, terminal css overhaul to avoid Black Lines
This commit is contained in:
+1
-1
@@ -141,7 +141,7 @@ set(SOURCE_FILES
|
|||||||
user/apars_osc.c
|
user/apars_osc.c
|
||||||
user/apars_osc.h
|
user/apars_osc.h
|
||||||
user/apars_dcs.c
|
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(include)
|
||||||
include_directories(user)
|
include_directories(user)
|
||||||
|
|||||||
@@ -19,3 +19,8 @@ rm html/css/app.css.map
|
|||||||
|
|
||||||
cp html_orig/img/* html/img/
|
cp html_orig/img/* html/img/
|
||||||
cp html_orig/favicon.ico html/favicon.ico
|
cp html_orig/favicon.ico html/favicon.ico
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
find html/ -name "*.orig" -delete
|
||||||
|
find html/ -name "*.xcf" -delete
|
||||||
|
find html/ -name "*~" -delete
|
||||||
|
|||||||
@@ -15,10 +15,9 @@ return [
|
|||||||
'btn5' => '5',
|
'btn5' => '5',
|
||||||
'labels_seq' => 'TESPTerm local debug1235',
|
'labels_seq' => 'TESPTerm local debug1235',
|
||||||
|
|
||||||
'screenData' => 'HELLOxNRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //,
|
|
||||||
|
|
||||||
'parser_tout_ms' => 10,
|
'parser_tout_ms' => 10,
|
||||||
'display_tout_ms' => 20,
|
'display_tout_ms' => 15,
|
||||||
|
'display_cooldown_ms' => 35,
|
||||||
'fn_alt_mode' => '1',
|
'fn_alt_mode' => '1',
|
||||||
|
|
||||||
'opmode' => '2',
|
'opmode' => '2',
|
||||||
@@ -61,6 +60,8 @@ return [
|
|||||||
'term_height' => '10',
|
'term_height' => '10',
|
||||||
'default_bg' => '0',
|
'default_bg' => '0',
|
||||||
'default_fg' => '7',
|
'default_fg' => '7',
|
||||||
|
'show_buttons' => '1',
|
||||||
|
'show_config_links' => '1',
|
||||||
|
|
||||||
'uart_baud' => 115200,
|
'uart_baud' => 115200,
|
||||||
'uart_stopbits' => 1,
|
'uart_stopbits' => 1,
|
||||||
|
|||||||
@@ -69,3 +69,78 @@ function include_str($code)
|
|||||||
fclose($tmp);
|
fclose($tmp);
|
||||||
return $ret;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+69
-24
@@ -570,10 +570,13 @@ ul {
|
|||||||
#loader.show {
|
#loader.show {
|
||||||
opacity: 1; }
|
opacity: 1; }
|
||||||
|
|
||||||
|
.botpad {
|
||||||
|
display: block;
|
||||||
|
height: 5em; }
|
||||||
|
|
||||||
.Box {
|
.Box {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
line-height: 1.35em;
|
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
padding: 0.61805rem 1rem;
|
padding: 0.61805rem 1rem;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@@ -904,6 +907,7 @@ form {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin: 12px auto;
|
margin: 12px auto;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
line-height: 1.35em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center; }
|
align-items: center; }
|
||||||
@@ -1147,50 +1151,58 @@ body.term #content {
|
|||||||
@media screen and (max-width: 544px) {
|
@media screen and (max-width: 544px) {
|
||||||
body.term #content h1 {
|
body.term #content h1 {
|
||||||
font-size: 1.42383em; } }
|
font-size: 1.42383em; } }
|
||||||
body.term #screen {
|
|
||||||
-webkit-user-select: none;
|
#screen {
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 20px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background: #111213;
|
background: #111213;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 2px solid #3983CD; }
|
border: 2px solid #3983CD;
|
||||||
body.term #screen span {
|
font-size: 24px;
|
||||||
white-space: pre;
|
font-family: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace; }
|
||||||
cursor: pointer;
|
#screen span {
|
||||||
display: inline-block;
|
white-space: pre; }
|
||||||
line-height: 1.15em;
|
#screen > span {
|
||||||
width: 0.6em;
|
position: relative;
|
||||||
overflow: visible; }
|
cursor: pointer; }
|
||||||
body.term #buttons {
|
#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;
|
margin-top: 10px;
|
||||||
white-space: nowrap; }
|
white-space: nowrap; }
|
||||||
body.term #buttons button {
|
#action-buttons button {
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
padding: 8px 5px;
|
padding: 8px 5px;
|
||||||
min-width: 62px;
|
min-width: 62px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: bold; }
|
font-weight: bold; }
|
||||||
body.term #botnav {
|
|
||||||
|
#term-nav {
|
||||||
padding-top: 1.5em;
|
padding-top: 1.5em;
|
||||||
text-align: center; }
|
text-align: center; }
|
||||||
body.term #botnav a {
|
#term-nav a {
|
||||||
padding: 0 0.38198rem;
|
padding: 0 0.38198rem;
|
||||||
text-decoration: underline; }
|
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; }
|
color: #336085; }
|
||||||
body.term #botnav a:hover {
|
#term-nav a:hover {
|
||||||
color: #5abfff; }
|
color: #5abfff; }
|
||||||
body.term #botnav .icn-keyboard {
|
#term-nav .icn-keyboard {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
vertical-align: middle; }
|
vertical-align: middle; }
|
||||||
|
|
||||||
#termwrap {
|
#term-wrap {
|
||||||
text-align: center; }
|
text-align: center; }
|
||||||
|
|
||||||
#softkb-input {
|
#softkb-input {
|
||||||
@@ -1677,6 +1689,39 @@ body.term #botnav {
|
|||||||
.tscroll {
|
.tscroll {
|
||||||
overflow-x: auto; }
|
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) {
|
@media screen and (min-width: 545px) {
|
||||||
.mq-phone {
|
.mq-phone {
|
||||||
display: none !important; } }
|
display: none !important; } }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ $selected = [
|
|||||||
'wifi.connected_ip_is',
|
'wifi.connected_ip_is',
|
||||||
'wifi.not_conn',
|
'wifi.not_conn',
|
||||||
'wifi.enter_passwd',
|
'wifi.enter_passwd',
|
||||||
|
'wifi.passwd_saved',
|
||||||
];
|
];
|
||||||
|
|
||||||
$out = [];
|
$out = [];
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
+18
-29
@@ -7,46 +7,35 @@ if (!isset($_GET['page'])) $_GET['page'] = 'term';
|
|||||||
$_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME;
|
$_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME;
|
||||||
$_GET['BODYCLASS'] = $_pages[$_GET['page']]->bodyclass;
|
$_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';
|
require __DIR__ . '/pages/_head.php';
|
||||||
$_pf = __DIR__ . '/pages/'.$_GET['page'].'.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)) {
|
if (file_exists($_pf)) {
|
||||||
$f = file_get_contents($_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 "<p>NOT FOUND: $n</p>";
|
||||||
|
}
|
||||||
|
}, $f);
|
||||||
|
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
$str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php'));
|
$str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php'));
|
||||||
else $str = $f;
|
else $str = $f;
|
||||||
|
|
||||||
// special symbols
|
// special symbols
|
||||||
$str = str_replace('\,', ' ', $str);
|
$str = str_replace('\,', ' ', $str);
|
||||||
$str = preg_replace('/(?<=[^ ])~(?=[^ ])/', ' ', $str);
|
$str = preg_replace('/(?<=[^ \\\\])~(?=[^ ])/', ' ', $str);
|
||||||
$str = preg_replace('/(?<!\w)`([^ `][^`]*?[^ `]|[^ `])`(?!\w)/', '<code>$1</code>', $str);
|
$str = str_replace('\~', '~', $str);
|
||||||
$str = preg_replace('/(?<!\w)_([^ _][^_]*?[^ _]|[^ _])_(?!\w)/', '<i>$1</i>', $str);
|
$str = preg_replace('/(?<![\w\\\\])`([^ `][^`]*?[^ `]|[^ `])`(?!\w)/', '<code>$1</code>', $str);
|
||||||
$str = preg_replace('/(?<!\w)\*([^ *][^*]*?[^ *]|[^ *])\*(?!\w)/', '<b>$1</b>', $str);
|
$str = preg_replace('/(?<![\w\\\\])_([^ _][^_]*?[^ _]|[^ _])_(?!\w)/', '<i>$1</i>', $str);
|
||||||
|
$str = preg_replace('/(?<![\w\\\\])\*([^ *][^*]*?[^ *]|[^ *])\*(?!\w)/', '<b>$1</b>', $str);
|
||||||
|
|
||||||
$str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '<br>', $str);
|
$str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '<br>', $str);
|
||||||
include_str($str);
|
include_str($str);
|
||||||
|
|||||||
+140
-91
@@ -1134,6 +1134,41 @@ function jsp() {
|
|||||||
return null;
|
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 */
|
/** Module for toggling a modal overlay */
|
||||||
(function () {
|
(function () {
|
||||||
var modal = {};
|
var modal = {};
|
||||||
@@ -1423,7 +1458,6 @@ function tr(key) { return _tr[key] || '?'+key+'?'; }
|
|||||||
|
|
||||||
$('#sta-nw .essid').html(e(name));
|
$('#sta-nw .essid').html(e(name));
|
||||||
var nopw = undef(password) || password.length == 0;
|
var nopw = undef(password) || password.length == 0;
|
||||||
$('#sta-nw .x-passwd').html(e(password));
|
|
||||||
$('#sta-nw .passwd').toggleClass('hidden', nopw);
|
$('#sta-nw .passwd').toggleClass('hidden', nopw);
|
||||||
$('#sta-nw .nopasswd').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'));
|
$('#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.init = wifiInit;
|
||||||
w.startScanning = startScanning;
|
w.startScanning = startScanning;
|
||||||
})(window.WiFi = {});
|
})(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 Screen = (function () {
|
||||||
var W = 0, H = 0; // dimensions
|
var W = 0, H = 0; // dimensions
|
||||||
var inited = false;
|
var inited = false;
|
||||||
@@ -1611,15 +1610,16 @@ var Screen = (function () {
|
|||||||
bg: 0,
|
bg: 0,
|
||||||
attrs: 0,
|
attrs: 0,
|
||||||
suppress: false, // do not turn on in blink interval (for safe moving)
|
suppress: false, // do not turn on in blink interval (for safe moving)
|
||||||
forceOn: false,
|
forceOn: false, // force on unless hanging: used to keep cursor visible during move
|
||||||
hidden: false, // do not show
|
hidden: false, // do not show (DEC opt)
|
||||||
hanging: false, // xenl
|
hanging: false, // cursor at column "W+1" - not visible
|
||||||
};
|
};
|
||||||
|
|
||||||
var screen = [];
|
var screen = [];
|
||||||
var blinkIval;
|
var blinkIval;
|
||||||
var cursorFlashStartIval;
|
var cursorFlashStartIval;
|
||||||
|
|
||||||
|
// Some non-bold Fraktur symbols are outside the contiguous block
|
||||||
var frakturExceptions = {
|
var frakturExceptions = {
|
||||||
'C': '\u212d',
|
'C': '\u212d',
|
||||||
'H': '\u210c',
|
'H': '\u210c',
|
||||||
@@ -1633,7 +1633,7 @@ var Screen = (function () {
|
|||||||
try {
|
try {
|
||||||
audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)();
|
audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)();
|
||||||
} catch (er) {
|
} catch (er) {
|
||||||
console.error("Browser does not support AudioContext, can't beep.", er);
|
console.error("No AudioContext!", er);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get cell under cursor */
|
/** Get cell under cursor */
|
||||||
@@ -1653,6 +1653,22 @@ var Screen = (function () {
|
|||||||
_draw(_curCell());
|
_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) */
|
/** Update cell on display. inv = invert (for cursor) */
|
||||||
function _draw(cell, inv) {
|
function _draw(cell, inv) {
|
||||||
if (!cell) return;
|
if (!cell) return;
|
||||||
@@ -1660,44 +1676,28 @@ var Screen = (function () {
|
|||||||
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
|
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var elem = cell.e, fg, bg, cn, t;
|
var fg, bg, cn, t;
|
||||||
// Colors
|
|
||||||
fg = inv ? cell.bg : cell.fg;
|
fg = inv ? cell.bg : cell.fg;
|
||||||
bg = inv ? cell.fg : cell.bg;
|
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;
|
cn = 'fg' + fg + ' bg' + bg;
|
||||||
if (cell.attrs & (1<<0)) cn += ' bold';
|
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<<2)) cn += ' italic';
|
||||||
if (cell.attrs & (1<<3)) cn += ' under';
|
if (cell.attrs & (1<<3)) cn += ' under';
|
||||||
if (cell.attrs & (1<<4)) cn += ' blink';
|
if (cell.attrs & (1<<4)) cn += ' blink';
|
||||||
if (cell.attrs & (1<<5)) {
|
if (cell.attrs & (1<<5)) {
|
||||||
cn += ' fraktur';
|
cn += ' fraktur';
|
||||||
// perform substitution
|
t = alpha2fraktur(t);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (cell.attrs & (1<<6)) cn += ' strike';
|
if (cell.attrs & (1<<6)) cn += ' strike';
|
||||||
|
|
||||||
if (cell.attrs & (1<<1)) {
|
cell.slot.textContent = t;
|
||||||
cn += ' faint';
|
cell.elem.className = cn;
|
||||||
// faint requires special html - otherwise it would also dim the background.
|
|
||||||
// we use opacity on the text...
|
|
||||||
elem.innerHTML = '<span>' + e(elem.textContent) + '</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.className = cn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Show entire screen */
|
/** Show entire screen */
|
||||||
@@ -1712,32 +1712,34 @@ var Screen = (function () {
|
|||||||
H = rows;
|
H = rows;
|
||||||
|
|
||||||
/* Build screen & show */
|
/* Build screen & show */
|
||||||
var e, cell, scr = qs('#screen');
|
var cOuter, cInner, cell, screenDiv = qs('#screen');
|
||||||
|
|
||||||
// Empty the screen node
|
// Empty the screen node
|
||||||
while (scr.firstChild) scr.removeChild(scr.firstChild);
|
while (screenDiv.firstChild) screenDiv.removeChild(screenDiv.firstChild);
|
||||||
|
|
||||||
screen = [];
|
screen = [];
|
||||||
|
|
||||||
for(var i = 0; i < W*H; i++) {
|
for(var i = 0; i < W*H; i++) {
|
||||||
e = mk('span');
|
cOuter = mk('span');
|
||||||
|
cInner = mk('span');
|
||||||
|
|
||||||
|
/* Mouse tracking */
|
||||||
(function() {
|
(function() {
|
||||||
var x = i % W;
|
var x = i % W;
|
||||||
var y = Math.floor(i / W);
|
var y = Math.floor(i / W);
|
||||||
e.addEventListener('mouseenter', function (evt) {
|
cOuter.addEventListener('mouseenter', function (evt) {
|
||||||
Input.onMouseMove(x, y);
|
Input.onMouseMove(x, y);
|
||||||
});
|
});
|
||||||
e.addEventListener('mousedown', function (evt) {
|
cOuter.addEventListener('mousedown', function (evt) {
|
||||||
Input.onMouseDown(x, y, evt.button+1);
|
Input.onMouseDown(x, y, evt.button+1);
|
||||||
});
|
});
|
||||||
e.addEventListener('mouseup', function (evt) {
|
cOuter.addEventListener('mouseup', function (evt) {
|
||||||
Input.onMouseUp(x, y, evt.button+1);
|
Input.onMouseUp(x, y, evt.button+1);
|
||||||
});
|
});
|
||||||
e.addEventListener('contextmenu', function (evt) {
|
cOuter.addEventListener('contextmenu', function (evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
});
|
});
|
||||||
e.addEventListener('mousewheel', function (evt) {
|
cOuter.addEventListener('mousewheel', function (evt) {
|
||||||
Input.onMouseWheel(x, y, evt.deltaY>0?1:-1);
|
Input.onMouseWheel(x, y, evt.deltaY>0?1:-1);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@@ -1745,17 +1747,19 @@ var Screen = (function () {
|
|||||||
|
|
||||||
/* End of line */
|
/* End of line */
|
||||||
if ((i > 0) && (i % W == 0)) {
|
if ((i > 0) && (i % W == 0)) {
|
||||||
scr.appendChild(mk('br'));
|
screenDiv.appendChild(mk('br'));
|
||||||
}
|
}
|
||||||
/* The cell */
|
/* The cell */
|
||||||
scr.appendChild(e);
|
cOuter.appendChild(cInner);
|
||||||
|
screenDiv.appendChild(cOuter);
|
||||||
|
|
||||||
cell = {
|
cell = {
|
||||||
t: ' ',
|
t: ' ',
|
||||||
fg: 7,
|
fg: 7,
|
||||||
bg: 0, // the colors will be replaced immediately as we receive data (user won't see this)
|
bg: 0, // the colors will be replaced immediately as we receive data (user won't see this)
|
||||||
attrs: 0,
|
attrs: 0,
|
||||||
e: e,
|
elem: cOuter,
|
||||||
|
slot: cInner,
|
||||||
x: i % W,
|
x: i % W,
|
||||||
y: Math.floor(i / W),
|
y: Math.floor(i / W),
|
||||||
};
|
};
|
||||||
@@ -1770,7 +1774,6 @@ var Screen = (function () {
|
|||||||
clearInterval(blinkIval);
|
clearInterval(blinkIval);
|
||||||
blinkIval = setInterval(function () {
|
blinkIval = setInterval(function () {
|
||||||
cursor.a = !cursor.a;
|
cursor.a = !cursor.a;
|
||||||
// TODO try to invent a new way to indicate "hanging" - this is copied from gtkterm
|
|
||||||
if (cursor.hidden || cursor.hanging) {
|
if (cursor.hidden || cursor.hanging) {
|
||||||
cursor.a = false;
|
cursor.a = false;
|
||||||
}
|
}
|
||||||
@@ -1780,7 +1783,7 @@ var Screen = (function () {
|
|||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
// blink attribute
|
/* blink attribute animation */
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
$('#screen').removeClass('blink-hide');
|
$('#screen').removeClass('blink-hide');
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@@ -1791,11 +1794,13 @@ var Screen = (function () {
|
|||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constants for decoding the update blob
|
||||||
var SEQ_SET_COLOR_ATTR = 1;
|
var SEQ_SET_COLOR_ATTR = 1;
|
||||||
var SEQ_REPEAT = 2;
|
var SEQ_REPEAT = 2;
|
||||||
var SEQ_SET_COLOR = 3;
|
var SEQ_SET_COLOR = 3;
|
||||||
var SEQ_SET_ATTR = 4;
|
var SEQ_SET_ATTR = 4;
|
||||||
|
|
||||||
|
/** Parse received screen update object (leading S removed already) */
|
||||||
function _load_content(str) {
|
function _load_content(str) {
|
||||||
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, attrs, cell;
|
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);
|
// console.log("Cursor at ",num, num2);
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
num = parse2B(str, i); i += 2; // fg bg bold hidden
|
num = parse2B(str, i); i += 2; // fg bg attribs
|
||||||
cursor.hidden = !(num & 0x0001);
|
cursor.hidden = !(num & (1<<0)); // DEC opt "visible"
|
||||||
cursor.hanging = !!(num & 0x0002);
|
cursor.hanging = !!(num & (1<<1));
|
||||||
// console.log("Attributes word ",num.toString(16)+'h');
|
// console.log("Attributes word ",num.toString(16)+'h');
|
||||||
|
|
||||||
Input.setAlts(
|
Input.setAlts(
|
||||||
!!(num & 0x0004), // cu
|
!!(num & (1<<2)), // cursors alt
|
||||||
!!(num & 0x0008), // np
|
!!(num & (1<<3)), // numpad alt
|
||||||
!!(num & 0x0010) // fn
|
!!(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;
|
fg = 7;
|
||||||
bg = 0;
|
bg = 0;
|
||||||
attrs = 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) {
|
function _load_labels(str) {
|
||||||
var pieces = str.split('\x01');
|
var pieces = str.split('\x01');
|
||||||
qs('h1').textContent = pieces[0];
|
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();
|
var s = pieces[i+1].trim();
|
||||||
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
||||||
x.innerHTML = s.length > 0 ? e(s) : " ";
|
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;
|
var osc, gain;
|
||||||
if (!audioCtx) return;
|
if (!audioCtx) return;
|
||||||
|
|
||||||
@@ -1946,6 +1965,7 @@ var Screen = (function () {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn("Bad data message type, ignoring.");
|
console.warn("Bad data message type, ignoring.");
|
||||||
|
console.log(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2071,24 +2091,31 @@ var Input = (function() {
|
|||||||
np_alt: false,
|
np_alt: false,
|
||||||
cu_alt: false,
|
cu_alt: false,
|
||||||
fn_alt: false,
|
fn_alt: false,
|
||||||
|
mt_click: false,
|
||||||
|
mt_move: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Send a literal message */
|
||||||
function sendStrMsg(str) {
|
function sendStrMsg(str) {
|
||||||
Conn.send("s"+str);
|
Conn.send("s"+str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Send a button event */
|
||||||
function sendBtnMsg(n) {
|
function sendBtnMsg(n) {
|
||||||
Conn.send("b"+Chr(n));
|
Conn.send("b"+Chr(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fn alt choice for key message */
|
||||||
function fa(alt, normal) {
|
function fa(alt, normal) {
|
||||||
return opts.fn_alt ? alt : normal;
|
return opts.fn_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cursor alt choice for key message */
|
||||||
function ca(alt, normal) {
|
function ca(alt, normal) {
|
||||||
return opts.cu_alt ? alt : normal;
|
return opts.cu_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Numpad alt choice for key message */
|
||||||
function na(alt, normal) {
|
function na(alt, normal) {
|
||||||
return opts.np_alt ? alt : normal;
|
return opts.np_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
@@ -2159,6 +2186,7 @@ var Input = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Bind a keystroke to message */
|
||||||
function bind(combo, str) {
|
function bind(combo, str) {
|
||||||
// mac fix - allow also cmd
|
// mac fix - allow also cmd
|
||||||
if (combo.indexOf('ctrl+') !== -1) {
|
if (combo.indexOf('ctrl+') !== -1) {
|
||||||
@@ -2174,6 +2202,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Bind/rebind key messages */
|
||||||
function _initKeys() {
|
function _initKeys() {
|
||||||
// This takes care of text characters typed
|
// This takes care of text characters typed
|
||||||
window.addEventListener('keypress', function(evt) {
|
window.addEventListener('keypress', function(evt) {
|
||||||
@@ -2199,10 +2228,12 @@ var Input = (function() {
|
|||||||
_bindFnKeys();
|
_bindFnKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mouse button states
|
||||||
var mb1 = 0;
|
var mb1 = 0;
|
||||||
var mb2 = 0;
|
var mb2 = 0;
|
||||||
var mb3 = 0;
|
var mb3 = 0;
|
||||||
|
|
||||||
|
/** Init the Input module */
|
||||||
function init() {
|
function init() {
|
||||||
_initKeys();
|
_initKeys();
|
||||||
|
|
||||||
@@ -2213,6 +2244,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// global mouse state tracking - for motion reporting
|
||||||
window.addEventListener('mousedown', function(evt) {
|
window.addEventListener('mousedown', function(evt) {
|
||||||
if (evt.button == 0) mb1 = 1;
|
if (evt.button == 0) mb1 = 1;
|
||||||
if (evt.button == 1) mb2 = 1;
|
if (evt.button == 1) mb2 = 1;
|
||||||
@@ -2226,6 +2258,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prepare modifiers byte for mouse message */
|
||||||
function packModifiersForMouse() {
|
function packModifiersForMouse() {
|
||||||
return (key.isModifier('ctrl')?1:0) |
|
return (key.isModifier('ctrl')?1:0) |
|
||||||
(key.isModifier('shift')?2:0) |
|
(key.isModifier('shift')?2:0) |
|
||||||
@@ -2234,9 +2267,13 @@ var Input = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/** Init the Input module */
|
||||||
init: init,
|
init: init,
|
||||||
// onTap: sendPosMsg,
|
|
||||||
|
/** Send a literal string message */
|
||||||
sendString: sendStrMsg,
|
sendString: sendStrMsg,
|
||||||
|
|
||||||
|
/** Enable alternate key modes (cursors, numpad, fn) */
|
||||||
setAlts: function(cu, np, fn) {
|
setAlts: function(cu, np, fn) {
|
||||||
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) {
|
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) {
|
||||||
opts.cu_alt = cu;
|
opts.cu_alt = cu;
|
||||||
@@ -2247,34 +2284,46 @@ var Input = (function() {
|
|||||||
_bindFnKeys();
|
_bindFnKeys();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setMouseMode: function(click, move) {
|
||||||
|
opts.mt_click = click;
|
||||||
|
opts.mt_move = move;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Mouse events
|
||||||
onMouseMove: function (x, y) {
|
onMouseMove: function (x, y) {
|
||||||
|
if (!opts.mt_move) return;
|
||||||
var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0;
|
var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
||||||
},
|
},
|
||||||
onMouseDown: function (x, y, b) {
|
onMouseDown: function (x, y, b) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
if (b > 3 || b < 1) return;
|
if (b > 3 || b < 1) return;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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) {
|
onMouseUp: function (x, y, b) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
if (b > 3 || b < 1) return;
|
if (b > 3 || b < 1) return;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("r" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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) {
|
onMouseWheel: function (x, y, dir) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
// -1 ... btn 4 (away from user)
|
// -1 ... btn 4 (away from user)
|
||||||
// +1 ... btn 5 (towards user)
|
// +1 ... btn 5 (towards user)
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
var b = (dir < 0 ? 4 : 5);
|
var b = (dir < 0 ? 4 : 5);
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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 () {
|
window.termInit = function () {
|
||||||
Conn.init();
|
Conn.init();
|
||||||
Input.init();
|
Input.init();
|
||||||
|
|||||||
+105
-90
@@ -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 Screen = (function () {
|
||||||
var W = 0, H = 0; // dimensions
|
var W = 0, H = 0; // dimensions
|
||||||
var inited = false;
|
var inited = false;
|
||||||
@@ -45,15 +10,16 @@ var Screen = (function () {
|
|||||||
bg: 0,
|
bg: 0,
|
||||||
attrs: 0,
|
attrs: 0,
|
||||||
suppress: false, // do not turn on in blink interval (for safe moving)
|
suppress: false, // do not turn on in blink interval (for safe moving)
|
||||||
forceOn: false,
|
forceOn: false, // force on unless hanging: used to keep cursor visible during move
|
||||||
hidden: false, // do not show
|
hidden: false, // do not show (DEC opt)
|
||||||
hanging: false, // xenl
|
hanging: false, // cursor at column "W+1" - not visible
|
||||||
};
|
};
|
||||||
|
|
||||||
var screen = [];
|
var screen = [];
|
||||||
var blinkIval;
|
var blinkIval;
|
||||||
var cursorFlashStartIval;
|
var cursorFlashStartIval;
|
||||||
|
|
||||||
|
// Some non-bold Fraktur symbols are outside the contiguous block
|
||||||
var frakturExceptions = {
|
var frakturExceptions = {
|
||||||
'C': '\u212d',
|
'C': '\u212d',
|
||||||
'H': '\u210c',
|
'H': '\u210c',
|
||||||
@@ -67,7 +33,7 @@ var Screen = (function () {
|
|||||||
try {
|
try {
|
||||||
audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)();
|
audioCtx = new (window.AudioContext || window.audioContext || window.webkitAudioContext)();
|
||||||
} catch (er) {
|
} catch (er) {
|
||||||
console.error("Browser does not support AudioContext, can't beep.", er);
|
console.error("No AudioContext!", er);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get cell under cursor */
|
/** Get cell under cursor */
|
||||||
@@ -87,6 +53,22 @@ var Screen = (function () {
|
|||||||
_draw(_curCell());
|
_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) */
|
/** Update cell on display. inv = invert (for cursor) */
|
||||||
function _draw(cell, inv) {
|
function _draw(cell, inv) {
|
||||||
if (!cell) return;
|
if (!cell) return;
|
||||||
@@ -94,44 +76,28 @@ var Screen = (function () {
|
|||||||
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
|
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var elem = cell.e, fg, bg, cn, t;
|
var fg, bg, cn, t;
|
||||||
// Colors
|
|
||||||
fg = inv ? cell.bg : cell.fg;
|
fg = inv ? cell.bg : cell.fg;
|
||||||
bg = inv ? cell.fg : cell.bg;
|
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;
|
cn = 'fg' + fg + ' bg' + bg;
|
||||||
if (cell.attrs & (1<<0)) cn += ' bold';
|
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<<2)) cn += ' italic';
|
||||||
if (cell.attrs & (1<<3)) cn += ' under';
|
if (cell.attrs & (1<<3)) cn += ' under';
|
||||||
if (cell.attrs & (1<<4)) cn += ' blink';
|
if (cell.attrs & (1<<4)) cn += ' blink';
|
||||||
if (cell.attrs & (1<<5)) {
|
if (cell.attrs & (1<<5)) {
|
||||||
cn += ' fraktur';
|
cn += ' fraktur';
|
||||||
// perform substitution
|
t = alpha2fraktur(t);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (cell.attrs & (1<<6)) cn += ' strike';
|
if (cell.attrs & (1<<6)) cn += ' strike';
|
||||||
|
|
||||||
if (cell.attrs & (1<<1)) {
|
cell.slot.textContent = t;
|
||||||
cn += ' faint';
|
cell.elem.className = cn;
|
||||||
// faint requires special html - otherwise it would also dim the background.
|
|
||||||
// we use opacity on the text...
|
|
||||||
elem.innerHTML = '<span>' + e(elem.textContent) + '</span>';
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.className = cn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Show entire screen */
|
/** Show entire screen */
|
||||||
@@ -146,32 +112,34 @@ var Screen = (function () {
|
|||||||
H = rows;
|
H = rows;
|
||||||
|
|
||||||
/* Build screen & show */
|
/* Build screen & show */
|
||||||
var e, cell, scr = qs('#screen');
|
var cOuter, cInner, cell, screenDiv = qs('#screen');
|
||||||
|
|
||||||
// Empty the screen node
|
// Empty the screen node
|
||||||
while (scr.firstChild) scr.removeChild(scr.firstChild);
|
while (screenDiv.firstChild) screenDiv.removeChild(screenDiv.firstChild);
|
||||||
|
|
||||||
screen = [];
|
screen = [];
|
||||||
|
|
||||||
for(var i = 0; i < W*H; i++) {
|
for(var i = 0; i < W*H; i++) {
|
||||||
e = mk('span');
|
cOuter = mk('span');
|
||||||
|
cInner = mk('span');
|
||||||
|
|
||||||
|
/* Mouse tracking */
|
||||||
(function() {
|
(function() {
|
||||||
var x = i % W;
|
var x = i % W;
|
||||||
var y = Math.floor(i / W);
|
var y = Math.floor(i / W);
|
||||||
e.addEventListener('mouseenter', function (evt) {
|
cOuter.addEventListener('mouseenter', function (evt) {
|
||||||
Input.onMouseMove(x, y);
|
Input.onMouseMove(x, y);
|
||||||
});
|
});
|
||||||
e.addEventListener('mousedown', function (evt) {
|
cOuter.addEventListener('mousedown', function (evt) {
|
||||||
Input.onMouseDown(x, y, evt.button+1);
|
Input.onMouseDown(x, y, evt.button+1);
|
||||||
});
|
});
|
||||||
e.addEventListener('mouseup', function (evt) {
|
cOuter.addEventListener('mouseup', function (evt) {
|
||||||
Input.onMouseUp(x, y, evt.button+1);
|
Input.onMouseUp(x, y, evt.button+1);
|
||||||
});
|
});
|
||||||
e.addEventListener('contextmenu', function (evt) {
|
cOuter.addEventListener('contextmenu', function (evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
});
|
});
|
||||||
e.addEventListener('mousewheel', function (evt) {
|
cOuter.addEventListener('mousewheel', function (evt) {
|
||||||
Input.onMouseWheel(x, y, evt.deltaY>0?1:-1);
|
Input.onMouseWheel(x, y, evt.deltaY>0?1:-1);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@@ -179,17 +147,19 @@ var Screen = (function () {
|
|||||||
|
|
||||||
/* End of line */
|
/* End of line */
|
||||||
if ((i > 0) && (i % W == 0)) {
|
if ((i > 0) && (i % W == 0)) {
|
||||||
scr.appendChild(mk('br'));
|
screenDiv.appendChild(mk('br'));
|
||||||
}
|
}
|
||||||
/* The cell */
|
/* The cell */
|
||||||
scr.appendChild(e);
|
cOuter.appendChild(cInner);
|
||||||
|
screenDiv.appendChild(cOuter);
|
||||||
|
|
||||||
cell = {
|
cell = {
|
||||||
t: ' ',
|
t: ' ',
|
||||||
fg: 7,
|
fg: 7,
|
||||||
bg: 0, // the colors will be replaced immediately as we receive data (user won't see this)
|
bg: 0, // the colors will be replaced immediately as we receive data (user won't see this)
|
||||||
attrs: 0,
|
attrs: 0,
|
||||||
e: e,
|
elem: cOuter,
|
||||||
|
slot: cInner,
|
||||||
x: i % W,
|
x: i % W,
|
||||||
y: Math.floor(i / W),
|
y: Math.floor(i / W),
|
||||||
};
|
};
|
||||||
@@ -204,7 +174,6 @@ var Screen = (function () {
|
|||||||
clearInterval(blinkIval);
|
clearInterval(blinkIval);
|
||||||
blinkIval = setInterval(function () {
|
blinkIval = setInterval(function () {
|
||||||
cursor.a = !cursor.a;
|
cursor.a = !cursor.a;
|
||||||
// TODO try to invent a new way to indicate "hanging" - this is copied from gtkterm
|
|
||||||
if (cursor.hidden || cursor.hanging) {
|
if (cursor.hidden || cursor.hanging) {
|
||||||
cursor.a = false;
|
cursor.a = false;
|
||||||
}
|
}
|
||||||
@@ -214,7 +183,7 @@ var Screen = (function () {
|
|||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
// blink attribute
|
/* blink attribute animation */
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
$('#screen').removeClass('blink-hide');
|
$('#screen').removeClass('blink-hide');
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@@ -225,11 +194,13 @@ var Screen = (function () {
|
|||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constants for decoding the update blob
|
||||||
var SEQ_SET_COLOR_ATTR = 1;
|
var SEQ_SET_COLOR_ATTR = 1;
|
||||||
var SEQ_REPEAT = 2;
|
var SEQ_REPEAT = 2;
|
||||||
var SEQ_SET_COLOR = 3;
|
var SEQ_SET_COLOR = 3;
|
||||||
var SEQ_SET_ATTR = 4;
|
var SEQ_SET_ATTR = 4;
|
||||||
|
|
||||||
|
/** Parse received screen update object (leading S removed already) */
|
||||||
function _load_content(str) {
|
function _load_content(str) {
|
||||||
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, attrs, cell;
|
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);
|
// console.log("Cursor at ",num, num2);
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
num = parse2B(str, i); i += 2; // fg bg bold hidden
|
num = parse2B(str, i); i += 2; // fg bg attribs
|
||||||
cursor.hidden = !(num & 0x0001);
|
cursor.hidden = !(num & (1<<0)); // DEC opt "visible"
|
||||||
cursor.hanging = !!(num & 0x0002);
|
cursor.hanging = !!(num & (1<<1));
|
||||||
// console.log("Attributes word ",num.toString(16)+'h');
|
// console.log("Attributes word ",num.toString(16)+'h');
|
||||||
|
|
||||||
Input.setAlts(
|
Input.setAlts(
|
||||||
!!(num & 0x0004), // cu
|
!!(num & (1<<2)), // cursors alt
|
||||||
!!(num & 0x0008), // np
|
!!(num & (1<<3)), // numpad alt
|
||||||
!!(num & 0x0010) // fn
|
!!(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;
|
fg = 7;
|
||||||
bg = 0;
|
bg = 0;
|
||||||
attrs = 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) {
|
function _load_labels(str) {
|
||||||
var pieces = str.split('\x01');
|
var pieces = str.split('\x01');
|
||||||
qs('h1').textContent = pieces[0];
|
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();
|
var s = pieces[i+1].trim();
|
||||||
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
||||||
x.innerHTML = s.length > 0 ? e(s) : " ";
|
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;
|
var osc, gain;
|
||||||
if (!audioCtx) return;
|
if (!audioCtx) return;
|
||||||
|
|
||||||
@@ -380,6 +365,7 @@ var Screen = (function () {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.warn("Bad data message type, ignoring.");
|
console.warn("Bad data message type, ignoring.");
|
||||||
|
console.log(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,24 +491,31 @@ var Input = (function() {
|
|||||||
np_alt: false,
|
np_alt: false,
|
||||||
cu_alt: false,
|
cu_alt: false,
|
||||||
fn_alt: false,
|
fn_alt: false,
|
||||||
|
mt_click: false,
|
||||||
|
mt_move: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Send a literal message */
|
||||||
function sendStrMsg(str) {
|
function sendStrMsg(str) {
|
||||||
Conn.send("s"+str);
|
Conn.send("s"+str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Send a button event */
|
||||||
function sendBtnMsg(n) {
|
function sendBtnMsg(n) {
|
||||||
Conn.send("b"+Chr(n));
|
Conn.send("b"+Chr(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fn alt choice for key message */
|
||||||
function fa(alt, normal) {
|
function fa(alt, normal) {
|
||||||
return opts.fn_alt ? alt : normal;
|
return opts.fn_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cursor alt choice for key message */
|
||||||
function ca(alt, normal) {
|
function ca(alt, normal) {
|
||||||
return opts.cu_alt ? alt : normal;
|
return opts.cu_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Numpad alt choice for key message */
|
||||||
function na(alt, normal) {
|
function na(alt, normal) {
|
||||||
return opts.np_alt ? alt : normal;
|
return opts.np_alt ? alt : normal;
|
||||||
}
|
}
|
||||||
@@ -593,6 +586,7 @@ var Input = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Bind a keystroke to message */
|
||||||
function bind(combo, str) {
|
function bind(combo, str) {
|
||||||
// mac fix - allow also cmd
|
// mac fix - allow also cmd
|
||||||
if (combo.indexOf('ctrl+') !== -1) {
|
if (combo.indexOf('ctrl+') !== -1) {
|
||||||
@@ -608,6 +602,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Bind/rebind key messages */
|
||||||
function _initKeys() {
|
function _initKeys() {
|
||||||
// This takes care of text characters typed
|
// This takes care of text characters typed
|
||||||
window.addEventListener('keypress', function(evt) {
|
window.addEventListener('keypress', function(evt) {
|
||||||
@@ -633,10 +628,12 @@ var Input = (function() {
|
|||||||
_bindFnKeys();
|
_bindFnKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mouse button states
|
||||||
var mb1 = 0;
|
var mb1 = 0;
|
||||||
var mb2 = 0;
|
var mb2 = 0;
|
||||||
var mb3 = 0;
|
var mb3 = 0;
|
||||||
|
|
||||||
|
/** Init the Input module */
|
||||||
function init() {
|
function init() {
|
||||||
_initKeys();
|
_initKeys();
|
||||||
|
|
||||||
@@ -647,6 +644,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// global mouse state tracking - for motion reporting
|
||||||
window.addEventListener('mousedown', function(evt) {
|
window.addEventListener('mousedown', function(evt) {
|
||||||
if (evt.button == 0) mb1 = 1;
|
if (evt.button == 0) mb1 = 1;
|
||||||
if (evt.button == 1) mb2 = 1;
|
if (evt.button == 1) mb2 = 1;
|
||||||
@@ -660,6 +658,7 @@ var Input = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prepare modifiers byte for mouse message */
|
||||||
function packModifiersForMouse() {
|
function packModifiersForMouse() {
|
||||||
return (key.isModifier('ctrl')?1:0) |
|
return (key.isModifier('ctrl')?1:0) |
|
||||||
(key.isModifier('shift')?2:0) |
|
(key.isModifier('shift')?2:0) |
|
||||||
@@ -668,9 +667,13 @@ var Input = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/** Init the Input module */
|
||||||
init: init,
|
init: init,
|
||||||
// onTap: sendPosMsg,
|
|
||||||
|
/** Send a literal string message */
|
||||||
sendString: sendStrMsg,
|
sendString: sendStrMsg,
|
||||||
|
|
||||||
|
/** Enable alternate key modes (cursors, numpad, fn) */
|
||||||
setAlts: function(cu, np, fn) {
|
setAlts: function(cu, np, fn) {
|
||||||
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) {
|
if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) {
|
||||||
opts.cu_alt = cu;
|
opts.cu_alt = cu;
|
||||||
@@ -681,34 +684,46 @@ var Input = (function() {
|
|||||||
_bindFnKeys();
|
_bindFnKeys();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setMouseMode: function(click, move) {
|
||||||
|
opts.mt_click = click;
|
||||||
|
opts.mt_move = move;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Mouse events
|
||||||
onMouseMove: function (x, y) {
|
onMouseMove: function (x, y) {
|
||||||
|
if (!opts.mt_move) return;
|
||||||
var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0;
|
var b = mb1 ? 1 : mb2 ? 2 : mb3 ? 3 : 0;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
Conn.send("m" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
||||||
},
|
},
|
||||||
onMouseDown: function (x, y, b) {
|
onMouseDown: function (x, y, b) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
if (b > 3 || b < 1) return;
|
if (b > 3 || b < 1) return;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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) {
|
onMouseUp: function (x, y, b) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
if (b > 3 || b < 1) return;
|
if (b > 3 || b < 1) return;
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
Conn.send("r" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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) {
|
onMouseWheel: function (x, y, dir) {
|
||||||
|
if (!opts.mt_click) return;
|
||||||
// -1 ... btn 4 (away from user)
|
// -1 ... btn 4 (away from user)
|
||||||
// +1 ... btn 5 (towards user)
|
// +1 ... btn 5 (towards user)
|
||||||
var m = packModifiersForMouse();
|
var m = packModifiersForMouse();
|
||||||
var b = (dir < 0 ? 4 : 5);
|
var b = (dir < 0 ? 4 : 5);
|
||||||
Conn.send("p" + encode2B(y) + encode2B(x) + encode2B(b) + encode2B(m));
|
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 () {
|
window.termInit = function () {
|
||||||
Conn.init();
|
Conn.init();
|
||||||
Input.init();
|
Input.init();
|
||||||
|
|||||||
@@ -121,3 +121,38 @@ function jsp() {
|
|||||||
return null;
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
$('#sta-nw .essid').html(e(name));
|
$('#sta-nw .essid').html(e(name));
|
||||||
var nopw = undef(password) || password.length == 0;
|
var nopw = undef(password) || password.length == 0;
|
||||||
$('#sta-nw .x-passwd').html(e(password));
|
|
||||||
$('#sta-nw .passwd').toggleClass('hidden', nopw);
|
$('#sta-nw .passwd').toggleClass('hidden', nopw);
|
||||||
$('#sta-nw .nopasswd').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'));
|
$('#sta-nw .ip').html(ip.length>0 ? tr('wifi.connected_ip_is')+ip : tr('wifi.not_conn'));
|
||||||
|
|||||||
+11
-5
@@ -28,11 +28,15 @@ return [
|
|||||||
'net.details' => 'MAC addresses',
|
'net.details' => 'MAC addresses',
|
||||||
|
|
||||||
'term.defaults' => 'Initial Settings',
|
'term.defaults' => 'Initial Settings',
|
||||||
|
'term.expert' => 'Expert Options',
|
||||||
'term.explain_initials' => '
|
'term.explain_initials' => '
|
||||||
Those are the initial settings used after ESPTerm powers on.
|
Those are the initial settings used after ESPTerm powers on or when the screen
|
||||||
The selected colors will also be used after receiving a
|
reset command is received. Some options can be changed by the application via escape sequences,
|
||||||
screen- or attributes-reset command. Those settings will be
|
those changes won\'t be saved in Flash.
|
||||||
applied immediately after saving to preview the changes live.',
|
',
|
||||||
|
'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',
|
'term.example' => 'Default colors preview',
|
||||||
|
|
||||||
@@ -45,6 +49,8 @@ return [
|
|||||||
'term.display_tout_ms' => 'Redraw delay',
|
'term.display_tout_ms' => 'Redraw delay',
|
||||||
'term.display_cooldown_ms' => 'Redraw cooldown',
|
'term.display_cooldown_ms' => 'Redraw cooldown',
|
||||||
'term.fn_alt_mode' => 'SS3 Fn keys',
|
'term.fn_alt_mode' => 'SS3 Fn keys',
|
||||||
|
'term.show_config_links' => 'Show nav links',
|
||||||
|
'term.show_buttons' => 'Show buttons',
|
||||||
|
|
||||||
// terminal color labels
|
// terminal color labels
|
||||||
'color.0' => 'Black',
|
'color.0' => 'Black',
|
||||||
@@ -94,7 +100,7 @@ return [
|
|||||||
|
|
||||||
'wifi.not_conn' => 'Not connected.',
|
'wifi.not_conn' => 'Not connected.',
|
||||||
'wifi.sta_none' => 'None',
|
'wifi.sta_none' => 'None',
|
||||||
'wifi.sta_active_pw' => '🔒',
|
'wifi.sta_active_pw' => '🔒 Password saved',
|
||||||
'wifi.sta_active_nopw' => '🔓 Open access',
|
'wifi.sta_active_nopw' => '🔓 Open access',
|
||||||
'wifi.connected_ip_is' => 'Connected, IP is ',
|
'wifi.connected_ip_is' => 'Connected, IP is ',
|
||||||
'wifi.sta_password' => 'Password:',
|
'wifi.sta_password' => 'Password:',
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
|
||||||
|
<?php if ($_GET['BODYCLASS'] !== 'page-term'): ?>
|
||||||
|
<div class="botpad"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="NotifyMsg hidden" id="notif"></div>
|
<div class="NotifyMsg hidden" id="notif"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -104,6 +104,18 @@
|
|||||||
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
|
<input class="short" type="text" name="btn5" id="btn5" value="%h:btn5%">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="Row buttons">
|
||||||
|
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="Box fold str" action="<?= e(url('term_set')) ?>" method="GET" id='form-2'>
|
||||||
|
<h2><?= tr('term.expert') ?></h2>
|
||||||
|
|
||||||
|
<div class="Row explain">
|
||||||
|
<?= tr('term.explain_expert') ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="Row">
|
<div class="Row">
|
||||||
<label for="parser_tout_ms"><?= tr('term.parser_tout_ms') ?><span class="mq-phone"> (ms)</span></label>
|
<label for="parser_tout_ms"><?= tr('term.parser_tout_ms') ?><span class="mq-phone"> (ms)</span></label>
|
||||||
<input type="number" step=1 min=0 name="parser_tout_ms" id="parser_tout_ms" value="%parser_tout_ms%" required>
|
<input type="number" step=1 min=0 name="parser_tout_ms" id="parser_tout_ms" value="%parser_tout_ms%" required>
|
||||||
@@ -128,8 +140,20 @@
|
|||||||
<input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%">
|
<input type="hidden" id="fn_alt_mode" name="fn_alt_mode" value="%fn_alt_mode%">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="Row checkbox" >
|
||||||
|
<label><?= tr('term.show_buttons') ?></label><!--
|
||||||
|
--><span class="box" tabindex=0 role=checkbox></span>
|
||||||
|
<input type="hidden" id="show_buttons" name="show_buttons" value="%show_buttons%">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="Row checkbox" >
|
||||||
|
<label><?= tr('term.show_config_links') ?></label><!--
|
||||||
|
--><span class="box" tabindex=0 role=checkbox></span>
|
||||||
|
<input type="hidden" id="show_config_links" name="show_config_links" value="%show_config_links%">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="Row buttons">
|
<div class="Row buttons">
|
||||||
<a class="button icn-ok" href="#" onclick="qs('#form-1').submit()"><?= tr('apply') ?></a>
|
<a class="button icn-ok" href="#" onclick="qs('#form-2').submit()"><?= tr('apply') ?></a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<div class="essid"></div>
|
<div class="essid"></div>
|
||||||
<div class="passwd"><?= tr('wifi.sta_active_pw') ?> <span class="x-passwd"></span></div>
|
<div class="passwd"><?= tr('wifi.sta_active_pw') ?></div>
|
||||||
<div class="nopasswd"><?= tr('wifi.sta_active_nopw') ?></div>
|
<div class="nopasswd"><?= tr('wifi.sta_active_nopw') ?></div>
|
||||||
<div class="ip"></div>
|
<div class="ip"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+18
-863
@@ -1,865 +1,20 @@
|
|||||||
<div class="Box fold">
|
<div class="Box">
|
||||||
<h2>Tips & Troubleshooting</h2>
|
<a href="#" onclick="hpfold(1)">Expand all</a> | <a href="#" onclick="hpfold(0)">Collapse all</a>
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<img src="/img/adapter.jpg" class="aside" alt="ESPTerm v2">
|
|
||||||
<ul>
|
|
||||||
<li>*Communication UART (Rx, Tx)* can be configured in the <a href="<?= url('cfg_system') ?>">System Settings</a>.
|
|
||||||
|
|
||||||
<li>*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.
|
|
||||||
|
|
||||||
<li>*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 <a href="<?= url('cfg_term') ?>">Terminal Settings</a>
|
|
||||||
to be able to manually enter escape sequences.
|
|
||||||
|
|
||||||
<li>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.
|
|
||||||
|
|
||||||
<li>*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.
|
|
||||||
|
|
||||||
<li>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
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=com.farproc.wifi.analyzer">WiFi Analyzer (Google Play)</a>.
|
|
||||||
Adjust the hotspot strength and range using the _Tx Power setting_.
|
|
||||||
|
|
||||||
<li>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
|
|
||||||
<a href="<?= url('cfg_system') ?>">System Settings</a>.
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="Box fold">
|
<?php require __DIR__ . "/help/troubleshooting.php"; ?>
|
||||||
<h2>Basic Intro & Nomenclature</h2>
|
<?php require __DIR__ . "/help/nomenclature.php"; ?>
|
||||||
|
<?php require __DIR__ . "/help/screen_behavior.php"; ?>
|
||||||
<div class="Row v">
|
<?php require __DIR__ . "/help/input.php"; ?>
|
||||||
<img src="/img/vt100.jpg" class="aside" alt="VT102">
|
<?php require __DIR__ . "/help/charsets.php"; ?>
|
||||||
|
<?php require __DIR__ . "/help/sgr_styles.php"; ?>
|
||||||
<p>
|
<?php require __DIR__ . "/help/sgr_colors.php"; ?>
|
||||||
ESPTerm emulates VT102 (pictured) with some additions from later VT models and Xterm.
|
<?php require __DIR__ . "/help/cmd_cursor.php"; ?>
|
||||||
All commonly used attributes and commands are supported.
|
<?php require __DIR__ . "/help/cmd_screen.php"; ?>
|
||||||
ESPTerm is capable of displaying ncurses applications such as _Midnight Commander_ using _agetty_.
|
<?php require __DIR__ . "/help/cmd_system.php"; ?>
|
||||||
</p>
|
|
||||||
|
<script>
|
||||||
<p>
|
function hpfold(yes) {
|
||||||
ESPTerm accepts UTF-8 characters received on the communication UART and displays them on the screen,
|
$('.fold').toggleClass('expanded', !!yes);
|
||||||
interpreting some codes as Control Characters. Those are e.g. _Carriage Return_ (13), _Line Feed_ (10),
|
}
|
||||||
_Tab_ (9), _Backspace_ (8) and _Bell_ (7).
|
</script>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Escape sequences start with the control character _ESC_ (27),
|
|
||||||
followed by any number of ASCII characters forming the body of the command.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Nomenclature & Command Types</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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!)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Name</th><th>Symbol</th><th>ASCII</th><th>C string</th><th>Function</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>*ESC*</td>
|
|
||||||
<td>`\e`</td>
|
|
||||||
<td>`ESC` (27)</td>
|
|
||||||
<td>`"\e"`, `"\x1b"`, `"\033"`</td>
|
|
||||||
<td>Introduces an escape sequence. _(Note: `\e` is a GCC extension)_</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Bell*</td>
|
|
||||||
<td>`\a`</td>
|
|
||||||
<td>`BEL`~(7)</td>
|
|
||||||
<td>`"\a"`, `"\x7"`, `"\07"`</td>
|
|
||||||
<td>Audible beep</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*String Terminator*</td>
|
|
||||||
<td>`ST`</td>
|
|
||||||
<td>`ESC \`~(27~92)<br>_or_~`\a`~(7)</td>
|
|
||||||
<td>`"\x1b\\"`, `"\a"`</td>
|
|
||||||
<td>Terminates a string command (`\a` can be used as an alternative)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Control Sequence Introducer*</td>
|
|
||||||
<td>`CSI`</td>
|
|
||||||
<td>`ESC [`</td>
|
|
||||||
<td>`"\x1b["`</td>
|
|
||||||
<td>Starts a CSI command. Examples: `\e[?7;10h`, `\e[2J`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Operating System Command*</td>
|
|
||||||
<td>`OSC`</td>
|
|
||||||
<td>`ESC ]`</td>
|
|
||||||
<td>`"\x1b]"`</td>
|
|
||||||
<td>Starts an OSC command. Is followed by a command string terminated by `ST`. Example: `\e]0;My Screen Title\a`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>*Select Graphic Rendition*</td>
|
|
||||||
<td>`SGR`</td>
|
|
||||||
<td>`CSI <i>n</i>;<i>n</i>;<i>n</i>m`</td>
|
|
||||||
<td>`"\x1b[1;2;3m"`</td>
|
|
||||||
<td>Set text attributes, like color or style. 0 to 10 numbers can be used, `\e[m` is treated as `\e[0m`</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>Screen Behavior & Refreshing</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
The initial screen size, title text and button labels can be configured in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>Text Attributes</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
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`.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>Those are the supported text attributes SGR codes:</p>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Style</th><th>Enable</th><th>Disable</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td><b>Bold</b></td><td>1</td><td>21, 22</td></tr>
|
|
||||||
<tr><td style="opacity:.6">Faint</td><td>2</td><td>22</td></tr>
|
|
||||||
<tr><td><i>Italic</i></td><td>3</td><td>23</td></tr>
|
|
||||||
<tr><td><u>Underlined</u></td><td>4</td><td>24</td></tr>
|
|
||||||
<tr><td>Blink</td><td>5</td><td>25</td></tr>
|
|
||||||
<tr><td><span style="color:black;background:#ccc;">Inverse</span></td><td>7</td><td>27</td></tr>
|
|
||||||
<tr><td><s>Striked</s></td><td>9</td><td>29</td></tr>
|
|
||||||
<tr><td>𝔉𝔯𝔞𝔨𝔱𝔲𝔯</td><td>20</td><td>23</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold theme-0">
|
|
||||||
<h2>Colors</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The actual color representation depends on a color theme which
|
|
||||||
can be selected in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Foreground colors</h3>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg7 fg0">30</span>
|
|
||||||
<span class="bg0 fg1">31</span>
|
|
||||||
<span class="bg0 fg2">32</span>
|
|
||||||
<span class="bg0 fg3">33</span>
|
|
||||||
<span class="bg0 fg4">34</span>
|
|
||||||
<span class="bg0 fg5">35</span>
|
|
||||||
<span class="bg0 fg6">36</span>
|
|
||||||
<span class="bg0 fg7">37</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg0 fg8">90</span>
|
|
||||||
<span class="bg0 fg9">91</span>
|
|
||||||
<span class="bg0 fg10">92</span>
|
|
||||||
<span class="bg0 fg11">93</span>
|
|
||||||
<span class="bg0 fg12">94</span>
|
|
||||||
<span class="bg0 fg13">95</span>
|
|
||||||
<span class="bg0 fg14">96</span>
|
|
||||||
<span class="bg0 fg15">97</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Background colors</h3>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg0 fg15">40</span>
|
|
||||||
<span class="bg1 fg15">41</span>
|
|
||||||
<span class="bg2 fg15">42</span>
|
|
||||||
<span class="bg3 fg0">43</span>
|
|
||||||
<span class="bg4 fg15">44</span>
|
|
||||||
<span class="bg5 fg15">45</span>
|
|
||||||
<span class="bg6 fg15">46</span>
|
|
||||||
<span class="bg7 fg0">47</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="colorprev">
|
|
||||||
<span class="bg8 fg15">100</span>
|
|
||||||
<span class="bg9 fg0">101</span>
|
|
||||||
<span class="bg10 fg0">102</span>
|
|
||||||
<span class="bg11 fg0">103</span>
|
|
||||||
<span class="bg12 fg0">104</span>
|
|
||||||
<span class="bg13 fg0">105</span>
|
|
||||||
<span class="bg14 fg0">106</span>
|
|
||||||
<span class="bg15 fg0">107</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>User Input: Keyboard, Mouse</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<h3>Keyboard</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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 <a href="<?= url('cfg_term') ?>">Terminal Settings</a>, others via commands.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Here are some examples of control key codes:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead><tr><th>Key</th><th>Code</th><th>Key</th><th>Code</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>Up</td>
|
|
||||||
<td>`\e[A`</td>
|
|
||||||
<td>F1</td>
|
|
||||||
<td>`\eOP`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Down</td>
|
|
||||||
<td>`\e[B`</td>
|
|
||||||
<td>F2</td>
|
|
||||||
<td>`\eOQ`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Right</td>
|
|
||||||
<td>`\e[C`</td>
|
|
||||||
<td>F3</td>
|
|
||||||
<td>`\eOR`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Left</td>
|
|
||||||
<td>`\e[D`</td>
|
|
||||||
<td>F4</td>
|
|
||||||
<td>`\eOS`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Home</td>
|
|
||||||
<td>`\eOH`</td>
|
|
||||||
<td>F5</td>
|
|
||||||
<td>`\e[15~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>End</td>
|
|
||||||
<td>`\eOF`</td>
|
|
||||||
<td>F6</td>
|
|
||||||
<td>`\e[17~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Insert</td>
|
|
||||||
<td>`\e[2~`</td>
|
|
||||||
<td>F7</td>
|
|
||||||
<td>`\e[18~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Delete</td>
|
|
||||||
<td>`\e[3~`</td>
|
|
||||||
<td>F8</td>
|
|
||||||
<td>`\e[19~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Page Up</td>
|
|
||||||
<td>`\e[5~`</td>
|
|
||||||
<td>F9</td>
|
|
||||||
<td>`\e[20~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Page Down</td>
|
|
||||||
<td>`\e[6~`</td>
|
|
||||||
<td>F10</td>
|
|
||||||
<td>`\e[21~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Enter</td>
|
|
||||||
<td>`\r` (13)</td>
|
|
||||||
<td>F11</td>
|
|
||||||
<td>`\e[23~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Ctrl+Enter</td>
|
|
||||||
<td>`\n` (10)</td>
|
|
||||||
<td>F12</td>
|
|
||||||
<td>`\e[24~`</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tab</td>
|
|
||||||
<td>`\t` (9)</td>
|
|
||||||
<td>ESC</td>
|
|
||||||
<td>`\e` (27)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Backspace</td>
|
|
||||||
<td>`\b` (8)</td>
|
|
||||||
<td>Ctrl+A..Z</td>
|
|
||||||
<td>ASCII 1-26</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Action buttons</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Mouse</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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_.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Mouse Tracking Modes</h4>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>`9`</td>
|
|
||||||
<td>*X10~mode*</td>
|
|
||||||
<td>
|
|
||||||
This is the most basic tracking mode, in which <b>only button presses</b> are reported.
|
|
||||||
N = button - 1: (0 left, 1 middle, 2 right, 3, 4 wheel).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1000`</td>
|
|
||||||
<td>*Normal~mode*</td>
|
|
||||||
<td>
|
|
||||||
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).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1002`</td>
|
|
||||||
<td>*Button-Event tracking*</td>
|
|
||||||
<td>
|
|
||||||
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).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1003`</td>
|
|
||||||
<td>*Any-Event tracking*</td>
|
|
||||||
<td>
|
|
||||||
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).
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1004`</td>
|
|
||||||
<td>*Focus~tracking*</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4>Mouse Report Encoding</h4>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The following encoding schemes can be used with any of the tracking modes (except Focus tracking, which is not affected).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="tscroll">
|
|
||||||
<table class="nomen">
|
|
||||||
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
|
||||||
<tr>
|
|
||||||
<td>--</td>
|
|
||||||
<td>*Normal~encoding*</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1005`</td>
|
|
||||||
<td>*UTF-8~encoding*</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1006`</td>
|
|
||||||
<td>*SGR~encoding*</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`1015`</td>
|
|
||||||
<td>*URXVT~encoding*</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>Cursor Commands</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
*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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3>Movement</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>A \\
|
|
||||||
\e[<i>n</i>B \\
|
|
||||||
\e[<i>n</i>C \\
|
|
||||||
\e[<i>n</i>D
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Move cursor up (`A`), down (`B`), right (`C`), left (`D`)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>F \\
|
|
||||||
\e[<i>n</i>E
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Go _n_ lines up (`F`) or down (`E`), start of line</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>r</i>d \\
|
|
||||||
\e[<i>c</i>G \\
|
|
||||||
\e[<i>r</i>;<i>c</i>H
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Go to absolute position - row (`d`), column (`G`), or both (`H`). Use `\e[H` to go to 1,1.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[6n`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Query cursor position. Sent back as `\e[<i>r</i>;<i>c</i>R`.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Save / restore</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[s \\
|
|
||||||
\e[u
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Save (`s`) or restore (`u`) cursor position</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e7 \\
|
|
||||||
\e8
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Save (`7`) or restore (`8`) cursor position and attributes</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Scrolling Region</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>a</i>;<i>b</i>r`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?6h \\
|
|
||||||
\e[?6l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>S \\
|
|
||||||
\e[<i>n</i>T
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Move contents of the Scrolling Region up (`S`) or down (`T`), pad with empty
|
|
||||||
lines of the current background color.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Tab stops</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\eH`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set tab stop at the current column. There are, by default, tabs every 8 columns.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>I \\
|
|
||||||
\e[<i>n</i>Z
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Advance (`I`) or go back (`Z`) _n_ tab stops or end/start of line. ASCII _TAB_ (9) is equivalent to <code>\e[1I</code></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[0g \\
|
|
||||||
\e[3g \\
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Clear tab stop at the current column (`0`), or all columns (`3`).</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Other options</h3>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?7h \\
|
|
||||||
\e[?7l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Enable (`h`) or disable (`l`) cursor auto-wrap and screen auto-scroll</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[?25h \\
|
|
||||||
\e[?25l
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>Show (`h`) or hide (`l`) the cursor</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>Screen Content Manipulation</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
<b>Legend:</b>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>m</i>J`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Clear part of screen. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>m</i>K`
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Erase part of line. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
`\e[<i>n</i>X`</td>
|
|
||||||
<td>
|
|
||||||
Erase _n_ characters in line.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>L \\
|
|
||||||
\e[<i>n</i>M
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Insert (`L`) or delete (`M`) _n_ lines. Following lines are pulled up or pushed down.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e[<i>n</i>@ \\
|
|
||||||
\e[<i>n</i>P
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>Alternate Character Sets</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The following codepages are implemented:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>`B` - US ASCII (default)</li>
|
|
||||||
<li>`A` - UK ASCII: # replaced with £</li>
|
|
||||||
<li>`0` - Symbols and basic line drawing (standard DEC alternate character set)</li>
|
|
||||||
<li>`1` - Symbols and advanced line drawing (based on DOS codepage 437)</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
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 (<code>\ec</code>).
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>The following commands are used:</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>`\e(<i>x</i>`</td>
|
|
||||||
<td>Set G0 = codepage <i>x</i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e)<i>x</i>`</td>
|
|
||||||
<td>Set G1 = codepage <i>x</i></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_SO_ (14)</td>
|
|
||||||
<td>Activate G0</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_SI_ (15)</td>
|
|
||||||
<td>Activate G1</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="Box fold">
|
|
||||||
<h2>System Commands</h2>
|
|
||||||
|
|
||||||
<div class="Row v">
|
|
||||||
<p>
|
|
||||||
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.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table class="ansiref w100">
|
|
||||||
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>`\ec`</td>
|
|
||||||
<td>
|
|
||||||
Clear screen, reset attributes and cursor.
|
|
||||||
The screen size, title and button labels remain unchanged.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e[5n`</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>_CAN_ (24)</td>
|
|
||||||
<td>
|
|
||||||
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.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e]0;<i>title</i>\a`</td>
|
|
||||||
<td>Set screen title (this is a standard OSC command)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>
|
|
||||||
\e]<i>81</i>;<i>btn1</i>\a \\
|
|
||||||
\e]<i>82</i>;<i>btn2</i>\a \\
|
|
||||||
\e]<i>83</i>;<i>btn3</i>\a \\
|
|
||||||
\e]<i>84</i>;<i>btn4</i>\a \\
|
|
||||||
\e]<i>85</i>;<i>btn5</i>\a \\
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
Set button 1-5 label - eg.`\e]81;Yes\a`
|
|
||||||
sets the first button text to "Yes".
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>`\e[8;<i>r</i>;<i>c</i>t`</td>
|
|
||||||
<td>Set screen size (this is a command borrowed from xterm)</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Alternate Character Sets</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Supported codepages</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>`B` - US ASCII (default)</li>
|
||||||
|
<li>`A` - UK ASCII: # replaced with £</li>
|
||||||
|
<li>`0` - Symbols and basic line drawing (standard DEC alternate character set)</li>
|
||||||
|
<li>`1` - Symbols and advanced line drawing (based on DOS codepage 437, ESPTerm specific)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
All codepages use codes 32-127, 32 being space. A character with no entry in the active codepage
|
||||||
|
stays unchanged.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$codepages = load_esp_charsets();
|
||||||
|
foreach($codepages as $name => $cp) {
|
||||||
|
echo "<h4>Codepage `$name`</h4>\n";
|
||||||
|
echo '<div class="charset">';
|
||||||
|
foreach($cp as $point) {
|
||||||
|
$dis = $point[1]==$point[2]?' class="none"' : '';
|
||||||
|
echo "<div$dis><span>$point[0]</span><span>$point[1]</span><span>$point[2]</span></div>";
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h3>Switching commands</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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 (<code>\ec</code>).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>The following commands are used:</p>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>`\e(<i>x</i>`</td>
|
||||||
|
<td>Set G0 = codepage <i>x</i></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`\e)<i>x</i>`</td>
|
||||||
|
<td>Set G1 = codepage <i>x</i></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>_SO_ (14)</td>
|
||||||
|
<td>Activate G0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>_SI_ (15)</td>
|
||||||
|
<td>Activate G1</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Commands: Cursor Functions</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
*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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Movement</h3>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>A \\
|
||||||
|
\e[<i>n</i>B \\
|
||||||
|
\e[<i>n</i>C \\
|
||||||
|
\e[<i>n</i>D
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Move cursor up (`A`), down (`B`), right (`C`), left (`D`)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>F \\
|
||||||
|
\e[<i>n</i>E
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Go _n_ lines up (`F`) or down (`E`), start of line</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>r</i>d \\
|
||||||
|
\e[<i>c</i>G \\
|
||||||
|
\e[<i>r</i>;<i>c</i>H
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Go to absolute position - row (`d`), column (`G`), or both (`H`). Use `\e[H` to go to 1,1.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\e[6n`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Query cursor position. Sent back as `\e[<i>r</i>;<i>c</i>R`.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Save / restore</h3>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[s \\
|
||||||
|
\e[u
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Save (`s`) or restore (`u`) cursor position</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e7 \\
|
||||||
|
\e8
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Save (`7`) or restore (`8`) cursor position and attributes</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Scrolling Region</h3>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\e[<i>a</i>;<i>b</i>r`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[?6h \\
|
||||||
|
\e[?6l
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>S \\
|
||||||
|
\e[<i>n</i>T
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Tab stops</h3>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\eH`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Set tab stop at the current column. There are, by default, tabs every 8 columns.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>I \\
|
||||||
|
\e[<i>n</i>Z
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Advance (`I`) or go back (`Z`) _n_ tab stops or end/start of line. ASCII _TAB_ (9) is equivalent to <code>\e[1I</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[0g \\
|
||||||
|
\e[3g \\
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Clear tab stop at the current column (`0`), or all columns (`3`).</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Other options</h3>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[?7h \\
|
||||||
|
\e[?7l
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Enable (`h`) or disable (`l`) cursor auto-wrap and screen auto-scroll</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[?25h \\
|
||||||
|
\e[?25l
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>Show (`h`) or hide (`l`) the cursor</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Commands: Screen Functions</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
<b>Legend:</b>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\e[<i>m</i>J`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Clear part of screen. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\e[<i>m</i>K`
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Erase part of line. _m_: 0 - from cursor, 1 - to cursor, 2 - all
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
`\e[<i>n</i>X`</td>
|
||||||
|
<td>
|
||||||
|
Erase _n_ characters in line.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>L \\
|
||||||
|
\e[<i>n</i>M
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Insert (`L`) or delete (`M`) _n_ lines. Following lines are pulled up or pushed down.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[<i>n</i>@ \\
|
||||||
|
\e[<i>n</i>P
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Commands: System Functions</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="ansiref w100">
|
||||||
|
<thead><tr><th>Code</th><th>Meaning</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>`\ec`</td>
|
||||||
|
<td>
|
||||||
|
Clear screen, reset attributes and cursor.
|
||||||
|
The screen size, title and button labels remain unchanged.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`\e[5n`</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>_CAN_ (24)</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`\e]0;<i>title</i>\a`</td>
|
||||||
|
<td>Set screen title (this is a standard OSC command)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e]<i>81</i>;<i>btn1</i>\a \\
|
||||||
|
\e]<i>82</i>;<i>btn2</i>\a \\
|
||||||
|
\e]<i>83</i>;<i>btn3</i>\a \\
|
||||||
|
\e]<i>84</i>;<i>btn4</i>\a \\
|
||||||
|
\e]<i>85</i>;<i>btn5</i>\a \\
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Set button 1-5 label - eg.`\e]81;Yes\a`
|
||||||
|
sets the first button text to "Yes".
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[?800h \\
|
||||||
|
\e[?800l
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Show (`h`) or hide (`l`) action buttons (the blue buttons under the screen).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<code>
|
||||||
|
\e[?801h \\
|
||||||
|
\e[?801l
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
Show (`h`) or hide (`l`) menu/help links under the screen.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`\e[8;<i>r</i>;<i>c</i>t`</td>
|
||||||
|
<td>Set screen size (this is a command borrowed from xterm)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
|
||||||
|
<div class="Box fold">
|
||||||
|
<h2>User Input: Keyboard, Mouse</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<h3>Keyboard</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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 <a href="<?= url('cfg_term') ?>">Terminal Settings</a>,
|
||||||
|
others via commands.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here are some examples of control key codes:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Key</th><th>Code</th><th>Key</th><th>Code</th></tr></thead>
|
||||||
|
<tr>
|
||||||
|
<td>Up</td>
|
||||||
|
<td>`\e[A`,~`\eOA`</td>
|
||||||
|
<td>F1</td>
|
||||||
|
<td>`\eOP`,~`\e[11\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Down</td>
|
||||||
|
<td>`\e[B`,~`\eOB`</td>
|
||||||
|
<td>F2</td>
|
||||||
|
<td>`\eOQ`,~`\e[12\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Right</td>
|
||||||
|
<td>`\e[C`,~`\eOC`</td>
|
||||||
|
<td>F3</td>
|
||||||
|
<td>`\eOR`,~`\e[13\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Left</td>
|
||||||
|
<td>`\e[D`,~`\eOD`</td>
|
||||||
|
<td>F4</td>
|
||||||
|
<td>`\eOS`,~`\e[14\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Home</td>
|
||||||
|
<td>`\eOH`,~`\e[H`,~`\e[1\~`</td>
|
||||||
|
<td>F5</td>
|
||||||
|
<td>`\e[15~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>End</td>
|
||||||
|
<td>`\eOF`,~`\e[F`,~`\e[4\~`</td>
|
||||||
|
<td>F6</td>
|
||||||
|
<td>`\e[17\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Insert</td>
|
||||||
|
<td>`\e[2\~`</td>
|
||||||
|
<td>F7</td>
|
||||||
|
<td>`\e[18\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Delete</td>
|
||||||
|
<td>`\e[3\~`</td>
|
||||||
|
<td>F8</td>
|
||||||
|
<td>`\e[19\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Page Up</td>
|
||||||
|
<td>`\e[5\~`</td>
|
||||||
|
<td>F9</td>
|
||||||
|
<td>`\e[20\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Page Down</td>
|
||||||
|
<td>`\e[6\~`</td>
|
||||||
|
<td>F10</td>
|
||||||
|
<td>`\e[21\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Enter</td>
|
||||||
|
<td>`\r` (13)</td>
|
||||||
|
<td>F11</td>
|
||||||
|
<td>`\e[23\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Ctrl+Enter</td>
|
||||||
|
<td>`\n` (10)</td>
|
||||||
|
<td>F12</td>
|
||||||
|
<td>`\e[24\~`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Tab</td>
|
||||||
|
<td>`\t` (9)</td>
|
||||||
|
<td>ESC</td>
|
||||||
|
<td>`\e` (27)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Backspace</td>
|
||||||
|
<td>`\b` (8)</td>
|
||||||
|
<td>Ctrl+A..Z</td>
|
||||||
|
<td>ASCII 1-26</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h3>Action buttons</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Mouse</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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_.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4>Mouse Tracking Modes</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tscroll">
|
||||||
|
<table class="nomen">
|
||||||
|
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
||||||
|
<tr>
|
||||||
|
<td>`9`</td>
|
||||||
|
<td>*X10~mode*</td>
|
||||||
|
<td>
|
||||||
|
This is the most basic tracking mode, in which <b>only button presses</b> are reported.
|
||||||
|
N = button - 1: (0 left, 1 middle, 2 right, 3, 4 wheel).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1000`</td>
|
||||||
|
<td>*Normal~mode*</td>
|
||||||
|
<td>
|
||||||
|
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).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1002`</td>
|
||||||
|
<td>*Button-Event tracking*</td>
|
||||||
|
<td>
|
||||||
|
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).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1003`</td>
|
||||||
|
<td>*Any-Event tracking*</td>
|
||||||
|
<td>
|
||||||
|
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).
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1004`</td>
|
||||||
|
<td>*Focus~tracking*</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4>Mouse Report Encoding</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The following encoding schemes can be used with any of the tracking modes (except Focus tracking, which is not affected).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tscroll">
|
||||||
|
<table class="nomen">
|
||||||
|
<thead><tr><th>Option</th><th>Name</th><th>Description</th></tr></thead>
|
||||||
|
<tr>
|
||||||
|
<td>--</td>
|
||||||
|
<td>*Normal~encoding*</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1005`</td>
|
||||||
|
<td>*UTF-8~encoding*</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1006`</td>
|
||||||
|
<td>*SGR~encoding*</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>`1015`</td>
|
||||||
|
<td>*URXVT~encoding*</td>
|
||||||
|
<td>
|
||||||
|
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.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Basic Intro & Nomenclature</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<img src="/img/vt100.jpg" class="aside" alt="VT102">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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_.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Escape sequences start with the control character _ESC_ (27),
|
||||||
|
followed by any number of ASCII characters forming the body of the command.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Nomenclature & Command Types</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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!)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="tscroll">
|
||||||
|
<table class="nomen">
|
||||||
|
<thead><tr><th>Name</th><th>Symbol</th><th>ASCII</th><th>C string</th><th>Function</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>*ESC*</td>
|
||||||
|
<td>`\e`</td>
|
||||||
|
<td>`ESC` (27)</td>
|
||||||
|
<td>`"\e"`, `"\x1b"`, `"\033"`</td>
|
||||||
|
<td>Introduces an escape sequence. _(Note: `\e` is a GCC extension)_</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>*Bell*</td>
|
||||||
|
<td>`\a`</td>
|
||||||
|
<td>`BEL`~(7)</td>
|
||||||
|
<td>`"\a"`, `"\x7"`, `"\07"`</td>
|
||||||
|
<td>Audible beep</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>*String Terminator*</td>
|
||||||
|
<td>`ST`</td>
|
||||||
|
<td>`ESC \`~(27~92)<br>_or_~`\a`~(7)</td>
|
||||||
|
<td>`"\x1b\\"`, `"\a"`</td>
|
||||||
|
<td>Terminates a string command (`\a` can be used as an alternative)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>*Control Sequence Introducer*</td>
|
||||||
|
<td>`CSI`</td>
|
||||||
|
<td>`ESC [`</td>
|
||||||
|
<td>`"\x1b["`</td>
|
||||||
|
<td>Starts a CSI command. Examples: `\e[?7;10h`, `\e[2J`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>*Operating System Command*</td>
|
||||||
|
<td>`OSC`</td>
|
||||||
|
<td>`ESC ]`</td>
|
||||||
|
<td>`"\x1b]"`</td>
|
||||||
|
<td>Starts an OSC command. Is followed by a command string terminated by `ST`. Example: `\e]0;My Screen Title\a`</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>*Select Graphic Rendition*</td>
|
||||||
|
<td>`SGR`</td>
|
||||||
|
<td>`CSI <i>n</i>;<i>n</i>;<i>n</i>m`</td>
|
||||||
|
<td>`"\x1b[1;2;3m"`</td>
|
||||||
|
<td>Set text attributes, like color or style. 0 to 10 numbers can be used, `\e[m` is treated as `\e[0m`</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>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.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Screen Behavior & Refreshing</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
The initial screen size, title text and button labels can be configured in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
<div class="Box fold theme-0">
|
||||||
|
<h2>Commands: Color SGR</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The actual color representation depends on a color theme which
|
||||||
|
can be selected in <a href="<?= url('cfg_term') ?>">Terminal Settings</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Foreground colors</h3>
|
||||||
|
|
||||||
|
<div class="colorprev">
|
||||||
|
<span class="bg7 fg0">30</span>
|
||||||
|
<span class="bg0 fg1">31</span>
|
||||||
|
<span class="bg0 fg2">32</span>
|
||||||
|
<span class="bg0 fg3">33</span>
|
||||||
|
<span class="bg0 fg4">34</span>
|
||||||
|
<span class="bg0 fg5">35</span>
|
||||||
|
<span class="bg0 fg6">36</span>
|
||||||
|
<span class="bg0 fg7">37</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="colorprev">
|
||||||
|
<span class="bg0 fg8">90</span>
|
||||||
|
<span class="bg0 fg9">91</span>
|
||||||
|
<span class="bg0 fg10">92</span>
|
||||||
|
<span class="bg0 fg11">93</span>
|
||||||
|
<span class="bg0 fg12">94</span>
|
||||||
|
<span class="bg0 fg13">95</span>
|
||||||
|
<span class="bg0 fg14">96</span>
|
||||||
|
<span class="bg0 fg15">97</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Background colors</h3>
|
||||||
|
|
||||||
|
<div class="colorprev">
|
||||||
|
<span class="bg0 fg15">40</span>
|
||||||
|
<span class="bg1 fg15">41</span>
|
||||||
|
<span class="bg2 fg15">42</span>
|
||||||
|
<span class="bg3 fg0">43</span>
|
||||||
|
<span class="bg4 fg15">44</span>
|
||||||
|
<span class="bg5 fg15">45</span>
|
||||||
|
<span class="bg6 fg15">46</span>
|
||||||
|
<span class="bg7 fg0">47</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="colorprev">
|
||||||
|
<span class="bg8 fg15">100</span>
|
||||||
|
<span class="bg9 fg0">101</span>
|
||||||
|
<span class="bg10 fg0">102</span>
|
||||||
|
<span class="bg11 fg0">103</span>
|
||||||
|
<span class="bg12 fg0">104</span>
|
||||||
|
<span class="bg13 fg0">105</span>
|
||||||
|
<span class="bg14 fg0">106</span>
|
||||||
|
<span class="bg15 fg0">107</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Commands: Style SGR</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<p>
|
||||||
|
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`.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Those are the supported text attributes SGR codes:</p>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead><tr><th>Style</th><th>Enable</th><th>Disable</th></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><b>Bold</b></td><td>1</td><td>21, 22</td></tr>
|
||||||
|
<tr><td style="opacity:.6">Faint</td><td>2</td><td>22</td></tr>
|
||||||
|
<tr><td><i>Italic</i></td><td>3</td><td>23</td></tr>
|
||||||
|
<tr><td><u>Underlined</u></td><td>4</td><td>24</td></tr>
|
||||||
|
<tr><td>Blink</td><td>5</td><td>25</td></tr>
|
||||||
|
<tr><td><span style="color:black;background:#ccc;">Inverse</span></td><td>7</td><td>27</td></tr>
|
||||||
|
<tr><td><s>Striked</s></td><td>9</td><td>29</td></tr>
|
||||||
|
<tr><td>𝔉𝔯𝔞𝔨𝔱𝔲𝔯</td><td>20</td><td>23</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<div class="Box fold">
|
||||||
|
<h2>Tips & Troubleshooting</h2>
|
||||||
|
|
||||||
|
<div class="Row v">
|
||||||
|
<ul>
|
||||||
|
<li>*Communication UART (Rx, Tx)* can be configured in the <a href="<?= url('cfg_system') ?>">System Settings</a>.
|
||||||
|
|
||||||
|
<li>*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.
|
||||||
|
|
||||||
|
<li>*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 <a href="<?= url('cfg_term') ?>">Terminal Settings</a>
|
||||||
|
to be able to manually enter escape sequences.
|
||||||
|
|
||||||
|
<li>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.
|
||||||
|
|
||||||
|
<li>*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.
|
||||||
|
|
||||||
|
<li>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
|
||||||
|
<a href="https://play.google.com/store/apps/details?id=com.farproc.wifi.analyzer">WiFi Analyzer (Google Play)</a>.
|
||||||
|
Adjust the hotspot strength and range using the _Tx Power setting_.
|
||||||
|
|
||||||
|
<li>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
|
||||||
|
<a href="<?= url('cfg_system') ?>">System Settings</a>.
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1></h1>
|
<h1><!-- Screen title gets loaded here by JS --></h1>
|
||||||
|
|
||||||
<div id="termwrap">
|
<div id="term-wrap">
|
||||||
<div id="screen" class="theme-%theme%"></div>
|
<div id="screen" class="theme-%theme%"></div>
|
||||||
|
|
||||||
<div id="buttons">
|
<div id="action-buttons">
|
||||||
<button data-n="1" class="btn-blue"></button><!--
|
<button data-n="1" class="btn-blue"></button><!--
|
||||||
--><button data-n="2" class="btn-blue"></button><!--
|
--><button data-n="2" class="btn-blue"></button><!--
|
||||||
--><button data-n="3" class="btn-blue"></button><!--
|
--><button data-n="3" class="btn-blue"></button><!--
|
||||||
@@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
<textarea id="softkb-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
<textarea id="softkb-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
|
||||||
|
|
||||||
<nav id="botnav">
|
<nav id="term-nav">
|
||||||
<a href="#" onclick="toggleSoftKb(true); return false" class="icn-keyboard mq-tablet-max"></a><!--
|
<a href="#" onclick="toggleSoftKb(true); return false" class="icn-keyboard mq-tablet-max"></a><!--
|
||||||
--><a href="<?= url('cfg_term') ?>"><?= tr('term_nav.config') ?></a><!--
|
--><a href="<?= url('cfg_term') ?>" class="x-term-conf-btn"><?= tr('term_nav.config') ?></a><!--
|
||||||
--><a href="<?= url('cfg_wifi') ?>"><?= tr('term_nav.wifi') ?></a><!--
|
--><a href="<?= url('cfg_wifi') ?>" class="x-term-conf-btn"><?= tr('term_nav.wifi') ?></a><!--
|
||||||
--><a href="<?= url('help') ?>"><?= tr('term_nav.help') ?></a><!--
|
--><a href="<?= url('help') ?>" class="x-term-conf-btn"><?= tr('term_nav.help') ?></a><!--
|
||||||
--><a href="<?= url('about') ?>"><?= tr('term_nav.about') ?></a>
|
--><a href="<?= url('about') ?>" class="x-term-conf-btn"><?= tr('term_nav.about') ?></a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ $c-form-field-fg: white;
|
|||||||
$c-form-highlight: #2972ba;
|
$c-form-highlight: #2972ba;
|
||||||
$c-form-highlight-a: #2ea1f9;
|
$c-form-highlight-a: #2ea1f9;
|
||||||
|
|
||||||
|
$screen-stack: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace;
|
||||||
|
|
||||||
@function dist($x) {
|
@function dist($x) {
|
||||||
@return modular-scale($x, 1rem, $golden);
|
@return modular-scale($x, 1rem, $golden);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ form { @include naked(); }
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin: 12px auto;
|
margin: 12px auto;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
line-height: 1.35em;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
.botpad {
|
||||||
|
display:block;
|
||||||
|
height: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
.Box {
|
.Box {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
line-height: 1.35em;
|
|
||||||
|
|
||||||
margin-top: dist(0);
|
margin-top: dist(0);
|
||||||
padding: dist(-1) dist(0);
|
padding: dist(-1) dist(0);
|
||||||
|
|||||||
@@ -80,3 +80,49 @@
|
|||||||
.tscroll {
|
.tscroll {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.charset {
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: inline-block;
|
||||||
|
width: 2.5em;
|
||||||
|
border: 1px solid #666;
|
||||||
|
height: 3em;
|
||||||
|
margin: 1px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(1) {
|
||||||
|
left: .2em;
|
||||||
|
top: .2em;
|
||||||
|
height: 1em;
|
||||||
|
font-size: 85%;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(2) {
|
||||||
|
right: .2em;
|
||||||
|
top: .2em;
|
||||||
|
height: 1em;
|
||||||
|
font-size: 85%;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:nth-child(3) {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 105%;
|
||||||
|
text-align: center;
|
||||||
|
bottom: .4em;
|
||||||
|
font-family: $screen-stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.none {
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,73 +13,84 @@ body.term {
|
|||||||
// longer duration to load everything in background nicely
|
// longer duration to load everything in background nicely
|
||||||
transition: opacity 0.25s ease-in;
|
transition: opacity 0.25s ease-in;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#screen {
|
#screen {
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #111213;
|
||||||
|
padding: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
border: 2px solid #3983CD;
|
||||||
|
|
||||||
|
font-size: 24px; // some font heights cause visual glitches with some font renderers. This should be configurable.
|
||||||
|
font-family: $screen-stack;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
position:absolute;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.noselect {
|
||||||
@include noselect();
|
@include noselect();
|
||||||
font-family: monospace;
|
|
||||||
font-size: 20px;//16pt; - 16pt causes vertical breaks in line drawing characters??
|
|
||||||
white-space: nowrap;
|
|
||||||
background: #111213;
|
|
||||||
padding: 6px;
|
|
||||||
display: inline-block;
|
|
||||||
border: 2px solid #3983CD; //#1bc249;
|
|
||||||
|
|
||||||
span {
|
|
||||||
white-space: pre;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1.15em; // this adjusts the spacing
|
|
||||||
width: 0.6em; // horizontal spacing, estimated to be about right
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#buttons {
|
|
||||||
margin-top: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin: 0 3px;
|
|
||||||
padding: 8px 5px;
|
|
||||||
//width: 18%;
|
|
||||||
min-width: 62px;
|
|
||||||
//max-width: 65px;
|
|
||||||
//min-width: initial;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#botnav {
|
|
||||||
padding-top: 1.5em;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding: 0 dist(-2);
|
|
||||||
text-decoration: underline;
|
|
||||||
|
|
||||||
&, &:visited, &:link {
|
|
||||||
color: #336085;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #5abfff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icn-keyboard {
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 150%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#termwrap {
|
#action-buttons {
|
||||||
|
margin-top: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin: 0 3px;
|
||||||
|
padding: 8px 5px;
|
||||||
|
min-width: 62px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#term-nav {
|
||||||
|
padding-top: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding: 0 dist(-2);
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
&, &:visited, &:link {
|
||||||
|
color: #336085;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #5abfff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icn-keyboard {
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 150%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#term-wrap {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dummy input field used to open android keyboard
|
||||||
#softkb-input {
|
#softkb-input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -9999px;
|
top: -9999px;
|
||||||
|
|||||||
@@ -531,6 +531,14 @@ static void ICACHE_FLASH_ATTR do_csi_privattr(CSI_Data *opts)
|
|||||||
else if (n == 25) {
|
else if (n == 25) {
|
||||||
screen_set_cursor_visible(yn);
|
screen_set_cursor_visible(yn);
|
||||||
}
|
}
|
||||||
|
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
||||||
|
termconf_scratch.show_buttons = yn;
|
||||||
|
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
||||||
|
}
|
||||||
|
else if (n == 801) { // ESPTerm: Toggle display of config links
|
||||||
|
termconf_scratch.show_config_links = yn;
|
||||||
|
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ansi_noimpl("CSI ? %d %c", n, opts->key);
|
ansi_noimpl("CSI ? %d %c", n, opts->key);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ apars_handle_osc(const char *buffer)
|
|||||||
if (n == 0 || n == 2) {
|
if (n == 0 || n == 2) {
|
||||||
screen_set_title(buffer);
|
screen_set_title(buffer);
|
||||||
}
|
}
|
||||||
else if (n >= 81 && n <= 85) { // numbers chosen to not collide with any xterm supported codes
|
else if (n >= 81 && n <= 85) { // ESPTerm: action button label
|
||||||
screen_set_button_text(n - 80, buffer);
|
screen_set_button_text(n - 80, buffer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -120,6 +120,18 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
termconf->fn_alt_mode = (bool)n;
|
termconf->fn_alt_mode = (bool)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("show_buttons")) {
|
||||||
|
dbg("Show buttons: %s", buff);
|
||||||
|
n = atoi(buff);
|
||||||
|
termconf->show_buttons = (bool)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("show_config_links")) {
|
||||||
|
dbg("Show config links: %s", buff);
|
||||||
|
n = atoi(buff);
|
||||||
|
termconf->show_config_links = (bool)n;
|
||||||
|
}
|
||||||
|
|
||||||
if (GET_ARG("default_fg")) {
|
if (GET_ARG("default_fg")) {
|
||||||
dbg("Screen default FG: %s", buff);
|
dbg("Screen default FG: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
@@ -212,6 +224,12 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
|||||||
else if (streq(token, "fn_alt_mode")) {
|
else if (streq(token, "fn_alt_mode")) {
|
||||||
sprintf(buff, "%d", (int)termconf->fn_alt_mode);
|
sprintf(buff, "%d", (int)termconf->fn_alt_mode);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "show_buttons")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->show_buttons);
|
||||||
|
}
|
||||||
|
else if (streq(token, "show_config_links")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->show_config_links);
|
||||||
|
}
|
||||||
else if (streq(token, "theme")) {
|
else if (streq(token, "theme")) {
|
||||||
sprintf(buff, "%d", termconf->theme);
|
sprintf(buff, "%d", termconf->theme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/09/06.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESPTERM_CHARACTER_SETS_H_H
|
||||||
|
#define ESPTERM_CHARACTER_SETS_H_H
|
||||||
|
|
||||||
|
#include <c_types.h>
|
||||||
|
|
||||||
|
// Tables must be contiguous!
|
||||||
|
|
||||||
|
#define CODEPAGE_A_BEGIN 35
|
||||||
|
#define CODEPAGE_A_END 35
|
||||||
|
|
||||||
|
static const u16 codepage_A[] =
|
||||||
|
{// Unicode ASCII SYM
|
||||||
|
// %%BEGIN:A%%
|
||||||
|
0x20a4, // 35 # £
|
||||||
|
// %%END:A%%
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CODEPAGE_0_BEGIN 96
|
||||||
|
#define CODEPAGE_0_END 126
|
||||||
|
|
||||||
|
/**
|
||||||
|
* translates VT100 ACS escape codes to Unicode values.
|
||||||
|
* Based on rxvt-unicode screen.C table.
|
||||||
|
*/
|
||||||
|
static const u16 codepage_0[] =
|
||||||
|
{// Unicode ASCII SYM
|
||||||
|
// %%BEGIN:0%%
|
||||||
|
0x2666, // 96 ` ♦
|
||||||
|
0x2592, // 97 a ▒
|
||||||
|
0x2409, // 98 b HT
|
||||||
|
0x240c, // 99 c FF
|
||||||
|
0x240d, // 100 d CR
|
||||||
|
0x240a, // 101 e LF
|
||||||
|
0x00b0, // 102 f °
|
||||||
|
0x00b1, // 103 g ±
|
||||||
|
0x2424, // 104 h NL
|
||||||
|
0x240b, // 105 i VT
|
||||||
|
0x2518, // 106 j ┘
|
||||||
|
0x2510, // 107 k ┐
|
||||||
|
0x250c, // 108 l ┌
|
||||||
|
0x2514, // 109 m └
|
||||||
|
0x253c, // 110 n ┼
|
||||||
|
0x23ba, // 111 o ⎺
|
||||||
|
0x23bb, // 112 p ⎻
|
||||||
|
0x2500, // 113 q ─
|
||||||
|
0x23bc, // 114 r ⎼
|
||||||
|
0x23bd, // 115 s ⎽
|
||||||
|
0x251c, // 116 t ├
|
||||||
|
0x2524, // 117 u ┤
|
||||||
|
0x2534, // 118 v ┴
|
||||||
|
0x252c, // 119 w ┬
|
||||||
|
0x2502, // 120 x │
|
||||||
|
0x2264, // 121 y ≤
|
||||||
|
0x2265, // 122 z ≥
|
||||||
|
0x03c0, // 123 { π
|
||||||
|
0x2260, // 124 | ≠
|
||||||
|
0x20a4, // 125 } £
|
||||||
|
0x00b7, // 126 ~ ·
|
||||||
|
// %%END:0%%
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CODEPAGE_1_BEGIN 33
|
||||||
|
#define CODEPAGE_1_END 126
|
||||||
|
|
||||||
|
static const u16 codepage_1[] =
|
||||||
|
{// Unicode ASCII SYM DOS
|
||||||
|
// %%BEGIN:1%%
|
||||||
|
0x263A, // 33 ! ☺ (1) - low ASCII symbols from DOS, moved to +32
|
||||||
|
0x263B, // 34 " ☻ (2)
|
||||||
|
0x2665, // 35 # ♥ (3)
|
||||||
|
0x2666, // 36 $ ♦ (4)
|
||||||
|
0x2663, // 37 % ♣ (5)
|
||||||
|
0x2660, // 38 & ♠ (6)
|
||||||
|
0x2022, // 39 ' • (7) - inverse dot and circle left out, can be done with SGR
|
||||||
|
0x231B, // 40 ( ⌛ - hourglass (timer icon)
|
||||||
|
0x25CB, // 41 ) ○ (9)
|
||||||
|
0x21AF, // 42 * ↯ - electricity (lightning monitor...)
|
||||||
|
0x266A, // 43 + ♪ (13)
|
||||||
|
0x266B, // 44 , ♫ (14)
|
||||||
|
0x263C, // 45 - ☼ (15)
|
||||||
|
0x2302, // 46 . ⌂ (127)
|
||||||
|
0x2622, // 47 / ☢ - radioactivity (geiger counter...)
|
||||||
|
0x2591, // 48 0 ░ (176) - this block is kept aligned and ordered from DOS, moved -128
|
||||||
|
0x2592, // 49 1 ▒ (177)
|
||||||
|
0x2593, // 50 2 ▓ (178)
|
||||||
|
0x2502, // 51 3 │ (179)
|
||||||
|
0x2524, // 52 4 ┤ (180)
|
||||||
|
0x2561, // 53 5 ╡ (181)
|
||||||
|
0x2562, // 54 6 ╢ (182)
|
||||||
|
0x2556, // 55 7 ╖ (183)
|
||||||
|
0x2555, // 56 8 ╕ (184)
|
||||||
|
0x2563, // 57 9 ╣ (185)
|
||||||
|
0x2551, // 58 : ║ (186)
|
||||||
|
0x2557, // 59 ; ╗ (187)
|
||||||
|
0x255D, // 60 < ╝ (188)
|
||||||
|
0x255C, // 61 = ╜ (189)
|
||||||
|
0x255B, // 62 > ╛ (190)
|
||||||
|
0x2510, // 63 ? ┐ (191)
|
||||||
|
0x2514, // 64 @ └ (192)
|
||||||
|
0x2534, // 65 A ┴ (193)
|
||||||
|
0x252C, // 66 B ┬ (194)
|
||||||
|
0x251C, // 67 C ├ (195)
|
||||||
|
0x2500, // 68 D ─ (196)
|
||||||
|
0x253C, // 69 E ┼ (197)
|
||||||
|
0x255E, // 70 F ╞ (198)
|
||||||
|
0x255F, // 71 G ╟ (199)
|
||||||
|
0x255A, // 72 H ╚ (200)
|
||||||
|
0x2554, // 73 I ╔ (201)
|
||||||
|
0x2569, // 74 J ╩ (202)
|
||||||
|
0x2566, // 75 K ╦ (203)
|
||||||
|
0x2560, // 76 L ╠ (204)
|
||||||
|
0x2550, // 77 M ═ (205)
|
||||||
|
0x256C, // 78 N ╬ (206)
|
||||||
|
0x2567, // 79 O ╧ (207)
|
||||||
|
0x2568, // 80 P ╨ (208)
|
||||||
|
0x2564, // 81 Q ╤ (209)
|
||||||
|
0x2565, // 82 R ╥ (210)
|
||||||
|
0x2559, // 83 S ╙ (211)
|
||||||
|
0x2558, // 84 T ╘ (212)
|
||||||
|
0x2552, // 85 U ╒ (213)
|
||||||
|
0x2553, // 86 V ╓ (214)
|
||||||
|
0x256B, // 87 W ╫ (215)
|
||||||
|
0x256A, // 88 X ╪ (216)
|
||||||
|
0x2518, // 89 Y ┘ (217)
|
||||||
|
0x250C, // 90 Z ┌ (218)
|
||||||
|
0x2588, // 91 [ █ (219)
|
||||||
|
0x2584, // 92 \ ▄ (220)
|
||||||
|
0x258C, // 93 ] ▌ (221)
|
||||||
|
0x2590, // 94 ^ ▐ (222)
|
||||||
|
0x2580, // 95 _ ▀ (223)
|
||||||
|
0x2195, // 96 ` ↕ (18) - moved from low DOS ASCII
|
||||||
|
0x2191, // 97 a ↑ (24)
|
||||||
|
0x2193, // 98 b ↓ (25)
|
||||||
|
0x2192, // 99 c → (26)
|
||||||
|
0x2190, // 100 d ← (27)
|
||||||
|
0x2194, // 101 e ↔ (29)
|
||||||
|
0x25B2, // 102 f ▲ (30)
|
||||||
|
0x25BC, // 103 g ▼ (31)
|
||||||
|
0x25BA, // 104 h ► (16)
|
||||||
|
0x25C4, // 105 i ◄ (17)
|
||||||
|
0x25E2, // 106 j ◢ - added for slanted corners
|
||||||
|
0x25E3, // 107 k ◣
|
||||||
|
0x25E4, // 108 l ◤
|
||||||
|
0x25E5, // 109 m ◥
|
||||||
|
0x256D, // 110 n ╭ - rounded corners
|
||||||
|
0x256E, // 111 o ╮
|
||||||
|
0x256F, // 112 p ╯
|
||||||
|
0x2570, // 113 q ╰
|
||||||
|
0x0, // 114 r - free positions for future expansion
|
||||||
|
0x0, // 115 s
|
||||||
|
0x0, // 116 t
|
||||||
|
0x0, // 117 u
|
||||||
|
0x0, // 118 v
|
||||||
|
0x0, // 119 w
|
||||||
|
0x0, // 120 x
|
||||||
|
0x0, // 121 y
|
||||||
|
0x0, // 122 z
|
||||||
|
0x0, // 123 {
|
||||||
|
0x0, // 124 |
|
||||||
|
0x2714, // 125 } ✔ - checkboxes or checklist items
|
||||||
|
0x2718, // 126 ~ ✘
|
||||||
|
// %%END:1%%
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //ESPTERM_CHARACTER_SETS_H_H
|
||||||
+44
-158
@@ -6,6 +6,7 @@
|
|||||||
#include "ascii.h"
|
#include "ascii.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
#include "jstring.h"
|
#include "jstring.h"
|
||||||
|
#include "character_sets.h"
|
||||||
|
|
||||||
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
||||||
TerminalConfigBundle termconf_scratch;
|
TerminalConfigBundle termconf_scratch;
|
||||||
@@ -129,17 +130,23 @@ static volatile int notifyLock = 0;
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
terminal_restore_defaults(void)
|
terminal_restore_defaults(void)
|
||||||
{
|
{
|
||||||
termconf->default_bg = 0;
|
|
||||||
termconf->default_fg = 7;
|
|
||||||
termconf->width = SCR_DEF_WIDTH;
|
termconf->width = SCR_DEF_WIDTH;
|
||||||
termconf->height = SCR_DEF_HEIGHT;
|
termconf->height = SCR_DEF_HEIGHT;
|
||||||
termconf->parser_tout_ms = SCR_DEF_PARSER_TOUT_MS;
|
termconf->default_bg = 0;
|
||||||
termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
termconf->default_fg = 7;
|
||||||
termconf->fn_alt_mode = SCR_DEF_FN_ALT_MODE;
|
|
||||||
sprintf(termconf->title, SCR_DEF_TITLE);
|
sprintf(termconf->title, SCR_DEF_TITLE);
|
||||||
for(int i=1; i <= 5; i++) {
|
for(int i=1; i <= 5; i++) {
|
||||||
sprintf(termconf->btn[i-1], "%d", i);
|
sprintf(termconf->btn[i-1], "%d", i);
|
||||||
}
|
}
|
||||||
|
termconf->theme = 0;
|
||||||
|
termconf->parser_tout_ms = SCR_DEF_PARSER_TOUT_MS;
|
||||||
|
termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
||||||
|
termconf->fn_alt_mode = SCR_DEF_FN_ALT_MODE;
|
||||||
|
termconf->config_version = TERMCONF_VERSION;
|
||||||
|
termconf->display_cooldown_ms = SCR_DEF_DISPLAY_COOLDOWN_MS;
|
||||||
|
termconf->loopback = 0;
|
||||||
|
termconf->show_buttons = 1;
|
||||||
|
termconf->show_config_links = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,6 +172,15 @@ terminal_apply_settings_noclear(void)
|
|||||||
changed = 1;
|
changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migrate to v2
|
||||||
|
if (termconf->config_version < 2) {
|
||||||
|
dbg("termconf: Updating to version 2");
|
||||||
|
termconf->loopback = 0;
|
||||||
|
termconf->show_config_links = 1;
|
||||||
|
termconf->show_buttons = 1;
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
termconf->config_version = TERMCONF_VERSION;
|
termconf->config_version = TERMCONF_VERSION;
|
||||||
|
|
||||||
// Validation...
|
// Validation...
|
||||||
@@ -223,8 +239,8 @@ cursor_reset(void)
|
|||||||
cursor.origin_mode = false;
|
cursor.origin_mode = false;
|
||||||
|
|
||||||
cursor.charsetN = 0;
|
cursor.charsetN = 0;
|
||||||
cursor.charset0 = CS_USASCII;
|
cursor.charset0 = CS_B_USASCII;
|
||||||
cursor.charset1 = CS_DEC_SUPPLEMENTAL;
|
cursor.charset1 = CS_0_DEC_SUPPLEMENTAL;
|
||||||
cursor.wraparound = true;
|
cursor.wraparound = true;
|
||||||
|
|
||||||
screen_reset_sgr();
|
screen_reset_sgr();
|
||||||
@@ -1119,143 +1135,6 @@ screen_putchar(const char *ch)
|
|||||||
NOTIFY_DONE();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* translates VT100 ACS escape codes to Unicode values.
|
|
||||||
* Based on rxvt-unicode screen.C table.
|
|
||||||
*/
|
|
||||||
static const u16 codepage_0[] =
|
|
||||||
{// Unicode ASCII SYM
|
|
||||||
0x2666, // 96 ` ♦
|
|
||||||
0x2592, // 97 a ▒
|
|
||||||
0x2409, // 98 b HT
|
|
||||||
0x240c, // 99 c FF
|
|
||||||
0x240d, // 100 d CR
|
|
||||||
0x240a, // 101 e LF
|
|
||||||
0x00b0, // 102 f °
|
|
||||||
0x00b1, // 103 g ±
|
|
||||||
0x2424, // 104 h NL
|
|
||||||
0x240b, // 105 i VT
|
|
||||||
0x2518, // 106 j ┘
|
|
||||||
0x2510, // 107 k ┐
|
|
||||||
0x250c, // 108 l ┌
|
|
||||||
0x2514, // 109 m └
|
|
||||||
0x253c, // 110 n ┼
|
|
||||||
0x23ba, // 111 o ⎺
|
|
||||||
0x23bb, // 112 p ⎻
|
|
||||||
0x2500, // 113 q ─
|
|
||||||
0x23bc, // 114 r ⎼
|
|
||||||
0x23bd, // 115 s ⎽
|
|
||||||
0x251c, // 116 t ├
|
|
||||||
0x2524, // 117 u ┤
|
|
||||||
0x2534, // 118 v ┴
|
|
||||||
0x252c, // 119 w ┬
|
|
||||||
0x2502, // 120 x │
|
|
||||||
0x2264, // 121 y ≤
|
|
||||||
0x2265, // 122 z ≥
|
|
||||||
0x03c0, // 123 { π
|
|
||||||
0x2260, // 124 | ≠
|
|
||||||
0x20a4, // 125 } £
|
|
||||||
0x00b7, // 126 ~ ·
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u16 codepage_1[] =
|
|
||||||
{// Unicode ASCII SYM DOS
|
|
||||||
0x263A, // 33 ! ☺ (1) - low ASCII symbols from DOS, moved to +32
|
|
||||||
0x263B, // 34 " ☻ (2)
|
|
||||||
0x2665, // 35 # ♥ (3)
|
|
||||||
0x2666, // 36 $ ♦ (4)
|
|
||||||
0x2663, // 37 % ♣ (5)
|
|
||||||
0x2660, // 38 & ♠ (6)
|
|
||||||
0x2022, // 39 ' • (7) - inverse dot and circle left out, can be done with SGR
|
|
||||||
0x0,//0x231B, // 40 ( ⌛ - hourglass (timer icon)
|
|
||||||
0x25CB, // 41 ) ○ (9)
|
|
||||||
0x21AF, // 42 * ↯ - electricity (lightning monitor...)
|
|
||||||
0x266A, // 43 + ♪ (13)
|
|
||||||
0x266B, // 44 , ♫ (14)
|
|
||||||
0x263C, // 45 - ☼ (15)
|
|
||||||
0x2302, // 46 . ⌂ (127)
|
|
||||||
0x0,//0x2622, // 47 / ☢ - radioactivity (geiger counter...)
|
|
||||||
0x2591, // 48 0 ░ (176) - this block is kept aligned and ordered from DOS, moved -128
|
|
||||||
0x2592, // 49 1 ▒ (177)
|
|
||||||
0x2593, // 50 2 ▓ (178)
|
|
||||||
0x2502, // 51 3 │ (179)
|
|
||||||
0x2524, // 52 4 ┤ (180)
|
|
||||||
0x2561, // 53 5 ╡ (181)
|
|
||||||
0x2562, // 54 6 ╢ (182)
|
|
||||||
0x2556, // 55 7 ╖ (183)
|
|
||||||
0x2555, // 56 8 ╕ (184)
|
|
||||||
0x2563, // 57 9 ╣ (185)
|
|
||||||
0x2551, // 58 : ║ (186)
|
|
||||||
0x2557, // 59 ; ╗ (187)
|
|
||||||
0x255D, // 60 < ╝ (188)
|
|
||||||
0x255C, // 61 = ╜ (189)
|
|
||||||
0x255B, // 62 > ╛ (190)
|
|
||||||
0x2510, // 63 ? ┐ (191)
|
|
||||||
0x2514, // 64 @ └ (192)
|
|
||||||
0x2534, // 65 A ┴ (193)
|
|
||||||
0x252C, // 66 B ┬ (194)
|
|
||||||
0x251C, // 67 C ├ (195)
|
|
||||||
0x2500, // 68 D ─ (196)
|
|
||||||
0x253C, // 69 E ┼ (197)
|
|
||||||
0x255E, // 70 F ╞ (198)
|
|
||||||
0x255F, // 71 G ╟ (199)
|
|
||||||
0x255A, // 72 H ╚ (200)
|
|
||||||
0x2554, // 73 I ╔ (201)
|
|
||||||
0x2569, // 74 J ╩ (202)
|
|
||||||
0x2566, // 75 K ╦ (203)
|
|
||||||
0x2560, // 76 L ╠ (204)
|
|
||||||
0x2550, // 77 M ═ (205)
|
|
||||||
0x256C, // 78 N ╬ (206)
|
|
||||||
0x2567, // 79 O ╧ (207)
|
|
||||||
0x2568, // 80 P ╨ (208)
|
|
||||||
0x2564, // 81 Q ╤ (209)
|
|
||||||
0x2565, // 82 R ╥ (210)
|
|
||||||
0x2559, // 83 S ╙ (211)
|
|
||||||
0x2558, // 84 T ╘ (212)
|
|
||||||
0x2552, // 85 U ╒ (213)
|
|
||||||
0x2553, // 86 V ╓ (214)
|
|
||||||
0x256B, // 87 W ╫ (215)
|
|
||||||
0x256A, // 88 X ╪ (216)
|
|
||||||
0x2518, // 89 Y ┘ (217)
|
|
||||||
0x250C, // 90 Z ┌ (218)
|
|
||||||
0x2588, // 91 [ █ (219)
|
|
||||||
0x2584, // 92 \ ▄ (220)
|
|
||||||
0x258C, // 93 ] ▌ (221)
|
|
||||||
0x2590, // 94 ^ ▐ (222)
|
|
||||||
0x2580, // 95 _ ▀ (223)
|
|
||||||
0x2195, // 96 ` ↕ (18) - moved from low DOS ASCII
|
|
||||||
0x2191, // 97 a ↑ (24)
|
|
||||||
0x2193, // 98 b ↓ (25)
|
|
||||||
0x2192, // 99 c → (26)
|
|
||||||
0x2190, // 100 d ← (27)
|
|
||||||
0x2194, // 101 e ↔ (29)
|
|
||||||
0x25B2, // 102 f ▲ (30)
|
|
||||||
0x25BC, // 103 g ▼ (31)
|
|
||||||
0x25BA, // 104 h ► (16)
|
|
||||||
0x25C4, // 105 i ◄ (17)
|
|
||||||
0x0,//0x25E2, // 106 j ◢ - added for slanted corners
|
|
||||||
0x0,//0x25E3, // 107 k ◣
|
|
||||||
0x0,//0x25E4, // 108 l ◤
|
|
||||||
0x0,//0x25E5, // 109 m ◥
|
|
||||||
0x256D, // 110 n ╭ - rounded corners
|
|
||||||
0x256E, // 111 o ╮
|
|
||||||
0x256F, // 112 p ╯
|
|
||||||
0x2570, // 113 q ╰
|
|
||||||
0x0, // 114 r - free positions for future expansion
|
|
||||||
0x0, // 115 s
|
|
||||||
0x0, // 116 t
|
|
||||||
0x0, // 117 u
|
|
||||||
0x0, // 118 v
|
|
||||||
0x0, // 119 w
|
|
||||||
0x0, // 120 x
|
|
||||||
0x0, // 121 y
|
|
||||||
0x0, // 122 z
|
|
||||||
0x0, // 123 {
|
|
||||||
0x0, // 124 |
|
|
||||||
0x0,//0x2714, // 125 } ✔ - checkboxes or checklist items
|
|
||||||
0x0,//0x2718, // 126 ~ ✘
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UTF remap
|
* UTF remap
|
||||||
* @param out - output char[4]
|
* @param out - output char[4]
|
||||||
@@ -1269,26 +1148,29 @@ utf8_remap(char *out, char g, char charset)
|
|||||||
u16 utf = (unsigned char)g;
|
u16 utf = (unsigned char)g;
|
||||||
|
|
||||||
switch (charset) {
|
switch (charset) {
|
||||||
case CS_DEC_SUPPLEMENTAL: /* DEC Special Character & Line Drawing Set */
|
case CS_0_DEC_SUPPLEMENTAL: /* DEC Special Character & Line Drawing Set */
|
||||||
if ((g >= 96) && (g < 0x7F)) {
|
if ((g >= CODEPAGE_0_BEGIN) && (g <= CODEPAGE_0_END)) {
|
||||||
n = codepage_0[g - 96];
|
n = codepage_0[g - CODEPAGE_0_BEGIN];
|
||||||
if (n) utf = n;
|
if (n) utf = n;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_DOS_437: /* ESPTerm Character Rom 1 */
|
case CS_1_DOS_437: /* ESPTerm Character Rom 1 */
|
||||||
if ((g >= 33) && (g < 0x7F)) {
|
if ((g >= CODEPAGE_1_BEGIN) && (g <= CODEPAGE_1_END)) {
|
||||||
n = codepage_1[g - 33];
|
n = codepage_1[g - CODEPAGE_1_END];
|
||||||
if (n) utf = n;
|
if (n) utf = n;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CS_UKASCII: /* UK, replaces # with GBP */
|
case CS_A_UKASCII: /* UK, replaces # with GBP */
|
||||||
if (g == '#') utf = 0x20a4;
|
if ((g >= CODEPAGE_A_BEGIN) && (g <= CODEPAGE_A_END)) {
|
||||||
|
n = codepage_A[g - CODEPAGE_A_BEGIN];
|
||||||
|
if (n) utf = n;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case CS_USASCII:
|
case CS_B_USASCII:
|
||||||
// No change
|
// No change
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1395,11 +1277,15 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
encode2B((u16) cursor.y, &w3);
|
encode2B((u16) cursor.y, &w3);
|
||||||
encode2B((u16) cursor.x, &w4);
|
encode2B((u16) cursor.x, &w4);
|
||||||
encode2B((u16) (
|
encode2B((u16) (
|
||||||
(cursor.visible ? 0x01 : 0) |
|
(cursor.visible ? 1<<0 : 0) |
|
||||||
(cursor.hanging ? 0x02 : 0) |
|
(cursor.hanging ? 1<<1 : 0) |
|
||||||
(scr.cursors_alt_mode ? 0x04 : 0) |
|
(scr.cursors_alt_mode ? 1<<2 : 0) |
|
||||||
(scr.numpad_alt_mode ? 0x08 : 0) |
|
(scr.numpad_alt_mode ? 1<<3 : 0) |
|
||||||
(termconf->fn_alt_mode ? 0x10 : 0)
|
(termconf->fn_alt_mode ? 1<<4 : 0) |
|
||||||
|
(mouse_tracking.mode!=MTM_NONE ? 1<<5 : 0) |
|
||||||
|
(mouse_tracking.mode>=MTM_BUTTON_MOTION ? 1<<6 : 0) |
|
||||||
|
(termconf_scratch.show_buttons ? 1<<7 : 0) |
|
||||||
|
(termconf_scratch.show_config_links ? 1<<8 : 0)
|
||||||
)
|
)
|
||||||
, &w5);
|
, &w5);
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -44,7 +44,7 @@
|
|||||||
#define SCR_DEF_DISPLAY_TOUT_MS 10
|
#define SCR_DEF_DISPLAY_TOUT_MS 10
|
||||||
#define SCR_DEF_DISPLAY_COOLDOWN_MS 30
|
#define SCR_DEF_DISPLAY_COOLDOWN_MS 30
|
||||||
#define SCR_DEF_PARSER_TOUT_MS 10
|
#define SCR_DEF_PARSER_TOUT_MS 10
|
||||||
#define SCR_DEF_FN_ALT_MODE false
|
#define SCR_DEF_FN_ALT_MODE true // true - SS3 codes, easier to parse & for xterm compatibility
|
||||||
#define SCR_DEF_WIDTH 26
|
#define SCR_DEF_WIDTH 26
|
||||||
#define SCR_DEF_HEIGHT 10
|
#define SCR_DEF_HEIGHT 10
|
||||||
#define SCR_DEF_TITLE "ESPTerm"
|
#define SCR_DEF_TITLE "ESPTerm"
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
/** Maximum screen size (determines size of the static data array) */
|
/** Maximum screen size (determines size of the static data array) */
|
||||||
#define MAX_SCREEN_SIZE (80*25)
|
#define MAX_SCREEN_SIZE (80*25)
|
||||||
|
|
||||||
#define TERMCONF_VERSION 1
|
#define TERMCONF_VERSION 2
|
||||||
|
|
||||||
// --- Persistent Settings ---
|
// --- Persistent Settings ---
|
||||||
|
|
||||||
@@ -69,6 +69,9 @@ typedef struct {
|
|||||||
bool fn_alt_mode; // xterm compatibility mode (alternate codes for some FN keys)
|
bool fn_alt_mode; // xterm compatibility mode (alternate codes for some FN keys)
|
||||||
u8 config_version;
|
u8 config_version;
|
||||||
u32 display_cooldown_ms;
|
u32 display_cooldown_ms;
|
||||||
|
bool loopback;
|
||||||
|
bool show_buttons;
|
||||||
|
bool show_config_links;
|
||||||
} TerminalConfigBundle;
|
} TerminalConfigBundle;
|
||||||
|
|
||||||
// Live config
|
// Live config
|
||||||
@@ -84,7 +87,7 @@ enum MTM {
|
|||||||
MTM_NONE = 0,
|
MTM_NONE = 0,
|
||||||
MTM_X10 = 1,
|
MTM_X10 = 1,
|
||||||
MTM_NORMAL = 2,
|
MTM_NORMAL = 2,
|
||||||
MTM_BUTTON_MOTION = 3,
|
MTM_BUTTON_MOTION = 3, // any higher mode tracks motion
|
||||||
MTM_ANY_MOTION = 4,
|
MTM_ANY_MOTION = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,10 +124,10 @@ void screen_set_button_text(int num, const char *text);
|
|||||||
// --- Encoding ---
|
// --- Encoding ---
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CS_USASCII = 'B',
|
CS_B_USASCII = 'B',
|
||||||
CS_UKASCII = 'A',
|
CS_A_UKASCII = 'A',
|
||||||
CS_DEC_SUPPLEMENTAL = '0',
|
CS_0_DEC_SUPPLEMENTAL = '0',
|
||||||
CS_DOS_437 = '1',
|
CS_1_DOS_437 = '1',
|
||||||
} CHARSET;
|
} CHARSET;
|
||||||
|
|
||||||
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@
|
|||||||
#ifndef ESP_VT100_FIRMWARE_VERSION_H
|
#ifndef ESP_VT100_FIRMWARE_VERSION_H
|
||||||
#define ESP_VT100_FIRMWARE_VERSION_H
|
#define ESP_VT100_FIRMWARE_VERSION_H
|
||||||
|
|
||||||
#define FW_V_MAJOR 0
|
#define FW_V_MAJOR 8
|
||||||
#define FW_V_MINOR 7
|
#define FW_V_MINOR 0
|
||||||
#define FW_V_PATCH 1
|
#define FW_V_PATCH 1
|
||||||
|
|
||||||
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH
|
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH
|
||||||
|
|||||||
Reference in New Issue
Block a user