diff --git a/html/css/app.css b/html/css/app.css
index 5e0927c..ce314f4 100644
--- a/html/css/app.css
+++ b/html/css/app.css
@@ -438,41 +438,52 @@ body {
body > * {
margin-left: auto;
margin-right: auto; }
- body h1 {
- text-align: center;
- font-size: 2.02729em;
- margin-top: 0;
- margin-bottom: 1rem; }
- @media screen and (max-width: 544px) {
- body h1 {
- font-size: 1.42383em;
- margin-bottom: 0.61805rem; } }
- @media screen and (min-width: 545px) and (max-width: 1000px) {
- body h1 {
- font-size: 1.80203em; } }
- body h2 {
- font-size: 1.26563em;
- margin-bottom: 0.61805rem; }
- body h2:first-child {
- margin-top: 0; }
- body td, body th {
- padding: 0.38198rem;
- white-space: nowrap; }
- @media screen and (max-width: 544px) {
- body td, body th {
- padding: 0.23608rem; } }
- body tbody th {
- text-align: right;
- width: 130px;
- color: white; }
- @media screen and (max-width: 544px) {
- body tbody th {
- width: auto; } }
- body tbody td input[type="text"], body tbody td input[type="number"] {
- width: 10em; }
- @media screen and (max-width: 544px) {
- body tbody td input[type="text"], body tbody td input[type="number"] {
- width: 8em; } }
+
+h1, h2 {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+
+h1 {
+ text-align: center;
+ font-size: 2.02729em;
+ margin-top: 0;
+ margin-bottom: 1rem; }
+ @media screen and (max-width: 544px) {
+ h1 {
+ font-size: 1.42383em;
+ margin-bottom: 0.61805rem; } }
+ @media screen and (min-width: 545px) and (max-width: 1000px) {
+ h1 {
+ font-size: 1.80203em; } }
+
+h2 {
+ font-size: 1.26563em;
+ margin-bottom: 0.61805rem; }
+ h2:first-child {
+ margin-top: 0; }
+
+td, th {
+ padding: 0.38198rem;
+ white-space: nowrap; }
+ @media screen and (max-width: 544px) {
+ td, th {
+ padding: 0.23608rem; } }
+
+tbody th {
+ text-align: right;
+ width: 130px;
+ color: white; }
+ @media screen and (max-width: 544px) {
+ tbody th {
+ width: auto; } }
+
+tbody td input[type="text"], tbody td input[type="number"] {
+ width: 10em; }
+ @media screen and (max-width: 544px) {
+ tbody td input[type="text"], tbody td input[type="number"] {
+ width: 8em; } }
#loader {
position: absolute;
diff --git a/html/js/app.js b/html/js/app.js
index aae60c2..bdc2c45 100644
--- a/html/js/app.js
+++ b/html/js/app.js
@@ -894,6 +894,7 @@ $._loader = function(vis) {
var W, H;
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
var screen = [];
+ var blinkIval;
/** Colors table */
var CLR = [// dark gray #2E3436
@@ -1071,7 +1072,8 @@ $._loader = function(vis) {
}
/* Cursor blinking */
- setInterval(function() {
+ clearInterval(blinkIval);
+ blinkIval = setInterval(function() {
cursor.a = !cursor.a;
if (cursor.hidden) {
cursor.a = false;
diff --git a/html_orig/css/app.css b/html_orig/css/app.css
index 5e0927c..ce314f4 100644
--- a/html_orig/css/app.css
+++ b/html_orig/css/app.css
@@ -438,41 +438,52 @@ body {
body > * {
margin-left: auto;
margin-right: auto; }
- body h1 {
- text-align: center;
- font-size: 2.02729em;
- margin-top: 0;
- margin-bottom: 1rem; }
- @media screen and (max-width: 544px) {
- body h1 {
- font-size: 1.42383em;
- margin-bottom: 0.61805rem; } }
- @media screen and (min-width: 545px) and (max-width: 1000px) {
- body h1 {
- font-size: 1.80203em; } }
- body h2 {
- font-size: 1.26563em;
- margin-bottom: 0.61805rem; }
- body h2:first-child {
- margin-top: 0; }
- body td, body th {
- padding: 0.38198rem;
- white-space: nowrap; }
- @media screen and (max-width: 544px) {
- body td, body th {
- padding: 0.23608rem; } }
- body tbody th {
- text-align: right;
- width: 130px;
- color: white; }
- @media screen and (max-width: 544px) {
- body tbody th {
- width: auto; } }
- body tbody td input[type="text"], body tbody td input[type="number"] {
- width: 10em; }
- @media screen and (max-width: 544px) {
- body tbody td input[type="text"], body tbody td input[type="number"] {
- width: 8em; } }
+
+h1, h2 {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none; }
+
+h1 {
+ text-align: center;
+ font-size: 2.02729em;
+ margin-top: 0;
+ margin-bottom: 1rem; }
+ @media screen and (max-width: 544px) {
+ h1 {
+ font-size: 1.42383em;
+ margin-bottom: 0.61805rem; } }
+ @media screen and (min-width: 545px) and (max-width: 1000px) {
+ h1 {
+ font-size: 1.80203em; } }
+
+h2 {
+ font-size: 1.26563em;
+ margin-bottom: 0.61805rem; }
+ h2:first-child {
+ margin-top: 0; }
+
+td, th {
+ padding: 0.38198rem;
+ white-space: nowrap; }
+ @media screen and (max-width: 544px) {
+ td, th {
+ padding: 0.23608rem; } }
+
+tbody th {
+ text-align: right;
+ width: 130px;
+ color: white; }
+ @media screen and (max-width: 544px) {
+ tbody th {
+ width: auto; } }
+
+tbody td input[type="text"], tbody td input[type="number"] {
+ width: 10em; }
+ @media screen and (max-width: 544px) {
+ tbody td input[type="text"], tbody td input[type="number"] {
+ width: 8em; } }
#loader {
position: absolute;
diff --git a/html_orig/jssrc/term.js b/html_orig/jssrc/term.js
index 9d73eb8..916c2c0 100644
--- a/html_orig/jssrc/term.js
+++ b/html_orig/jssrc/term.js
@@ -6,6 +6,7 @@
var W, H;
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
var screen = [];
+ var blinkIval;
/** Colors table */
var CLR = [// dark gray #2E3436
@@ -183,7 +184,8 @@
}
/* Cursor blinking */
- setInterval(function() {
+ clearInterval(blinkIval);
+ blinkIval = setInterval(function() {
cursor.a = !cursor.a;
if (cursor.hidden) {
cursor.a = false;
diff --git a/html_orig/sass/_layout.scss b/html_orig/sass/_layout.scss
index 9326f07..56c06c3 100644
--- a/html_orig/sass/_layout.scss
+++ b/html_orig/sass/_layout.scss
@@ -78,55 +78,59 @@ body {
margin-left: auto;
margin-right: auto;
}
+}
- h1 {
- text-align: center;
- font-size: fsize(6);
- margin-top: 0;
- margin-bottom: dist(0);
+h1,h2 {
+ @include noselect();
+}
- @include media($phone) {
- font-size: fsize(3);
- margin-bottom: dist(-1);
- }
+h1 {
+ text-align: center;
+ font-size: fsize(6);
+ margin-top: 0;
+ margin-bottom: dist(0);
- @include media($tablet) {
- font-size: fsize(5);
- }
+ @include media($phone) {
+ font-size: fsize(3);
+ margin-bottom: dist(-1);
}
- h2 {
- font-size: fsize(2);
- margin-bottom: dist(-1);
- &:first-child{margin-top:0}
+ @include media($tablet) {
+ font-size: fsize(5);
}
+}
+
+h2 {
+ font-size: fsize(2);
+ margin-bottom: dist(-1);
+ &:first-child{margin-top:0}
+}
- td, th {
- padding: dist(-2);
- white-space: nowrap;
+td, th {
+ padding: dist(-2);
+ white-space: nowrap;
- @include media($phone) {
- padding: dist(-3);
- }
+ @include media($phone) {
+ padding: dist(-3);
}
+}
- tbody th {
- text-align: right;
- width: $form-label-w;
- color: $c-form-label-fg;
+tbody th {
+ text-align: right;
+ width: $form-label-w;
+ color: $c-form-label-fg;
- @include media($phone) {
- width: auto;
- }
+ @include media($phone) {
+ width: auto;
}
+}
- tbody td {
- input[type="text"], input[type="number"] {
- width: 10em;
+tbody td {
+ input[type="text"], input[type="number"] {
+ width: 10em;
- @include media($phone) {
- width: 8em;
- }
+ @include media($phone) {
+ width: 8em;
}
}
}
diff --git a/user/ansi_parser.c b/user/ansi_parser.c
index 9edd515..9791a7c 100644
--- a/user/ansi_parser.c
+++ b/user/ansi_parser.c
@@ -182,28 +182,49 @@ handle_plainchar(char c)
screen_putchar(c);
}
+void ICACHE_FLASH_ATTR
+handle_OSC_FactoryReset(void)
+{
+ info("OSC: Factory reset");
+
+ warn("NOT IMPLEMENTED");
+ // TODO
+}
+
+void ICACHE_FLASH_ATTR
+handle_OSC_SetScreenSize(int rows, int cols)
+{
+ info("OSC: Set screen size to %d x %d", rows, cols);
+
+ screen_resize(rows, cols);
+}
+
+
/* Ragel constants block */
-/* #line 188 "user/ansi_parser.c" */
+/* #line 206 "user/ansi_parser.c" */
static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 1,
- 7, 1, 8, 1, 9
+ 7, 1, 8, 1, 9, 1, 10
};
static const char _ansi_eof_actions[] = {
- 0, 15, 15, 13, 13, 0, 0
+ 0, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 0, 0,
+ 0
};
static const int ansi_start = 1;
-static const int ansi_first_final = 5;
+static const int ansi_first_final = 14;
static const int ansi_error = 0;
static const int ansi_en_CSI_body = 3;
+static const int ansi_en_OSC_body = 5;
static const int ansi_en_main = 1;
-/* #line 187 "user/ansi_parser.rl" */
+/* #line 205 "user/ansi_parser.rl" */
/**
@@ -240,17 +261,17 @@ ansi_parser(const char *newdata, size_t len)
// Init Ragel on the first run
if (cs == -1) {
-/* #line 244 "user/ansi_parser.c" */
+/* #line 265 "user/ansi_parser.c" */
{
cs = ansi_start;
}
-/* #line 223 "user/ansi_parser.rl" */
+/* #line 241 "user/ansi_parser.rl" */
}
// The parser
-/* #line 254 "user/ansi_parser.c" */
+/* #line 275 "user/ansi_parser.c" */
{
const char *_acts;
unsigned int _nacts;
@@ -274,79 +295,137 @@ case 2:
goto tr2;
case 0:
goto _out;
-case 5:
+case 14:
if ( (*p) == 27 )
goto tr1;
goto tr0;
case 3:
if ( (*p) == 59 )
- goto tr9;
+ goto tr8;
if ( (*p) < 60 ) {
if ( (*p) > 47 ) {
if ( 48 <= (*p) && (*p) <= 57 )
- goto tr8;
+ goto tr7;
} else if ( (*p) >= 32 )
- goto tr7;
+ goto tr6;
} else if ( (*p) > 64 ) {
if ( (*p) > 90 ) {
if ( 97 <= (*p) && (*p) <= 122 )
- goto tr10;
+ goto tr9;
} else if ( (*p) >= 65 )
- goto tr10;
+ goto tr9;
} else
- goto tr7;
- goto tr6;
+ goto tr6;
+ goto tr2;
case 4:
if ( (*p) == 59 )
- goto tr9;
+ goto tr8;
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
- goto tr8;
+ goto tr7;
} else if ( (*p) > 90 ) {
if ( 97 <= (*p) && (*p) <= 122 )
- goto tr10;
+ goto tr9;
} else
- goto tr10;
- goto tr6;
+ goto tr9;
+ goto tr2;
+case 15:
+ goto tr2;
+case 5:
+ switch( (*p) ) {
+ case 70: goto tr10;
+ case 87: goto tr11;
+ }
+ goto tr2;
case 6:
- goto tr6;
+ if ( (*p) == 82 )
+ goto tr12;
+ goto tr2;
+case 7:
+ switch( (*p) ) {
+ case 7: goto tr13;
+ case 27: goto tr14;
+ }
+ goto tr2;
+case 16:
+ goto tr2;
+case 8:
+ if ( (*p) == 92 )
+ goto tr13;
+ goto tr2;
+case 9:
+ if ( 48 <= (*p) && (*p) <= 57 )
+ goto tr15;
+ goto tr2;
+case 10:
+ if ( (*p) == 59 )
+ goto tr16;
+ if ( 48 <= (*p) && (*p) <= 57 )
+ goto tr15;
+ goto tr2;
+case 11:
+ if ( 48 <= (*p) && (*p) <= 57 )
+ goto tr17;
+ goto tr2;
+case 12:
+ switch( (*p) ) {
+ case 7: goto tr18;
+ case 27: goto tr19;
+ }
+ if ( 48 <= (*p) && (*p) <= 57 )
+ goto tr17;
+ goto tr2;
+case 13:
+ if ( (*p) == 92 )
+ goto tr18;
+ goto tr2;
}
tr2: cs = 0; goto f0;
- tr6: cs = 0; goto f5;
tr0: cs = 1; goto f1;
tr1: cs = 2; goto _again;
+ tr6: cs = 4; goto f5;
tr7: cs = 4; goto f6;
tr8: cs = 4; goto f7;
- tr9: cs = 4; goto f8;
- tr3: cs = 5; goto f2;
- tr4: cs = 5; goto f3;
- tr5: cs = 5; goto f4;
- tr10: cs = 6; goto f9;
+ tr10: cs = 6; goto _again;
+ tr12: cs = 7; goto _again;
+ tr14: cs = 8; goto _again;
+ tr11: cs = 9; goto _again;
+ tr15: cs = 10; goto f6;
+ tr16: cs = 11; goto f7;
+ tr17: cs = 12; goto f6;
+ tr19: cs = 13; goto _again;
+ tr3: cs = 14; goto f2;
+ tr4: cs = 14; goto f3;
+ tr5: cs = 14; goto f4;
+ tr9: cs = 15; goto f8;
+ tr13: cs = 16; goto f9;
+ tr18: cs = 16; goto f10;
f1: _acts = _ansi_actions + 1; goto execFuncs;
f2: _acts = _ansi_actions + 3; goto execFuncs;
- f6: _acts = _ansi_actions + 5; goto execFuncs;
- f7: _acts = _ansi_actions + 7; goto execFuncs;
- f8: _acts = _ansi_actions + 9; goto execFuncs;
- f9: _acts = _ansi_actions + 11; goto execFuncs;
- f5: _acts = _ansi_actions + 13; goto execFuncs;
- f0: _acts = _ansi_actions + 15; goto execFuncs;
- f3: _acts = _ansi_actions + 17; goto execFuncs;
- f4: _acts = _ansi_actions + 19; goto execFuncs;
+ f5: _acts = _ansi_actions + 5; goto execFuncs;
+ f6: _acts = _ansi_actions + 7; goto execFuncs;
+ f7: _acts = _ansi_actions + 9; goto execFuncs;
+ f8: _acts = _ansi_actions + 11; goto execFuncs;
+ f0: _acts = _ansi_actions + 13; goto execFuncs;
+ f3: _acts = _ansi_actions + 15; goto execFuncs;
+ f9: _acts = _ansi_actions + 17; goto execFuncs;
+ f10: _acts = _ansi_actions + 19; goto execFuncs;
+ f4: _acts = _ansi_actions + 21; goto execFuncs;
execFuncs:
_nacts = *_acts++;
while ( _nacts-- > 0 ) {
switch ( *_acts++ ) {
case 0:
-/* #line 233 "user/ansi_parser.rl" */
+/* #line 251 "user/ansi_parser.rl" */
{
handle_plainchar((*p));
}
break;
case 1:
-/* #line 240 "user/ansi_parser.rl" */
+/* #line 258 "user/ansi_parser.rl" */
{
/* Reset the CSI builder */
csi_leading = csi_char = 0;
@@ -361,13 +440,13 @@ execFuncs:
}
break;
case 2:
-/* #line 253 "user/ansi_parser.rl" */
+/* #line 271 "user/ansi_parser.rl" */
{
csi_leading = (*p);
}
break;
case 3:
-/* #line 257 "user/ansi_parser.rl" */
+/* #line 275 "user/ansi_parser.rl" */
{
/* x10 + digit */
if (csi_ni < CSI_N_MAX) {
@@ -376,13 +455,13 @@ execFuncs:
}
break;
case 4:
-/* #line 264 "user/ansi_parser.rl" */
+/* #line 282 "user/ansi_parser.rl" */
{
csi_ni++;
}
break;
case 5:
-/* #line 268 "user/ansi_parser.rl" */
+/* #line 286 "user/ansi_parser.rl" */
{
csi_char = (*p);
@@ -392,33 +471,49 @@ execFuncs:
}
break;
case 6:
-/* #line 276 "user/ansi_parser.rl" */
+/* #line 294 "user/ansi_parser.rl" */
{
+ warn("Invalid escape sequence discarded.");
{cs = 1; goto _again;}
}
break;
case 7:
-/* #line 280 "user/ansi_parser.rl" */
+/* #line 311 "user/ansi_parser.rl" */
{
- {cs = 1; goto _again;}
+ csi_ni = 0;
+
+ // we reuse the CSI numeric buffer
+ for(int i = 0; i < CSI_N_MAX; i++) {
+ csi_n[i] = 0;
+ }
+
+ {cs = 5; goto _again;}
}
break;
case 8:
-/* #line 292 "user/ansi_parser.rl" */
+/* #line 322 "user/ansi_parser.rl" */
{
- // TODO implement OS control code parsing
+ handle_OSC_FactoryReset();
{cs = 1; goto _again;}
}
break;
case 9:
-/* #line 297 "user/ansi_parser.rl" */
+/* #line 327 "user/ansi_parser.rl" */
+ {
+ handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
+
+ {cs = 1; goto _again;}
+ }
+ break;
+ case 10:
+/* #line 338 "user/ansi_parser.rl" */
{
// Reset screen
handle_RESET_cmd();
{cs = 1; goto _again;}
}
break;
-/* #line 422 "user/ansi_parser.c" */
+/* #line 517 "user/ansi_parser.c" */
}
}
goto _again;
@@ -436,18 +531,13 @@ _again:
while ( __nacts-- > 0 ) {
switch ( *__acts++ ) {
case 6:
-/* #line 276 "user/ansi_parser.rl" */
- {
- {cs = 1; goto _again;}
- }
- break;
- case 7:
-/* #line 280 "user/ansi_parser.rl" */
+/* #line 294 "user/ansi_parser.rl" */
{
+ warn("Invalid escape sequence discarded.");
{cs = 1; goto _again;}
}
break;
-/* #line 451 "user/ansi_parser.c" */
+/* #line 541 "user/ansi_parser.c" */
}
}
}
@@ -455,6 +545,6 @@ _again:
_out: {}
}
-/* #line 315 "user/ansi_parser.rl" */
+/* #line 356 "user/ansi_parser.rl" */
}
diff --git a/user/ansi_parser.rl b/user/ansi_parser.rl
index 46c504d..bab6b71 100644
--- a/user/ansi_parser.rl
+++ b/user/ansi_parser.rl
@@ -180,6 +180,24 @@ handle_plainchar(char c)
screen_putchar(c);
}
+void ICACHE_FLASH_ATTR
+handle_OSC_FactoryReset(void)
+{
+ info("OSC: Factory reset");
+
+ warn("NOT IMPLEMENTED");
+ // TODO
+}
+
+void ICACHE_FLASH_ATTR
+handle_OSC_SetScreenSize(int rows, int cols)
+{
+ info("OSC: Set screen size to %d x %d", rows, cols);
+
+ screen_resize(rows, cols);
+}
+
+
/* Ragel constants block */
%%{
machine ansi;
@@ -273,26 +291,49 @@ ansi_parser(const char *newdata, size_t len)
fgoto main;
}
- action CSI_fail {
+ action errBadSeq {
+ warn("Invalid escape sequence discarded.");
fgoto main;
}
- action main_fail {
+ action back2main {
fgoto main;
}
CSI_body := ((32..47|60..64) @CSI_leading)?
((digit @CSI_digit)* ';' @CSI_semi)*
- (digit @CSI_digit)* alpha @CSI_end $!CSI_fail;
+ (digit @CSI_digit)* alpha @CSI_end $!errBadSeq;
# --- OSC commands (Operating System Commands) ---
# Module parametrisation
action OSC_start {
- // TODO implement OS control code parsing
+ csi_ni = 0;
+
+ // we reuse the CSI numeric buffer
+ for(int i = 0; i < CSI_N_MAX; i++) {
+ csi_n[i] = 0;
+ }
+
+ fgoto OSC_body;
+ }
+
+ action OSC_fr {
+ handle_OSC_FactoryReset();
+ fgoto main;
+ }
+
+ action OSC_resize {
+ handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
+
fgoto main;
}
+
+ OSC_body := (
+ ("FR" ('\a' | ESC '\\') @OSC_fr) |
+ ('W' (digit @CSI_digit)+ ';' @CSI_semi (digit @CSI_digit)+ ('\a' | ESC '\\') @OSC_resize)
+ ) $!errBadSeq;
action RESET_cmd {
// Reset screen
@@ -309,7 +350,7 @@ ansi_parser(const char *newdata, size_t len)
']' @OSC_start |
'c' @RESET_cmd
)
- )+ $!main_fail;
+ )+ $!errBadSeq;
write exec;
}%%
diff --git a/user/screen.c b/user/screen.c
index 5320d39..4f03887 100644
--- a/user/screen.c
+++ b/user/screen.c
@@ -189,20 +189,28 @@ screen_clear_line(ClearMode mode)
/**
* Change the screen size
*
- * @param w - new width
- * @param h - new height
+ * @param cols - new width
+ * @param rows - new height
*/
void ICACHE_FLASH_ATTR
-screen_resize(Coordinate w, Coordinate h)
+screen_resize(Coordinate rows, Coordinate cols)
{
NOTIFY_LOCK();
// sanitize
- if (w < 1) w = 1;
- if (h < 1) h = 1;
+ if (cols < 1 || rows < 1) {
+ error("Screen size must be positive");
+ goto done;
+ }
+
+ if (cols * rows > MAX_SCREEN_SIZE) {
+ error("Max screen size exceeded");
+ goto done;
+ }
- W = w;
- H = h;
+ W = cols;
+ H = rows;
screen_reset();
+done:
NOTIFY_DONE();
}
@@ -579,11 +587,11 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
ss->lastFg = 0;
ss->lastChar = '\0';
- bufprint("{\"w\":%d,\"h\":%d,\"x\":%d,\"y\":%d,\"cv\":%d,\"screen\":\"", W, H, cursor.x, cursor.y, cursor.visible);
+ bufprint("{\n \"w\": %d, \"h\": %d,\n \"x\": %d, \"y\": %d,\n \"cv\": %d,\n \"screen\": \"", W, H, cursor.x, cursor.y, cursor.visible);
}
int i = ss->index;
- while(i < W*H && remain > 6) {
+ while(i < W*H && remain > 12) {
cell = cell0 = &screen[i];
// Count how many times same as previous
@@ -598,11 +606,25 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
}
if (repCnt == 0) {
+ // All this crap is needed because it's JSON and also
+ // embedded in HTML (hence the angle brackets)
+
if (cell0->fg == ss->lastFg && cell0->bg == ss->lastBg) {
// same colors as previous
- bufprint(",%c", cell0->c);
+ bufprint(",");
} else {
- bufprint("%X%X%c", cell0->fg, cell0->bg, cell0->c);
+ bufprint("%X%X", cell0->fg, cell0->bg);
+ }
+
+ char c = cell0->c;
+ if (c == '"' || c == '\\') {
+ bufprint("\\%c", c);
+ }
+ else if (c == '<' || c == '>' || c == '\'' || c == '/' || c == '&') {
+ bufprint("\\u00%02X", (int)c);
+ }
+ else {
+ bufprint("%c", c);
}
ss->lastFg = cell0->fg;
@@ -633,7 +655,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
}
if (remain >= 3) {
- bufprint("\"}");
+ bufprint("\"\n}");
return HTTPD_CGI_DONE;
} else {
return HTTPD_CGI_MORE;
diff --git a/user/screen.h b/user/screen.h
index 677b6c4..d8a02ad 100644
--- a/user/screen.h
+++ b/user/screen.h
@@ -62,7 +62,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
void screen_init(void);
/** Change the screen size */
-void screen_resize(Coordinate w, Coordinate h);
+void screen_resize(Coordinate rows, Coordinate cols);
// --- Clearing ---
diff --git a/user/user_main.c b/user/user_main.c
index 305c195..0f33295 100644
--- a/user/user_main.c
+++ b/user/user_main.c
@@ -50,17 +50,20 @@ static ETSTimer prHeapTimer;
/** Periodically show heap usage */
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
{
- static uint32_t cnt = 0;
static uint32_t last = 0;
- if (cnt == 5) {
- uint32_t heap = system_get_free_heap_size();
- dbg("Free heap: %d bytes (~ %d)", heap, (heap-last));
- cnt = 0;
- last = heap;
+ uint32_t heap = system_get_free_heap_size();
+ int32_t diff = (heap-last);
+ const char *cc = "+";
+ if (diff<0) cc = "";
+
+ if (diff == 0) {
+ dbg("Free heap: %d bytes", heap);
+ } else {
+ dbg("Free heap: %d bytes (%s%d)", heap, cc, diff);
}
- cnt++;
+ last = heap;
}
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
@@ -97,7 +100,7 @@ void ICACHE_FLASH_ATTR user_init(void)
// Heap use timer & blink
os_timer_disarm(&prHeapTimer);
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
- os_timer_arm(&prHeapTimer, 1000, 1);
+ os_timer_arm(&prHeapTimer, 5000, 1);
// The terminal screen
screen_init();