From ba9c757cdcf9e6edacd1a6355eea49769e07f173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Wed, 6 Sep 2017 14:21:38 +0200 Subject: [PATCH] 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 --- CMakeLists.txt | 2 +- build_web.sh | 5 + html_orig/_debug_replacements.php | 7 +- html_orig/base.php | 75 ++ html_orig/css/app.css | 93 +- html_orig/dump_js_lang.php | 1 + .../img/{adapter.jpg => adapter.jpg.orig} | Bin html_orig/img/vt100.jpg | Bin 18503 -> 11088 bytes html_orig/img/vt100.jpg.orig | Bin 0 -> 18503 bytes html_orig/index.php | 47 +- html_orig/js/app.js | 231 +++-- html_orig/jssrc/term.js | 195 ++-- html_orig/jssrc/utils.js | 35 + html_orig/jssrc/wifi.js | 1 - html_orig/lang/en.php | 16 +- html_orig/pages/_tail.php | 4 + html_orig/pages/cfg_term.php | 26 +- html_orig/pages/cfg_wifi.php | 2 +- html_orig/pages/help.php | 885 +----------------- html_orig/pages/help/charsets.php | 80 ++ html_orig/pages/help/cmd_cursor.php | 199 ++++ html_orig/pages/help/cmd_screen.php | 63 ++ html_orig/pages/help/cmd_system.php | 84 ++ html_orig/pages/help/input.php | 254 +++++ html_orig/pages/help/nomenclature.php | 84 ++ html_orig/pages/help/screen_behavior.php | 17 + html_orig/pages/help/sgr_colors.php | 65 ++ html_orig/pages/help/sgr_styles.php | 26 + html_orig/pages/help/troubleshooting.php | 33 + html_orig/pages/term.php | 16 +- html_orig/sass/app.scss | 2 + html_orig/sass/form/_form_layout.scss | 1 + html_orig/sass/layout/_box.scss | 6 +- html_orig/sass/pages/_about.scss | 46 + html_orig/sass/pages/_term.scss | 109 ++- user/apars_csi.c | 8 + user/apars_osc.c | 2 +- user/cgi_term_cfg.c | 18 + user/character_sets.h | 169 ++++ user/screen.c | 202 +--- user/screen.h | 17 +- user/version.h | 4 +- 42 files changed, 1793 insertions(+), 1337 deletions(-) rename html_orig/img/{adapter.jpg => adapter.jpg.orig} (100%) create mode 100644 html_orig/img/vt100.jpg.orig create mode 100644 html_orig/pages/help/charsets.php create mode 100644 html_orig/pages/help/cmd_cursor.php create mode 100644 html_orig/pages/help/cmd_screen.php create mode 100644 html_orig/pages/help/cmd_system.php create mode 100644 html_orig/pages/help/input.php create mode 100644 html_orig/pages/help/nomenclature.php create mode 100644 html_orig/pages/help/screen_behavior.php create mode 100644 html_orig/pages/help/sgr_colors.php create mode 100644 html_orig/pages/help/sgr_styles.php create mode 100644 html_orig/pages/help/troubleshooting.php create mode 100644 user/character_sets.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bebbdb..33ed3d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,7 +141,7 @@ set(SOURCE_FILES user/apars_osc.c user/apars_osc.h user/apars_dcs.c - user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h) + user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h user/character_sets.h) include_directories(include) include_directories(user) diff --git a/build_web.sh b/build_web.sh index b794ccd..72ad0eb 100755 --- a/build_web.sh +++ b/build_web.sh @@ -19,3 +19,8 @@ rm html/css/app.css.map cp html_orig/img/* html/img/ cp html_orig/favicon.ico html/favicon.ico + +# cleanup +find html/ -name "*.orig" -delete +find html/ -name "*.xcf" -delete +find html/ -name "*~" -delete diff --git a/html_orig/_debug_replacements.php b/html_orig/_debug_replacements.php index e154ce0..b02463f 100644 --- a/html_orig/_debug_replacements.php +++ b/html_orig/_debug_replacements.php @@ -15,10 +15,9 @@ return [ 'btn5' => '5', 'labels_seq' => 'TESPTerm local debug1235', - 'screenData' => '  HELLOx NRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //, - 'parser_tout_ms' => 10, - 'display_tout_ms' => 20, + 'display_tout_ms' => 15, + 'display_cooldown_ms' => 35, 'fn_alt_mode' => '1', 'opmode' => '2', @@ -61,6 +60,8 @@ return [ 'term_height' => '10', 'default_bg' => '0', 'default_fg' => '7', + 'show_buttons' => '1', + 'show_config_links' => '1', 'uart_baud' => 115200, 'uart_stopbits' => 1, diff --git a/html_orig/base.php b/html_orig/base.php index 925d057..c4531b1 100644 --- a/html_orig/base.php +++ b/html_orig/base.php @@ -69,3 +69,78 @@ function include_str($code) fclose($tmp); return $ret; } + +if (!function_exists('utf8')) { + function utf8($num) + { + if($num<=0x7F) return chr($num); + if($num<=0x7FF) return chr(($num>>6)+192).chr(($num&63)+128); + if($num<=0xFFFF) return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128); + if($num<=0x1FFFFF) return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128); + return ''; + } +} + +if (!function_exists('load_esp_charsets')) { + function load_esp_charsets() { + $chsf = __DIR__ . '/../user/character_sets.h'; + $re_table = '/\/\/ %%BEGIN:(.)%%\s*(.*?)\s*\/\/ %%END:\1%%/s'; + preg_match_all($re_table, file_get_contents($chsf), $m_tbl); + + $re_bounds = '/#define CODEPAGE_(.)_BEGIN\s+(\d+)\n#define CODEPAGE_\1_END\s+(\d+)/'; + preg_match_all($re_bounds, file_get_contents($chsf), $m_bounds); + + $cps = []; + + foreach ($m_tbl[2] as $i => $str) { + $name = $m_tbl[1][$i]; + $start = intval($m_bounds[2][$i]); + $table = []; + $str = preg_replace('/,\s*\/\/[^\n]*/', '', $str); + $rows = explode("\n", $str); + $rows = array_map('trim', $rows); + + foreach($rows as $j => $v) { + if (strpos($v, '0x') === 0) { + $v = substr($v, 2); + $v = hexdec($v); + } else { + $v = intval($v); + } + $ascii = $start+$j; + $table[] = [ + $ascii, + chr($ascii), + utf8($v==0? $ascii :$v), + ]; + } + $cps[$name] = $table; + } + return $cps; + } +} + +if (!function_exists('tplSubs')) { + function tplSubs($str, $reps) + { + return preg_replace_callback('/%(j:|js:|h:|html:)?([a-z0-9-_.]+)%/i', function ($m) use ($reps) { + $key = $m[2]; + if (array_key_exists($key, $reps)) { + $val = $reps[$key]; + } else { + $val = ''; + } + switch ($m[1]) { + case 'j:': + case 'js:': + $v = json_encode($val); + return substr($v, 1, strlen($v) - 2); + case 'h:': + case 'html:': + return htmlspecialchars($val); + default: + return $val; + } + }, $str); + } +} diff --git a/html_orig/css/app.css b/html_orig/css/app.css index 2c759a8..0518663 100644 --- a/html_orig/css/app.css +++ b/html_orig/css/app.css @@ -570,10 +570,13 @@ ul { #loader.show { opacity: 1; } +.botpad { + display: block; + height: 5em; } + .Box { display: block; max-width: 900px; - line-height: 1.35em; margin-top: 1rem; padding: 0.61805rem 1rem; border-radius: 3px; @@ -904,6 +907,7 @@ form { vertical-align: middle; margin: 12px auto; text-align: left; + line-height: 1.35em; display: flex; flex-direction: row; align-items: center; } @@ -1147,50 +1151,58 @@ body.term #content { @media screen and (max-width: 544px) { body.term #content h1 { font-size: 1.42383em; } } -body.term #screen { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - font-family: monospace; - font-size: 20px; + +#screen { white-space: nowrap; background: #111213; padding: 6px; display: inline-block; - border: 2px solid #3983CD; } - body.term #screen span { - white-space: pre; - cursor: pointer; - display: inline-block; - line-height: 1.15em; - width: 0.6em; - overflow: visible; } -body.term #buttons { + border: 2px solid #3983CD; + font-size: 24px; + font-family: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace; } + #screen span { + white-space: pre; } + #screen > span { + position: relative; + cursor: pointer; } + #screen > span::before { + content: " "; } + #screen > span > span { + position: absolute; + left: 0; + z-index: 1; } + #screen.noselect { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +#action-buttons { margin-top: 10px; white-space: nowrap; } - body.term #buttons button { + #action-buttons button { margin: 0 3px; padding: 8px 5px; min-width: 62px; cursor: pointer; font-weight: bold; } -body.term #botnav { + +#term-nav { padding-top: 1.5em; text-align: center; } - body.term #botnav a { + #term-nav a { padding: 0 0.38198rem; text-decoration: underline; } - body.term #botnav a, body.term #botnav a:visited, body.term #botnav a:link { + #term-nav a, #term-nav a:visited, #term-nav a:link { color: #336085; } - body.term #botnav a:hover { + #term-nav a:hover { color: #5abfff; } - body.term #botnav .icn-keyboard { + #term-nav .icn-keyboard { text-decoration: none; font-size: 150%; vertical-align: middle; } -#termwrap { +#term-wrap { text-align: center; } #softkb-input { @@ -1677,6 +1689,39 @@ body.term #botnav { .tscroll { overflow-x: auto; } +.charset { + line-height: 1; } + .charset div { + display: inline-block; + width: 2.5em; + border: 1px solid #666; + height: 3em; + margin: 1px; + position: relative; } + .charset div span { + display: block; + position: absolute; } + .charset div span:nth-child(1) { + left: .2em; + top: .2em; + height: 1em; + font-size: 85%; + color: #999; } + .charset div span:nth-child(2) { + right: .2em; + top: .2em; + height: 1em; + font-size: 85%; + color: #999; } + .charset div span:nth-child(3) { + width: 100%; + font-size: 105%; + text-align: center; + bottom: .4em; + font-family: "DejaVu Sans Mono", "Liberation Mono", "Inconsolata", monospace; } + .charset div.none { + opacity: .4; } + @media screen and (min-width: 545px) { .mq-phone { display: none !important; } } diff --git a/html_orig/dump_js_lang.php b/html_orig/dump_js_lang.php index 14b0db6..ab2f976 100755 --- a/html_orig/dump_js_lang.php +++ b/html_orig/dump_js_lang.php @@ -8,6 +8,7 @@ $selected = [ 'wifi.connected_ip_is', 'wifi.not_conn', 'wifi.enter_passwd', + 'wifi.passwd_saved', ]; $out = []; diff --git a/html_orig/img/adapter.jpg b/html_orig/img/adapter.jpg.orig similarity index 100% rename from html_orig/img/adapter.jpg rename to html_orig/img/adapter.jpg.orig diff --git a/html_orig/img/vt100.jpg b/html_orig/img/vt100.jpg index 909461afa7d6d3210eb1b8f378bf0a26ca79d87e..70460424146a7244d0c97278296eb631af97826c 100644 GIT binary patch literal 11088 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 Jl5KyO|6gXHiYfpA literal 18503 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