FIXED STUPID JSON BUG YOOOO

pull/30/head
Ondřej Hruška 7 years ago
parent 0f7fb9430c
commit f8d848f383
  1. 81
      html/css/app.css
  2. 4
      html/js/app.js
  3. 81
      html_orig/css/app.css
  4. 4
      html_orig/jssrc/term.js
  5. 74
      html_orig/sass/_layout.scss
  6. 206
      user/ansi_parser.c
  7. 51
      user/ansi_parser.rl
  8. 46
      user/screen.c
  9. 2
      user/screen.h
  10. 19
      user/user_main.c

@ -438,41 +438,52 @@ body {
body > * { body > * {
margin-left: auto; margin-left: auto;
margin-right: auto; } margin-right: auto; }
body h1 {
text-align: center; h1, h2 {
font-size: 2.02729em; -webkit-user-select: none;
margin-top: 0; -moz-user-select: none;
margin-bottom: 1rem; } -ms-user-select: none;
@media screen and (max-width: 544px) { user-select: none; }
body h1 {
font-size: 1.42383em; h1 {
margin-bottom: 0.61805rem; } } text-align: center;
@media screen and (min-width: 545px) and (max-width: 1000px) { font-size: 2.02729em;
body h1 { margin-top: 0;
font-size: 1.80203em; } } margin-bottom: 1rem; }
body h2 { @media screen and (max-width: 544px) {
font-size: 1.26563em; h1 {
margin-bottom: 0.61805rem; } font-size: 1.42383em;
body h2:first-child { margin-bottom: 0.61805rem; } }
margin-top: 0; } @media screen and (min-width: 545px) and (max-width: 1000px) {
body td, body th { h1 {
padding: 0.38198rem; font-size: 1.80203em; } }
white-space: nowrap; }
@media screen and (max-width: 544px) { h2 {
body td, body th { font-size: 1.26563em;
padding: 0.23608rem; } } margin-bottom: 0.61805rem; }
body tbody th { h2:first-child {
text-align: right; margin-top: 0; }
width: 130px;
color: white; } td, th {
@media screen and (max-width: 544px) { padding: 0.38198rem;
body tbody th { white-space: nowrap; }
width: auto; } } @media screen and (max-width: 544px) {
body tbody td input[type="text"], body tbody td input[type="number"] { td, th {
width: 10em; } padding: 0.23608rem; } }
@media screen and (max-width: 544px) {
body tbody td input[type="text"], body tbody td input[type="number"] { tbody th {
width: 8em; } } 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 { #loader {
position: absolute; position: absolute;

@ -894,6 +894,7 @@ $._loader = function(vis) {
var W, H; var W, H;
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false}; var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
var screen = []; var screen = [];
var blinkIval;
/** Colors table */ /** Colors table */
var CLR = [// dark gray #2E3436 var CLR = [// dark gray #2E3436
@ -1071,7 +1072,8 @@ $._loader = function(vis) {
} }
/* Cursor blinking */ /* Cursor blinking */
setInterval(function() { clearInterval(blinkIval);
blinkIval = setInterval(function() {
cursor.a = !cursor.a; cursor.a = !cursor.a;
if (cursor.hidden) { if (cursor.hidden) {
cursor.a = false; cursor.a = false;

@ -438,41 +438,52 @@ body {
body > * { body > * {
margin-left: auto; margin-left: auto;
margin-right: auto; } margin-right: auto; }
body h1 {
text-align: center; h1, h2 {
font-size: 2.02729em; -webkit-user-select: none;
margin-top: 0; -moz-user-select: none;
margin-bottom: 1rem; } -ms-user-select: none;
@media screen and (max-width: 544px) { user-select: none; }
body h1 {
font-size: 1.42383em; h1 {
margin-bottom: 0.61805rem; } } text-align: center;
@media screen and (min-width: 545px) and (max-width: 1000px) { font-size: 2.02729em;
body h1 { margin-top: 0;
font-size: 1.80203em; } } margin-bottom: 1rem; }
body h2 { @media screen and (max-width: 544px) {
font-size: 1.26563em; h1 {
margin-bottom: 0.61805rem; } font-size: 1.42383em;
body h2:first-child { margin-bottom: 0.61805rem; } }
margin-top: 0; } @media screen and (min-width: 545px) and (max-width: 1000px) {
body td, body th { h1 {
padding: 0.38198rem; font-size: 1.80203em; } }
white-space: nowrap; }
@media screen and (max-width: 544px) { h2 {
body td, body th { font-size: 1.26563em;
padding: 0.23608rem; } } margin-bottom: 0.61805rem; }
body tbody th { h2:first-child {
text-align: right; margin-top: 0; }
width: 130px;
color: white; } td, th {
@media screen and (max-width: 544px) { padding: 0.38198rem;
body tbody th { white-space: nowrap; }
width: auto; } } @media screen and (max-width: 544px) {
body tbody td input[type="text"], body tbody td input[type="number"] { td, th {
width: 10em; } padding: 0.23608rem; } }
@media screen and (max-width: 544px) {
body tbody td input[type="text"], body tbody td input[type="number"] { tbody th {
width: 8em; } } 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 { #loader {
position: absolute; position: absolute;

@ -6,6 +6,7 @@
var W, H; var W, H;
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false}; var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
var screen = []; var screen = [];
var blinkIval;
/** Colors table */ /** Colors table */
var CLR = [// dark gray #2E3436 var CLR = [// dark gray #2E3436
@ -183,7 +184,8 @@
} }
/* Cursor blinking */ /* Cursor blinking */
setInterval(function() { clearInterval(blinkIval);
blinkIval = setInterval(function() {
cursor.a = !cursor.a; cursor.a = !cursor.a;
if (cursor.hidden) { if (cursor.hidden) {
cursor.a = false; cursor.a = false;

@ -78,55 +78,59 @@ body {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
}
h1 { h1,h2 {
text-align: center; @include noselect();
font-size: fsize(6); }
margin-top: 0;
margin-bottom: dist(0);
@include media($phone) { h1 {
font-size: fsize(3); text-align: center;
margin-bottom: dist(-1); font-size: fsize(6);
} margin-top: 0;
margin-bottom: dist(0);
@include media($tablet) { @include media($phone) {
font-size: fsize(5); font-size: fsize(3);
} margin-bottom: dist(-1);
} }
h2 { @include media($tablet) {
font-size: fsize(2); font-size: fsize(5);
margin-bottom: dist(-1);
&:first-child{margin-top:0}
} }
}
h2 {
font-size: fsize(2);
margin-bottom: dist(-1);
&:first-child{margin-top:0}
}
td, th { td, th {
padding: dist(-2); padding: dist(-2);
white-space: nowrap; white-space: nowrap;
@include media($phone) { @include media($phone) {
padding: dist(-3); padding: dist(-3);
}
} }
}
tbody th { tbody th {
text-align: right; text-align: right;
width: $form-label-w; width: $form-label-w;
color: $c-form-label-fg; color: $c-form-label-fg;
@include media($phone) { @include media($phone) {
width: auto; width: auto;
}
} }
}
tbody td { tbody td {
input[type="text"], input[type="number"] { input[type="text"], input[type="number"] {
width: 10em; width: 10em;
@include media($phone) { @include media($phone) {
width: 8em; width: 8em;
}
} }
} }
} }

@ -182,28 +182,49 @@ handle_plainchar(char c)
screen_putchar(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 */ /* Ragel constants block */
/* #line 188 "user/ansi_parser.c" */ /* #line 206 "user/ansi_parser.c" */
static const char _ansi_actions[] = { static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1, 0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 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[] = { 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_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_error = 0;
static const int ansi_en_CSI_body = 3; static const int ansi_en_CSI_body = 3;
static const int ansi_en_OSC_body = 5;
static const int ansi_en_main = 1; 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 // Init Ragel on the first run
if (cs == -1) { if (cs == -1) {
/* #line 244 "user/ansi_parser.c" */ /* #line 265 "user/ansi_parser.c" */
{ {
cs = ansi_start; cs = ansi_start;
} }
/* #line 223 "user/ansi_parser.rl" */ /* #line 241 "user/ansi_parser.rl" */
} }
// The parser // The parser
/* #line 254 "user/ansi_parser.c" */ /* #line 275 "user/ansi_parser.c" */
{ {
const char *_acts; const char *_acts;
unsigned int _nacts; unsigned int _nacts;
@ -274,79 +295,137 @@ case 2:
goto tr2; goto tr2;
case 0: case 0:
goto _out; goto _out;
case 5: case 14:
if ( (*p) == 27 ) if ( (*p) == 27 )
goto tr1; goto tr1;
goto tr0; goto tr0;
case 3: case 3:
if ( (*p) == 59 ) if ( (*p) == 59 )
goto tr9; goto tr8;
if ( (*p) < 60 ) { if ( (*p) < 60 ) {
if ( (*p) > 47 ) { if ( (*p) > 47 ) {
if ( 48 <= (*p) && (*p) <= 57 ) if ( 48 <= (*p) && (*p) <= 57 )
goto tr8; goto tr7;
} else if ( (*p) >= 32 ) } else if ( (*p) >= 32 )
goto tr7; goto tr6;
} else if ( (*p) > 64 ) { } else if ( (*p) > 64 ) {
if ( (*p) > 90 ) { if ( (*p) > 90 ) {
if ( 97 <= (*p) && (*p) <= 122 ) if ( 97 <= (*p) && (*p) <= 122 )
goto tr10; goto tr9;
} else if ( (*p) >= 65 ) } else if ( (*p) >= 65 )
goto tr10; goto tr9;
} else } else
goto tr7; goto tr6;
goto tr6; goto tr2;
case 4: case 4:
if ( (*p) == 59 ) if ( (*p) == 59 )
goto tr9; goto tr8;
if ( (*p) < 65 ) { if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 ) if ( 48 <= (*p) && (*p) <= 57 )
goto tr8; goto tr7;
} else if ( (*p) > 90 ) { } else if ( (*p) > 90 ) {
if ( 97 <= (*p) && (*p) <= 122 ) if ( 97 <= (*p) && (*p) <= 122 )
goto tr10; goto tr9;
} else } else
goto tr10; goto tr9;
goto tr6; goto tr2;
case 15:
goto tr2;
case 5:
switch( (*p) ) {
case 70: goto tr10;
case 87: goto tr11;
}
goto tr2;
case 6: 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; tr2: cs = 0; goto f0;
tr6: cs = 0; goto f5;
tr0: cs = 1; goto f1; tr0: cs = 1; goto f1;
tr1: cs = 2; goto _again; tr1: cs = 2; goto _again;
tr6: cs = 4; goto f5;
tr7: cs = 4; goto f6; tr7: cs = 4; goto f6;
tr8: cs = 4; goto f7; tr8: cs = 4; goto f7;
tr9: cs = 4; goto f8; tr10: cs = 6; goto _again;
tr3: cs = 5; goto f2; tr12: cs = 7; goto _again;
tr4: cs = 5; goto f3; tr14: cs = 8; goto _again;
tr5: cs = 5; goto f4; tr11: cs = 9; goto _again;
tr10: cs = 6; goto f9; 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; f1: _acts = _ansi_actions + 1; goto execFuncs;
f2: _acts = _ansi_actions + 3; goto execFuncs; f2: _acts = _ansi_actions + 3; goto execFuncs;
f6: _acts = _ansi_actions + 5; goto execFuncs; f5: _acts = _ansi_actions + 5; goto execFuncs;
f7: _acts = _ansi_actions + 7; goto execFuncs; f6: _acts = _ansi_actions + 7; goto execFuncs;
f8: _acts = _ansi_actions + 9; goto execFuncs; f7: _acts = _ansi_actions + 9; goto execFuncs;
f9: _acts = _ansi_actions + 11; goto execFuncs; f8: _acts = _ansi_actions + 11; goto execFuncs;
f5: _acts = _ansi_actions + 13; goto execFuncs; f0: _acts = _ansi_actions + 13; goto execFuncs;
f0: _acts = _ansi_actions + 15; goto execFuncs; f3: _acts = _ansi_actions + 15; goto execFuncs;
f3: _acts = _ansi_actions + 17; goto execFuncs; f9: _acts = _ansi_actions + 17; goto execFuncs;
f4: _acts = _ansi_actions + 19; goto execFuncs; f10: _acts = _ansi_actions + 19; goto execFuncs;
f4: _acts = _ansi_actions + 21; goto execFuncs;
execFuncs: execFuncs:
_nacts = *_acts++; _nacts = *_acts++;
while ( _nacts-- > 0 ) { while ( _nacts-- > 0 ) {
switch ( *_acts++ ) { switch ( *_acts++ ) {
case 0: case 0:
/* #line 233 "user/ansi_parser.rl" */ /* #line 251 "user/ansi_parser.rl" */
{ {
handle_plainchar((*p)); handle_plainchar((*p));
} }
break; break;
case 1: case 1:
/* #line 240 "user/ansi_parser.rl" */ /* #line 258 "user/ansi_parser.rl" */
{ {
/* Reset the CSI builder */ /* Reset the CSI builder */
csi_leading = csi_char = 0; csi_leading = csi_char = 0;
@ -361,13 +440,13 @@ execFuncs:
} }
break; break;
case 2: case 2:
/* #line 253 "user/ansi_parser.rl" */ /* #line 271 "user/ansi_parser.rl" */
{ {
csi_leading = (*p); csi_leading = (*p);
} }
break; break;
case 3: case 3:
/* #line 257 "user/ansi_parser.rl" */ /* #line 275 "user/ansi_parser.rl" */
{ {
/* x10 + digit */ /* x10 + digit */
if (csi_ni < CSI_N_MAX) { if (csi_ni < CSI_N_MAX) {
@ -376,13 +455,13 @@ execFuncs:
} }
break; break;
case 4: case 4:
/* #line 264 "user/ansi_parser.rl" */ /* #line 282 "user/ansi_parser.rl" */
{ {
csi_ni++; csi_ni++;
} }
break; break;
case 5: case 5:
/* #line 268 "user/ansi_parser.rl" */ /* #line 286 "user/ansi_parser.rl" */
{ {
csi_char = (*p); csi_char = (*p);
@ -392,33 +471,49 @@ execFuncs:
} }
break; break;
case 6: case 6:
/* #line 276 "user/ansi_parser.rl" */ /* #line 294 "user/ansi_parser.rl" */
{ {
warn("Invalid escape sequence discarded.");
{cs = 1; goto _again;} {cs = 1; goto _again;}
} }
break; break;
case 7: 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; break;
case 8: 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;} {cs = 1; goto _again;}
} }
break; break;
case 9: 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 // Reset screen
handle_RESET_cmd(); handle_RESET_cmd();
{cs = 1; goto _again;} {cs = 1; goto _again;}
} }
break; break;
/* #line 422 "user/ansi_parser.c" */ /* #line 517 "user/ansi_parser.c" */
} }
} }
goto _again; goto _again;
@ -436,18 +531,13 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 6: case 6:
/* #line 276 "user/ansi_parser.rl" */ /* #line 294 "user/ansi_parser.rl" */
{
{cs = 1; goto _again;}
}
break;
case 7:
/* #line 280 "user/ansi_parser.rl" */
{ {
warn("Invalid escape sequence discarded.");
{cs = 1; goto _again;} {cs = 1; goto _again;}
} }
break; break;
/* #line 451 "user/ansi_parser.c" */ /* #line 541 "user/ansi_parser.c" */
} }
} }
} }
@ -455,6 +545,6 @@ _again:
_out: {} _out: {}
} }
/* #line 315 "user/ansi_parser.rl" */ /* #line 356 "user/ansi_parser.rl" */
} }

@ -180,6 +180,24 @@ handle_plainchar(char c)
screen_putchar(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 */ /* Ragel constants block */
%%{ %%{
machine ansi; machine ansi;
@ -273,26 +291,49 @@ ansi_parser(const char *newdata, size_t len)
fgoto main; fgoto main;
} }
action CSI_fail { action errBadSeq {
warn("Invalid escape sequence discarded.");
fgoto main; fgoto main;
} }
action main_fail { action back2main {
fgoto main; fgoto main;
} }
CSI_body := ((32..47|60..64) @CSI_leading)? CSI_body := ((32..47|60..64) @CSI_leading)?
((digit @CSI_digit)* ';' @CSI_semi)* ((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) --- # --- OSC commands (Operating System Commands) ---
# Module parametrisation # Module parametrisation
action OSC_start { 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; 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 { action RESET_cmd {
// Reset screen // Reset screen
@ -309,7 +350,7 @@ ansi_parser(const char *newdata, size_t len)
']' @OSC_start | ']' @OSC_start |
'c' @RESET_cmd 'c' @RESET_cmd
) )
)+ $!main_fail; )+ $!errBadSeq;
write exec; write exec;
}%% }%%

@ -189,20 +189,28 @@ screen_clear_line(ClearMode mode)
/** /**
* Change the screen size * Change the screen size
* *
* @param w - new width * @param cols - new width
* @param h - new height * @param rows - new height
*/ */
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
screen_resize(Coordinate w, Coordinate h) screen_resize(Coordinate rows, Coordinate cols)
{ {
NOTIFY_LOCK(); NOTIFY_LOCK();
// sanitize // sanitize
if (w < 1) w = 1; if (cols < 1 || rows < 1) {
if (h < 1) h = 1; error("Screen size must be positive");
goto done;
}
if (cols * rows > MAX_SCREEN_SIZE) {
error("Max screen size exceeded");
goto done;
}
W = w; W = cols;
H = h; H = rows;
screen_reset(); screen_reset();
done:
NOTIFY_DONE(); NOTIFY_DONE();
} }
@ -579,11 +587,11 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
ss->lastFg = 0; ss->lastFg = 0;
ss->lastChar = '\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; int i = ss->index;
while(i < W*H && remain > 6) { while(i < W*H && remain > 12) {
cell = cell0 = &screen[i]; cell = cell0 = &screen[i];
// Count how many times same as previous // Count how many times same as previous
@ -598,11 +606,25 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
} }
if (repCnt == 0) { 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) { if (cell0->fg == ss->lastFg && cell0->bg == ss->lastBg) {
// same colors as previous // same colors as previous
bufprint(",%c", cell0->c); bufprint(",");
} else { } 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; ss->lastFg = cell0->fg;
@ -633,7 +655,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
} }
if (remain >= 3) { if (remain >= 3) {
bufprint("\"}"); bufprint("\"\n}");
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} else { } else {
return HTTPD_CGI_MORE; return HTTPD_CGI_MORE;

@ -62,7 +62,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
void screen_init(void); void screen_init(void);
/** Change the screen size */ /** Change the screen size */
void screen_resize(Coordinate w, Coordinate h); void screen_resize(Coordinate rows, Coordinate cols);
// --- Clearing --- // --- Clearing ---

@ -50,17 +50,20 @@ static ETSTimer prHeapTimer;
/** Periodically show heap usage */ /** Periodically show heap usage */
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
{ {
static uint32_t cnt = 0;
static uint32_t last = 0; static uint32_t last = 0;
if (cnt == 5) { uint32_t heap = system_get_free_heap_size();
uint32_t heap = system_get_free_heap_size(); int32_t diff = (heap-last);
dbg("Free heap: %d bytes (~ %d)", heap, (heap-last)); const char *cc = "+";
cnt = 0; if (diff<0) cc = "";
last = heap;
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. //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 // Heap use timer & blink
os_timer_disarm(&prHeapTimer); os_timer_disarm(&prHeapTimer);
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL); os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
os_timer_arm(&prHeapTimer, 1000, 1); os_timer_arm(&prHeapTimer, 5000, 1);
// The terminal screen // The terminal screen
screen_init(); screen_init();

Loading…
Cancel
Save