w.i.p. Terminal Themes added, improved terminal color picker, new compression in front-end

pull/111/merge
Ondřej Hruška 8 years ago
parent 76167b8014
commit d711909812
  1. 13
      html_orig/_debug_replacements.php
  2. 547
      html_orig/css/app.css
  3. BIN
      html_orig/fontello/fontello.zip
  4. 535
      html_orig/js/app.js
  5. 561
      html_orig/jssrc/term.js
  6. 27
      html_orig/lang/en.php
  7. 120
      html_orig/pages/cfg_term.php
  8. 2
      html_orig/pages/help.php
  9. 28
      html_orig/pages/term.php
  10. 6
      html_orig/sass/_fontello.scss
  11. 24
      html_orig/sass/_term-colors.scss
  12. 1
      html_orig/sass/app.scss
  13. 134
      html_orig/sass/pages/_term.scss
  14. 16
      user/cgi_main.c
  15. 14
      user/cgi_term_cfg.c
  16. 11
      user/persist.c
  17. 2
      user/persist.h
  18. 20
      user/screen.c
  19. 2
      user/screen.h

@ -14,12 +14,13 @@ return [
'%btn4%' => '4', '%btn4%' => '4',
'%btn5%' => '5', '%btn5%' => '5',
'%screenData%' => '{ '%screenData%' => '  HELLOx NRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //,
/*'{
"w": 26, "h": 10, "w": 26, "h": 10,
"x": 0, "y": 0, "x": 10, "y": 5,
"cv": 1, "cv": 1, "fg": 10, "bg": 2,
"screen": "70 t259" "screen": ""
}', }',//"70 t259"*/
'%opmode%' => '2', '%opmode%' => '2',
'%sta_enable%' => '0', '%sta_enable%' => '0',
@ -65,4 +66,6 @@ return [
'%uart_baud%' => 115200, '%uart_baud%' => 115200,
'%uart_stopbits%' => 1, '%uart_stopbits%' => 1,
'%uart_parity%' => 2, '%uart_parity%' => 2,
'%theme%' => 5,
]; ];

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -1182,306 +1182,337 @@ function tr(key) { return _tr[key] || '?'+key+'?'; }
w.init = wifiInit; w.init = wifiInit;
w.startScanning = startScanning; w.startScanning = startScanning;
})(window.WiFi = {}); })(window.WiFi = {});
(function() { var Screen = (function () {
/** var W, H; // dimensions
* Terminal module var inited = false;
*/
var Term = (function () { var cursor = {
var W, H; a: false, // active (blink state)
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false}; x: 0, // 0-based coordinates
var screen = []; y: 0,
var blinkIval; fg: 7, // colors 0-15
bg: 0,
/* bold: false,
/!** Clear screen *!/ suppress: false, // do not turn on in blink interval (for safe moving)
function cls() { hidden: false // do not show
screen.forEach(function(cell, i) { };
cell.t = ' ';
cell.fg = 7;
cell.bg = 0;
blit(cell);
});
}
*/
/** Set text and color at XY */ var screen = [];
function cellAt(y, x) { var blinkIval;
return screen[y*W+x];
/** Clear screen */
function _clear() {
for (var i = W*H-1; i>=0; i--) {
var cell = screen[i];
cell.t = ' ';
cell.bg = cursor.bg;
cell.fg = cursor.fg;
cell.bold = false;
_draw(cell);
} }
}
/** Get cell under cursor */ /** Set text and color at XY */
function cursorCell() { function _cellAt(y, x) {
return cellAt(cursor.y, cursor.x); return screen[y*W+x];
} }
/* /** Get cell under cursor */
/!** Enable or disable cursor visibility *!/ function _curCell() {
function cursorEnable(enable) { return screen[cursor.y*W + cursor.x];
cursor.hidden = !enable; }
cursor.a &= enable;
blit(cursorCell(), cursor.a);
}
/!** Safely move cursor *!/ /** Enable or disable cursor visibility */
function cursorSet(y, x) { function _cursorEnable(enable) {
// Hide and prevent from showing up during the move cursor.hidden = !enable;
cursor.suppress = true; cursor.a &= enable;
blit(cursorCell(), false); _draw(_curCell());
}
cursor.x = x; /** Safely move cursor */
cursor.y = y; function cursorSet(y, x) {
// Hide and prevent from showing up during the move
cursor.suppress = true;
_draw(_curCell(), false);
cursor.x = x;
cursor.y = y;
// Show again
cursor.suppress = false;
_draw(_curCell());
}
// Show again /** Update cell on display. inv = invert (for cursor) */
cursor.suppress = false; function _draw(cell, inv) {
blit(cursorCell(), cursor.a); if (typeof inv == 'undefined') {
} inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
*/
/** Update cell on display. inv = invert (for cursor) */
function blit(cell, inv) {
var e = cell.e, fg, bg;
// Colors
fg = inv ? cell.bg : cell.fg;
bg = inv ? cell.fg : cell.bg;
// Update
e.innerText = (cell.t+' ')[0];
e.className = 'fg'+fg+' bg'+bg;
} }
/** Show entire screen */ var e = cell.e, fg, bg;
function blitAll() { // Colors
screen.forEach(function(cell, i) { fg = inv ? cell.bg : cell.fg;
/* Invert if under cursor & cursor active */ bg = inv ? cell.fg : cell.bg;
var inv = cursor.a && (i == cursor.y*W+cursor.x); // Update
blit(cell, inv); e.innerText = (cell.t + ' ')[0];
}); e.className = 'fg' + fg + ' bg' + bg + (cell.bold ? ' bold' : '');
} }
/** Load screen content from a 'binary' sequence */ /** Show entire screen */
function load(obj) { function _drawAll() {
cursor.x = obj.x; for (var i = W*H-1; i>=0; i--) {
cursor.y = obj.y; _draw(screen[i]);
cursor.hidden = !obj.cv; }
}
// full re-init if size changed function _rebuild(rows, cols) {
if (obj.w != W || obj.h != H) { W = cols;
Term.init(obj); H = rows;
return;
}
// Simple compression - hexFG hexBG 'ASCII' (r/s/t/u NUM{1,2,3,4})? /* Build screen & show */
// comma instead of both colors = same as before var e, cell, scr = qs('#screen');
var i = 0, ci = 0, str = obj.screen; // Empty the screen node
var fg = 7, bg = 0; while (scr.firstChild) scr.removeChild(scr.firstChild);
while(i < str.length && ci<W*H) {
var cell = screen[ci++];
var j = str[i]; screen = [];
if (j != ',') { // comma = repeat last colors
fg = cell.fg = parseInt(str[i++], 16);
bg = cell.bg = parseInt(str[i++], 16);
} else {
i++;
cell.fg = fg;
cell.bg = bg;
}
var t = cell.t = str[i++]; for(var i = 0; i < W*H; i++) {
e = mk('span');
var repchars = 0; (function() {
switch(str[i]) { var x = i % W;
case 'r': repchars = 1; break; var y = Math.floor(i / W);
case 's': repchars = 2; break; e.addEventListener('click', function () {
case 't': repchars = 3; break; Input.onTap(y, x);
case 'u': repchars = 4; break; });
default: repchars = 0; })();
}
if (repchars > 0) { /* End of line */
var rep = parseInt(str.substr(i+1,repchars)); if ((i > 0) && (i % W == 0)) {
i = i + repchars + 1; scr.appendChild(mk('br'));
for (; rep>0 && ci<W*H; rep--) {
cell = screen[ci++];
cell.fg = fg;
cell.bg = bg;
cell.t = t;
}
}
} }
/* The cell */
blitAll(); scr.appendChild(e);
cell = {
t: ' ',
fg: cursor.fg,
bg: cursor.bg,
e: e,
x: i % W,
y: Math.floor(i / W),
};
screen.push(cell);
_draw(cell);
} }
}
/** Init the terminal */ /** Init the terminal */
function init(obj) { function _init() {
W = obj.w; /* Cursor blinking */
H = obj.h; clearInterval(blinkIval);
blinkIval = setInterval(function () {
cursor.a = !cursor.a;
if (cursor.hidden) {
cursor.a = false;
}
/* Build screen & show */ if (!cursor.suppress) {
var e, cell, scr = qs('#screen'); _draw(_curCell(), cursor.a);
}
}, 500);
inited = true;
}
// Empty the screen node /** Decode two-byte number */
while (scr.firstChild) scr.removeChild(scr.firstChild); function parse2B(s, i) {
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
}
screen = []; var SEQ_SET_COLOR = 1;
var SEQ_REPEAT = 2;
for(var i = 0; i < W*H; i++) { /** Load screen content from a binary sequence (new) */
e = mk('span'); function load(str) {
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell;
(function() { if (!inited) _init();
var x = i % W;
var y = Math.floor(i / W);
e.addEventListener('click', function () {
Input.onTap(y, x);
});
})();
/* End of line */ // Set size
if ((i > 0) && (i % W == 0)) { num = parse2B(str, i); i += 2;
scr.appendChild(mk('br')); num2 = parse2B(str, i); i += 2;
if (num != H || num2 != W) {
_rebuild(num, num2);
}
console.log("Size ",num, num2);
// Cursor position
num = parse2B(str, i); i += 2;
num2 = parse2B(str, i); i += 2;
cursorSet(num, num2);
console.log("Cursor at ",num, num2);
// Attributes
num = parse2B(str, i); i += 2;
cursor.fg = num & 0x0F;
cursor.bg = (num & 0xF0) >> 4;
cursor.bold = !!(num & 0x100);
cursor.hidden = !(num & 0x200);
console.log("FG ",cursor.fg, ", BG ", cursor.bg,", BOLD ", cursor.bold, ", HIDE ", cursor.hidden);
fg = cursor.fg;
bg = cursor.bg;
bold = cursor.bold;
// Here come the content
while(i < str.length && ci<W*H) {
j = str[i++];
jc = j.charCodeAt(0);
if (jc == SEQ_SET_COLOR) {
num = parse2B(str, i); i += 2;
fg = num & 0x0F;
bg = (num & 0xF0) >> 4;
bold = !!(num & 0x100);
console.log("Switch to ",fg,bg,bold);
}
else if (jc == SEQ_REPEAT) {
num = parse2B(str, i); i += 2;
console.log("Repeat x ",num);
for (; num>0 && ci<W*H; num--) {
cell = screen[ci++];
cell.fg = fg;
cell.bg = bg;
cell.t = t;
cell.bold = bold;
} }
/* The cell */
scr.appendChild(e);
cell = {t: ' ', fg: 7, bg: 0, e: e};
screen.push(cell);
blit(cell);
} }
else {
cell = screen[ci++];
// Unique cell character
t = cell.t = j;
cell.fg = fg;
cell.bg = bg;
cell.bold = bold;
console.log("Symbol ", j);
}
}
/* Cursor blinking */ _drawAll();
clearInterval(blinkIval); }
blinkIval = setInterval(function() {
cursor.a = !cursor.a;
if (cursor.hidden) {
cursor.a = false;
}
if (!cursor.suppress) { return {
blit(cursorCell(), cursor.a); load: load, // full load (string)
} };
}, 500); })();
load(obj); /** Handle connections */
} var Conn = (function() {
var ws;
// publish function onOpen(evt) {
return { console.log("CONNECTED");
init: init, }
load: load
};
})();
/** Handle connections */ function onClose(evt) {
var Conn = (function() { console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting...");
var ws; setTimeout(function() {
init();
}, 1000);
}
function onOpen(evt) { function onMessage(evt) {
console.log("CONNECTED"); try {
console.log("RX: ", evt.data);
// Assume all our messages are screen updates
Screen.load(evt.data);
} catch(e) {
console.error(e);
} }
}
function onClose(evt) { function doSend(message) {
console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting..."); console.log("TX: ", message);
setTimeout(function() { if (!ws) return; // for dry testing
init(); if (ws.readyState != 1) {
}, 1000); console.error("Socket not ready");
return;
} }
if (typeof message != "string") {
function onMessage(evt) { message = JSON.stringify(message);
try {
console.log("RX: ", evt.data);
// Assume all our messages are screen updates
Term.load(JSON.parse(evt.data));
} catch(e) {
console.error(e);
}
} }
ws.send(message);
}
function doSend(message) { function init() {
console.log("TX: ", message); ws = new WebSocket("ws://"+_root+"/ws/update.cgi");
if (ws.readyState != 1) { ws.onopen = onOpen;
console.error("Socket not ready"); ws.onclose = onClose;
return; ws.onmessage = onMessage;
}
if (typeof message != "string") {
message = JSON.stringify(message);
}
ws.send(message);
}
function init() { console.log("Opening socket.");
ws = new WebSocket("ws://"+_root+"/ws/update.cgi"); }
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
console.log("Opening socket."); return {
} ws: null,
init: init,
send: doSend
};
})();
return { /** User input */
ws: null, var Input = (function() {
init: init, function sendStrMsg(str) {
send: doSend Conn.send("STR:"+str);
}; }
})();
//
// Keyboard (& mouse) input
//
var Input = (function() {
function sendStrMsg(str) {
Conn.send("STR:"+str);
}
function sendPosMsg(y, x) { function sendPosMsg(y, x) {
Conn.send("TAP:"+y+','+x); Conn.send("TAP:"+y+','+x);
} }
function sendBtnMsg(n) { function sendBtnMsg(n) {
Conn.send("BTN:"+n); Conn.send("BTN:"+n);
} }
function init() { function init() {
window.addEventListener('keypress', function(e) { window.addEventListener('keypress', function(e) {
var code = +e.which; var code = +e.which;
if (code >= 32 && code < 127) { if (code >= 32 && code < 127) {
var ch = String.fromCharCode(code); var ch = String.fromCharCode(code);
//console.log("Typed ", ch, "code", code, e); //console.log("Typed ", ch, "code", code, e);
sendStrMsg(ch); sendStrMsg(ch);
} }
}); });
window.addEventListener('keydown', function(e) { window.addEventListener('keydown', function(e) {
var code = e.keyCode; var code = e.keyCode;
//console.log("Down ", code, e); //console.log("Down ", code, e);
switch(code) { switch(code) {
case 8: sendStrMsg('\x08'); break; case 8: sendStrMsg('\x08'); break;
case 13: sendStrMsg('\x0d\x0a'); break; case 10:
case 27: sendStrMsg('\x1b'); break; // this allows to directly enter control sequences case 13: sendStrMsg('\x0d\x0a'); break;
case 37: sendStrMsg('\x1b[D'); break; case 27: sendStrMsg('\x1b'); break; // this allows to directly enter control sequences
case 38: sendStrMsg('\x1b[A'); break; case 37: sendStrMsg('\x1b[D'); break;
case 39: sendStrMsg('\x1b[C'); break; case 38: sendStrMsg('\x1b[A'); break;
case 40: sendStrMsg('\x1b[B'); break; case 39: sendStrMsg('\x1b[C'); break;
} case 40: sendStrMsg('\x1b[B'); break;
}); }
});
qsa('#buttons button').forEach(function(s) { qsa('#buttons button').forEach(function(s) {
s.addEventListener('click', function() { s.addEventListener('click', function() {
sendBtnMsg(+this.dataset['n']); sendBtnMsg(+this.dataset['n']);
});
}); });
} });
}
return {
init: init,
onTap: sendPosMsg
};
})();
window.termInit = function (obj) { return {
Term.init(obj); init: init,
Conn.init(); onTap: sendPosMsg
Input.init();
}; };
})(); })();
window.termInit = function (str) {
Screen.load(str);
Conn.init();
Input.init();
};

@ -1,303 +1,334 @@
(function() { var Screen = (function () {
/** var W, H; // dimensions
* Terminal module var inited = false;
*/
var Term = (function () { var cursor = {
var W, H; a: false, // active (blink state)
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false}; x: 0, // 0-based coordinates
var screen = []; y: 0,
var blinkIval; fg: 7, // colors 0-15
bg: 0,
/* bold: false,
/!** Clear screen *!/ suppress: false, // do not turn on in blink interval (for safe moving)
function cls() { hidden: false // do not show
screen.forEach(function(cell, i) { };
cell.t = ' ';
cell.fg = 7;
cell.bg = 0;
blit(cell);
});
}
*/
/** Set text and color at XY */
function cellAt(y, x) {
return screen[y*W+x];
}
/** Get cell under cursor */
function cursorCell() {
return cellAt(cursor.y, cursor.x);
}
/*
/!** Enable or disable cursor visibility *!/
function cursorEnable(enable) {
cursor.hidden = !enable;
cursor.a &= enable;
blit(cursorCell(), cursor.a);
}
/!** Safely move cursor *!/
function cursorSet(y, x) {
// Hide and prevent from showing up during the move
cursor.suppress = true;
blit(cursorCell(), false);
cursor.x = x;
cursor.y = y;
// Show again var screen = [];
cursor.suppress = false; var blinkIval;
blit(cursorCell(), cursor.a);
/** Clear screen */
function _clear() {
for (var i = W*H-1; i>=0; i--) {
var cell = screen[i];
cell.t = ' ';
cell.bg = cursor.bg;
cell.fg = cursor.fg;
cell.bold = false;
_draw(cell);
} }
*/ }
/** Update cell on display. inv = invert (for cursor) */ /** Set text and color at XY */
function blit(cell, inv) { function _cellAt(y, x) {
var e = cell.e, fg, bg; return screen[y*W+x];
// Colors }
fg = inv ? cell.bg : cell.fg;
bg = inv ? cell.fg : cell.bg; /** Get cell under cursor */
// Update function _curCell() {
e.innerText = (cell.t+' ')[0]; return screen[cursor.y*W + cursor.x];
e.className = 'fg'+fg+' bg'+bg; }
/** Enable or disable cursor visibility */
function _cursorEnable(enable) {
cursor.hidden = !enable;
cursor.a &= enable;
_draw(_curCell());
}
/** Safely move cursor */
function cursorSet(y, x) {
// Hide and prevent from showing up during the move
cursor.suppress = true;
_draw(_curCell(), false);
cursor.x = x;
cursor.y = y;
// Show again
cursor.suppress = false;
_draw(_curCell());
}
/** Update cell on display. inv = invert (for cursor) */
function _draw(cell, inv) {
if (typeof inv == 'undefined') {
inv = cursor.a && cursor.x == cell.x && cursor.y == cell.y;
} }
/** Show entire screen */ var e = cell.e, fg, bg;
function blitAll() { // Colors
screen.forEach(function(cell, i) { fg = inv ? cell.bg : cell.fg;
/* Invert if under cursor & cursor active */ bg = inv ? cell.fg : cell.bg;
var inv = cursor.a && (i == cursor.y*W+cursor.x); // Update
blit(cell, inv); e.innerText = (cell.t + ' ')[0];
}); e.className = 'fg' + fg + ' bg' + bg + (cell.bold ? ' bold' : '');
}
/** Show entire screen */
function _drawAll() {
for (var i = W*H-1; i>=0; i--) {
_draw(screen[i]);
} }
}
/** Load screen content from a 'binary' sequence */ function _rebuild(rows, cols) {
function load(obj) { W = cols;
cursor.x = obj.x; H = rows;
cursor.y = obj.y;
cursor.hidden = !obj.cv;
// full re-init if size changed /* Build screen & show */
if (obj.w != W || obj.h != H) { var e, cell, scr = qs('#screen');
Term.init(obj);
return;
}
// Simple compression - hexFG hexBG 'ASCII' (r/s/t/u NUM{1,2,3,4})? // Empty the screen node
// comma instead of both colors = same as before while (scr.firstChild) scr.removeChild(scr.firstChild);
var i = 0, ci = 0, str = obj.screen; screen = [];
var fg = 7, bg = 0;
while(i < str.length && ci<W*H) {
var cell = screen[ci++];
var j = str[i]; for(var i = 0; i < W*H; i++) {
if (j != ',') { // comma = repeat last colors e = mk('span');
fg = cell.fg = parseInt(str[i++], 16);
bg = cell.bg = parseInt(str[i++], 16);
} else {
i++;
cell.fg = fg;
cell.bg = bg;
}
var t = cell.t = str[i++]; (function() {
var x = i % W;
var repchars = 0; var y = Math.floor(i / W);
switch(str[i]) { e.addEventListener('click', function () {
case 'r': repchars = 1; break; Input.onTap(y, x);
case 's': repchars = 2; break; });
case 't': repchars = 3; break; })();
case 'u': repchars = 4; break;
default: repchars = 0;
}
if (repchars > 0) { /* End of line */
var rep = parseInt(str.substr(i+1,repchars)); if ((i > 0) && (i % W == 0)) {
i = i + repchars + 1; scr.appendChild(mk('br'));
for (; rep>0 && ci<W*H; rep--) {
cell = screen[ci++];
cell.fg = fg;
cell.bg = bg;
cell.t = t;
}
}
} }
/* The cell */
blitAll(); scr.appendChild(e);
cell = {
t: ' ',
fg: cursor.fg,
bg: cursor.bg,
e: e,
x: i % W,
y: Math.floor(i / W),
};
screen.push(cell);
_draw(cell);
} }
}
/** Init the terminal */
function init(obj) { /** Init the terminal */
W = obj.w; function _init() {
H = obj.h; /* Cursor blinking */
clearInterval(blinkIval);
/* Build screen & show */ blinkIval = setInterval(function () {
var e, cell, scr = qs('#screen'); cursor.a = !cursor.a;
if (cursor.hidden) {
// Empty the screen node cursor.a = false;
while (scr.firstChild) scr.removeChild(scr.firstChild);
screen = [];
for(var i = 0; i < W*H; i++) {
e = mk('span');
(function() {
var x = i % W;
var y = Math.floor(i / W);
e.addEventListener('click', function () {
Input.onTap(y, x);
});
})();
/* End of line */
if ((i > 0) && (i % W == 0)) {
scr.appendChild(mk('br'));
}
/* The cell */
scr.appendChild(e);
cell = {t: ' ', fg: 7, bg: 0, e: e};
screen.push(cell);
blit(cell);
} }
/* Cursor blinking */ if (!cursor.suppress) {
clearInterval(blinkIval); _draw(_curCell(), cursor.a);
blinkIval = setInterval(function() { }
cursor.a = !cursor.a; }, 500);
if (cursor.hidden) { inited = true;
cursor.a = false; }
}
if (!cursor.suppress) {
blit(cursorCell(), cursor.a);
}
}, 500);
load(obj); /** Decode two-byte number */
} function parse2B(s, i) {
return (s.charCodeAt(i++) - 1) + (s.charCodeAt(i) - 1) * 127;
}
// publish var SEQ_SET_COLOR = 1;
return { var SEQ_REPEAT = 2;
init: init,
load: load
};
})();
/** Handle connections */ /** Load screen content from a binary sequence (new) */
var Conn = (function() { function load(str) {
var ws; var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell;
function onOpen(evt) { if (!inited) _init();
console.log("CONNECTED");
}
function onClose(evt) { // Set size
console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting..."); num = parse2B(str, i); i += 2;
setTimeout(function() { num2 = parse2B(str, i); i += 2;
init(); if (num != H || num2 != W) {
}, 1000); _rebuild(num, num2);
} }
console.log("Size ",num, num2);
function onMessage(evt) {
try { // Cursor position
console.log("RX: ", evt.data); num = parse2B(str, i); i += 2;
// Assume all our messages are screen updates num2 = parse2B(str, i); i += 2;
Term.load(JSON.parse(evt.data)); cursorSet(num, num2);
} catch(e) { console.log("Cursor at ",num, num2);
console.error(e);
// Attributes
num = parse2B(str, i); i += 2;
cursor.fg = num & 0x0F;
cursor.bg = (num & 0xF0) >> 4;
cursor.bold = !!(num & 0x100);
cursor.hidden = !(num & 0x200);
console.log("FG ",cursor.fg, ", BG ", cursor.bg,", BOLD ", cursor.bold, ", HIDE ", cursor.hidden);
fg = cursor.fg;
bg = cursor.bg;
bold = cursor.bold;
// Here come the content
while(i < str.length && ci<W*H) {
j = str[i++];
jc = j.charCodeAt(0);
if (jc == SEQ_SET_COLOR) {
num = parse2B(str, i); i += 2;
fg = num & 0x0F;
bg = (num & 0xF0) >> 4;
bold = !!(num & 0x100);
console.log("Switch to ",fg,bg,bold);
} }
} else if (jc == SEQ_REPEAT) {
num = parse2B(str, i); i += 2;
function doSend(message) { console.log("Repeat x ",num);
console.log("TX: ", message); for (; num>0 && ci<W*H; num--) {
if (ws.readyState != 1) { cell = screen[ci++];
console.error("Socket not ready"); cell.fg = fg;
return; cell.bg = bg;
cell.t = t;
cell.bold = bold;
}
} }
if (typeof message != "string") { else {
message = JSON.stringify(message); cell = screen[ci++];
// Unique cell character
t = cell.t = j;
cell.fg = fg;
cell.bg = bg;
cell.bold = bold;
console.log("Symbol ", j);
} }
ws.send(message);
} }
function init() { _drawAll();
ws = new WebSocket("ws://"+_root+"/ws/update.cgi"); }
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
console.log("Opening socket."); return {
} load: load, // full load (string)
};
})();
return { /** Handle connections */
ws: null, var Conn = (function() {
init: init, var ws;
send: doSend
}; function onOpen(evt) {
})(); console.log("CONNECTED");
}
//
// Keyboard (& mouse) input function onClose(evt) {
// console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting...");
var Input = (function() { setTimeout(function() {
function sendStrMsg(str) { init();
Conn.send("STR:"+str); }, 1000);
}
function onMessage(evt) {
try {
console.log("RX: ", evt.data);
// Assume all our messages are screen updates
Screen.load(evt.data);
} catch(e) {
console.error(e);
} }
}
function sendPosMsg(y, x) {
Conn.send("TAP:"+y+','+x); function doSend(message) {
console.log("TX: ", message);
if (!ws) return; // for dry testing
if (ws.readyState != 1) {
console.error("Socket not ready");
return;
} }
if (typeof message != "string") {
function sendBtnMsg(n) { message = JSON.stringify(message);
Conn.send("BTN:"+n);
} }
ws.send(message);
}
function init() {
ws = new WebSocket("ws://"+_root+"/ws/update.cgi");
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
console.log("Opening socket.");
}
return {
ws: null,
init: init,
send: doSend
};
})();
function init() { /** User input */
window.addEventListener('keypress', function(e) { var Input = (function() {
var code = +e.which; function sendStrMsg(str) {
if (code >= 32 && code < 127) { Conn.send("STR:"+str);
var ch = String.fromCharCode(code); }
//console.log("Typed ", ch, "code", code, e);
sendStrMsg(ch); function sendPosMsg(y, x) {
} Conn.send("TAP:"+y+','+x);
}); }
window.addEventListener('keydown', function(e) { function sendBtnMsg(n) {
var code = e.keyCode; Conn.send("BTN:"+n);
//console.log("Down ", code, e); }
switch(code) {
case 8: sendStrMsg('\x08'); break; function init() {
case 13: sendStrMsg('\x0d\x0a'); break; window.addEventListener('keypress', function(e) {
case 27: sendStrMsg('\x1b'); break; // this allows to directly enter control sequences var code = +e.which;
case 37: sendStrMsg('\x1b[D'); break; if (code >= 32 && code < 127) {
case 38: sendStrMsg('\x1b[A'); break; var ch = String.fromCharCode(code);
case 39: sendStrMsg('\x1b[C'); break; //console.log("Typed ", ch, "code", code, e);
case 40: sendStrMsg('\x1b[B'); break; sendStrMsg(ch);
} }
}); });
window.addEventListener('keydown', function(e) {
var code = e.keyCode;
//console.log("Down ", code, e);
switch(code) {
case 8: sendStrMsg('\x08'); break;
case 10:
case 13: sendStrMsg('\x0d\x0a'); break;
case 27: sendStrMsg('\x1b'); break; // this allows to directly enter control sequences
case 37: sendStrMsg('\x1b[D'); break;
case 38: sendStrMsg('\x1b[A'); break;
case 39: sendStrMsg('\x1b[C'); break;
case 40: sendStrMsg('\x1b[B'); break;
}
});
qsa('#buttons button').forEach(function(s) { qsa('#buttons button').forEach(function(s) {
s.addEventListener('click', function() { s.addEventListener('click', function() {
sendBtnMsg(+this.dataset['n']); sendBtnMsg(+this.dataset['n']);
});
}); });
} });
}
return { return {
init: init, init: init,
onTap: sendPosMsg onTap: sendPosMsg
};
})();
window.termInit = function (obj) {
Term.init(obj);
Conn.init();
Input.init();
}; };
})(); })();
window.termInit = function (str) {
Screen.load(str);
Conn.init();
Input.init();
};

@ -27,27 +27,22 @@ return [
Those are the initial settings used after ESPTerm powers on. They Those are the initial settings used after ESPTerm powers on. They
will also be applied immediately after you submit this form.', will also be applied immediately after you submit this form.',
'term.example' => 'Color settings example', 'term.example' => 'Default colors preview',
'term.term_title' => 'Header text', 'term.term_title' => 'Header text',
'term.term_width' => 'Screen width', 'term.term_width' => 'Screen width / height',
'term.term_height' => 'Screen height', 'term.default_fg_bg' => 'Text / background',
'term.default_fg' => 'Text color', 'term.buttons' => 'Button labels',
'term.default_bg' => 'Background', 'term.theme' => 'Color scheme',
'term.btn1' => 'Button 1 text',
'term.btn2' => 'Button 2 text',
'term.btn3' => 'Button 3 text',
'term.btn4' => 'Button 4 text',
'term.btn5' => 'Button 5 text',
// terminal color labels // terminal color labels
'color.0' => 'Black', 'color.0' => 'Black',
'color.1' => 'Dark Red', 'color.1' => 'Red',
'color.2' => 'Dark Green', 'color.2' => 'Green',
'color.3' => 'Dim Yellow', 'color.3' => 'Yellow',
'color.4' => 'Deep Blue', 'color.4' => 'Blue',
'color.5' => 'Deep Purple', 'color.5' => 'Purple',
'color.6' => 'Dark Cyan', 'color.6' => 'Cyan',
'color.7' => 'Silver', 'color.7' => 'Silver',
'color.8' => 'Gray', 'color.8' => 'Gray',
'color.9' => 'Light Red', 'color.9' => 'Light Red',

@ -6,21 +6,78 @@
</div> </div>
<div class="Row"> <div class="Row">
<div style="font-family:monospace; font-size: 16pt; padding: 5px;" id="color-example"><?= tr("term.example") ?></div> <label for="theme"><?= tr("term.theme") ?></label>
<select name="theme" id="theme" class="short" onchange="showColor()">
<option value="0">Tango</option>
<option value="1">Linux</option>
<option value="2">XTerm</option>
<option value="3">Rxvt</option>
<option value="4">Ambience</option>
<option value="5">Solarized</option>
</select>
</div>
<div class="Row color-preview">
<div class="colorprev">
<span data-fg=0 class="bg0 fg0">30</span><!--
--><span data-fg=1 class="bg0 fg1">31</span><!--
--><span data-fg=2 class="bg0 fg2">32</span><!--
--><span data-fg=3 class="bg0 fg3">33</span><!--
--><span data-fg=4 class="bg0 fg4">34</span><!--
--><span data-fg=5 class="bg0 fg5">35</span><!--
--><span data-fg=6 class="bg0 fg6">36</span><!--
--><span data-fg=7 class="bg0 fg7">37</span>
</div>
<div class="colorprev">
<span data-fg=8 class="bg0 fg8">90</span><!--
--><span data-fg=9 class="bg0 fg9">91</span><!--
--><span data-fg=10 class="bg0 fg10">92</span><!--
--><span data-fg=11 class="bg0 fg11">93</span><!--
--><span data-fg=12 class="bg0 fg12">94</span><!--
--><span data-fg=13 class="bg0 fg13">95</span><!--
--><span data-fg=14 class="bg0 fg14">96</span><!--
--><span data-fg=15 class="bg0 fg15">97</span>
</div>
<div class="colorprev">
<span data-bg=0 class="bg0 fg15">40</span><!--
--><span data-bg=1 class="bg1 fg15">41</span><!--
--><span data-bg=2 class="bg2 fg15">42</span><!--
--><span data-bg=3 class="bg3 fg0">43</span><!--
--><span data-bg=4 class="bg4 fg15">44</span><!--
--><span data-bg=5 class="bg5 fg15">45</span><!--
--><span data-bg=6 class="bg6 fg15">46</span><!--
--><span data-bg=7 class="bg7 fg0">47</span>
</div>
<div class="colorprev">
<span data-bg=8 class="bg8 fg15">100</span><!--
--><span data-bg=9 class="bg9 fg0">101</span><!--
--><span data-bg=10 class="bg10 fg0">102</span><!--
--><span data-bg=11 class="bg11 fg0">103</span><!--
--><span data-bg=12 class="bg12 fg0">104</span><!--
--><span data-bg=13 class="bg13 fg0">105</span><!--
--><span data-bg=14 class="bg14 fg0">106</span><!--
--><span data-bg=15 class="bg15 fg0">107</span>
</div>
</div>
<div class="Row color-preview">
<div style="
" id="color-example">
<?= tr("term.example") ?>
</div>
</div> </div>
<div class="Row"> <div class="Row">
<label for="default_fg"><?= tr("term.default_fg") ?></label> <label><?= tr("term.default_fg_bg") ?></label>
<select name="default_fg" id="default_fg" class="short" onchange="showColor()"> <select name="default_fg" id="default_fg" class="short" onchange="showColor()">
<?php for($i=0; $i<16; $i++): ?> <?php for($i=0; $i<16; $i++): ?>
<option value="<?=$i?>"><?= tr("color.$i") ?></option> <option value="<?=$i?>"><?= tr("color.$i") ?></option>
<?php endfor; ?> <?php endfor; ?>
</select> </select>&nbsp;<!--
</div> --><select name="default_bg" id="default_bg" class="short" onchange="showColor()">
<div class="Row">
<label for="default_bg"><?= tr("term.default_bg") ?></label>
<select name="default_bg" id="default_bg" class="short" onchange="showColor()">
<?php for($i=0; $i<16; $i++): ?> <?php for($i=0; $i<16; $i++): ?>
<option value="<?=$i?>"><?= tr("color.$i") ?></option> <option value="<?=$i?>"><?= tr("color.$i") ?></option>
<?php endfor; ?> <?php endfor; ?>
@ -29,12 +86,8 @@
<div class="Row"> <div class="Row">
<label for="term_width"><?= tr('term.term_width') ?></label> <label for="term_width"><?= tr('term.term_width') ?></label>
<input type="number" step=1 min=1 max=255 name="term_width" id="term_width" value="%term_width%" required> <input type="number" step=1 min=1 max=255 name="term_width" id="term_width" value="%term_width%" required>&nbsp;<!--
</div> --><input type="number" step=1 min=1 max=255 name="term_height" id="term_height" value="%term_height%" required>
<div class="Row">
<label for="term_height"><?= tr('term.term_height') ?></label>
<input type="number" step=1 min=1 max=255 name="term_height" id="term_height" value="%term_height%" required>
</div> </div>
<div class="Row"> <div class="Row">
@ -43,27 +96,11 @@
</div> </div>
<div class="Row"> <div class="Row">
<label for="btn1"><?= tr("term.btn1") ?></label> <label><?= tr("term.buttons") ?></label>
<input class="short" type="text" name="btn1" id="btn1" value="%btn1%"> <input class="short" type="text" name="btn1" id="btn1" value="%btn1%">&nbsp;
</div> <input class="short" type="text" name="btn2" id="btn2" value="%btn2%">&nbsp;
<input class="short" type="text" name="btn3" id="btn3" value="%btn3%">&nbsp;
<div class="Row"> <input class="short" type="text" name="btn4" id="btn4" value="%btn4%">&nbsp;
<label for="btn2"><?= tr("term.btn2") ?></label>
<input class="short" type="text" name="btn2" id="btn2" value="%btn2%">
</div>
<div class="Row">
<label for="btn3"><?= tr("term.btn3") ?></label>
<input class="short" type="text" name="btn3" id="btn3" value="%btn3%">
</div>
<div class="Row">
<label for="btn4"><?= tr("term.btn4") ?></label>
<input class="short" type="text" name="btn4" id="btn4" value="%btn4%">
</div>
<div class="Row">
<label for="btn5"><?= tr("term.btn5") ?></label>
<input class="short" type="text" name="btn5" id="btn5" value="%btn5%"> <input class="short" type="text" name="btn5" id="btn5" value="%btn5%">
</div> </div>
@ -75,12 +112,25 @@
<script> <script>
$('#default_fg').val(%default_fg%); $('#default_fg').val(%default_fg%);
$('#default_bg').val(%default_bg%); $('#default_bg').val(%default_bg%);
$('#theme').val(%theme%);
function showColor() { function showColor() {
var ex = qs('#color-example'); var ex = qs('#color-example');
ex.className = ''; ex.className = '';
ex.classList.add('fg'+$('#default_fg').val()); ex.classList.add('fg'+$('#default_fg').val());
ex.classList.add('bg'+$('#default_bg').val()); ex.classList.add('bg'+$('#default_bg').val());
var th = $('#theme').val();
$('.color-preview').forEach(function(e) {
e.className = 'Row color-preview theme-'+th;
});
} }
showColor(); showColor();
$('.colorprev span').on('click', function() {
var fg = this.dataset.fg;
var bg = this.dataset.bg;
if (typeof fg != 'undefined') $('#default_fg').val(fg);
if (typeof bg != 'undefined') $('#default_bg').val(bg);
showColor()
});
</script> </script>

@ -178,7 +178,7 @@
<tr> <tr>
<td>\e[&lt;n&gt;E</td> <td>\e[&lt;n&gt;E</td>
<td>[count]</td> <td>[count]</td>
<td>Go N line down, start of line</td> <td>Go N lines down, start of line</td>
</tr> </tr>
<tr> <tr>
<td>\e[&lt;n&gt;F</td> <td>\e[&lt;n&gt;F</td>

@ -2,6 +2,7 @@
// Workaround for badly loaded page // Workaround for badly loaded page
setTimeout(function() { setTimeout(function() {
if (typeof termInit == 'undefined' || typeof $ == 'undefined') { if (typeof termInit == 'undefined' || typeof $ == 'undefined') {
console.error("Page load failed, refreshing…");
location.reload(true); location.reload(true);
} }
}, 2000); }, 2000);
@ -10,7 +11,7 @@
<h1>%term_title%</h1> <h1>%term_title%</h1>
<div id="termwrap"> <div id="termwrap">
<div id="screen"></div> <div id="screen" class="theme-%theme%"></div>
<div id="buttons"> <div id="buttons">
<button data-n="1" class="btn-blue">%btn1%</button><!-- <button data-n="1" class="btn-blue">%btn1%</button><!--
@ -21,17 +22,32 @@
</div> </div>
</div> </div>
<input id="softkb-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
<nav id="botnav"> <nav id="botnav">
<a href="<?= url('cfg_wifi') ?>"><?= tr('menu.settings') ?></a><!-- <a href="#" onclick="toggleSoftKb(true); return false" class="icn-keyboard mq-tablet-max"></a><!--
--><a href="<?= url('help') ?>">Help</a><!-- --><a href="<?= url('cfg_wifi') ?>"><?= tr('menu.settings') ?></a><!--
--><a href="<?= url('about') ?>">About</a> --><a href="<?= url('help') ?>">Help</a><!--
--><a href="<?= url('about') ?>">About</a>
</nav> </nav>
<script> <script>
// TODO cleanup
try { try {
termInit(%screenData%); termInit("%screenData%");
// auto-clear the input box
$('#softkb-input').on('input', function(e) {
setTimeout(function(){$('#softkb-input').val('');}, 1);
});
} catch(e) { } catch(e) {
console.error("Fail, reloading..."); console.error(e);
console.error("Fail, reloading…");
location.reload(true); location.reload(true);
} }
function toggleSoftKb(yes) {
qs('#softkb-input')[yes ? 'focus' : 'blur']();
qs('.icn-keyboard').blur();
}
</script> </script>

File diff suppressed because one or more lines are too long

@ -1,24 +0,0 @@
$term-colors:
// 0 black, 1 red, 2 green, 3 yellow
// 4 blue, 5 mag, 6 cyan, 7 white
#111213, #CC0000, #4E9A06, #C4A000,
#3465A4, #75507B, #06989A, #D3D7CF,
// BRIGHT
// 8 black, 9 red, 10 green, 11 yellow
// 12 blue, 13 mag, 14 cyan, 15 white
#555753, #EF2929, #8AE234, #FCE94F,
#729FCF, #AD7FA8, #34E2E2, #EEEEEC;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
.fg8, .fg9, .fg10, .fg11, .fg12, .fg13, .fg14, .fg15 {
font-weight: bold;
}
.nb {
font-weight: normal !important;
}

@ -33,7 +33,6 @@ $c-form-highlight-a: #2ea1f9;
@import "pages/wifi"; @import "pages/wifi";
@import "pages/term"; @import "pages/term";
@import "pages/about"; @import "pages/about";
@import "term-colors";
// media queries // media queries

@ -1,8 +1,13 @@
body.term { body.term {
h1 { #content {
font-size: fsize(5); padding-left: 0;
@include media($phone) { padding-right: 0;
font-size: fsize(3);
h1 {
font-size: fsize(5);
@include media($phone) {
font-size: fsize(3);
}
} }
} }
@ -36,7 +41,7 @@ body.term {
margin: 0 3px; margin: 0 3px;
padding: 8px 5px; padding: 8px 5px;
//width: 18%; //width: 18%;
min-width: 65px; min-width: 62px;
//max-width: 65px; //max-width: 65px;
//min-width: initial; //min-width: initial;
cursor: pointer; cursor: pointer;
@ -53,16 +58,133 @@ body.term {
text-decoration: underline; text-decoration: underline;
&, &:visited, &:link { &, &:visited, &:link {
color: #2e4d6e; color: #336085;
} }
&:hover { &:hover {
color: #5abfff; color: #5abfff;
} }
} }
.icn-keyboard {
text-decoration: none;
font-size: 150%;
vertical-align: middle;
}
} }
} }
#termwrap { #termwrap {
text-align: center; text-align: center;
} }
#softkb-input {
position: absolute;
top: -9999px;
}
// "non-bold"
.nb {
font-weight: normal !important;
}
// Tango
.theme-0 {
$term-colors:
#111213, #CC0000, #4E9A06, #C4A000, #3465A4, #75507B, #06989A, #D3D7CF,
#555753, #EF2929, #8AE234, #FCE94F, #729FCF, #AD7FA8, #34E2E2, #EEEEEC;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
// Linux
.theme-1 {
$term-colors:
#000000, #aa0000, #00aa00, #aa5500, #0000aa, #aa00aa, #00aaaa, #aaaaaa,
#555555, #ff5555, #55ff55, #ffff55, #5555ff, #ff55ff, #55ffff, #ffffff;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
// xterm
.theme-2 {
$term-colors:
#000000, #cd0000, #00cd00, #cdcd00, #0000ee, #cd00cd, #00cdcd, #e5e5e5,
#7f7f7f, #ff0000, #00ff00, #ffff00, #5c5cff, #ff00ff, #00ffff, #ffffff;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
// rxvt
.theme-3 {
$term-colors:
#000000, #cd0000, #00cd00, #cdcd00, #0000cd, #cd00cd, #00cdcd, #faebd7,
#404040, #ff0000, #00ff00, #ffff00, #0000ff, #ff00ff, #00ffff, #ffffff;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
// Ambience
.theme-4 {
$term-colors:
#2e3436, #cc0000, #4e9a06, #c4a000, #3465a4, #75507b, #06989a, #d3d7cf,
#555753, #ef2929, #8ae234, #fce94f, #729fcf, #ad7fa8, #34e2e2, #eeeeec;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
// Solarized
.theme-5 {
$term-colors:
#073642, #dc322f, #859900, #b58900, #268bd2, #d33682, #2aa198, #eee8d5,
#002b36, #cb4b16, #586e75, #657b83, #839496, #6c71c4, #93a1a1, #fdf6e3;
@for $i from 1 through length($term-colors) {
$c: nth($term-colors, $i);
.fg#{$i - 1} { color: $c; }
.bg#{$i - 1} { background-color: $c; }
}
}
.bold {
font-weight: bold !important;
}
.Row.color-preview {
font-family: monospace;
font-size: 16pt;
display: block;
margin-bottom: 0;
padding-left: $form-label-w;
@include media($phone) {
padding-left: 0;
font-size: 14pt;
}
.colorprev {
display:block;
margin: 0;
cursor: pointer;
}
}
#color-example {
display: inline-block;
padding: 5px;
}

@ -44,12 +44,16 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token
else if (streq(token, "btn5")) { else if (streq(token, "btn5")) {
httpdSend(connData, termconf->btn5, -1); httpdSend(connData, termconf->btn5, -1);
} }
else if (streq(token, "default_bg")) { // else if (streq(token, "default_bg")) {
sprintf(buff, "%d", termconf->default_bg); // sprintf(buff, "%d", termconf->default_bg);
httpdSend(connData, buff, -1); // httpdSend(connData, buff, -1);
} // }
else if (streq(token, "default_fg")) { // else if (streq(token, "default_fg")) {
sprintf(buff, "%d", termconf->default_fg); // sprintf(buff, "%d", termconf->default_fg);
// httpdSend(connData, buff, -1);
// }
else if (streq(token, "theme")) {
sprintf(buff, "%d", termconf->theme);
httpdSend(connData, buff, -1); httpdSend(connData, buff, -1);
} }
else if (streq(token, "screenData")) { else if (streq(token, "screenData")) {

@ -82,6 +82,17 @@ cgiTermCfgSetParams(HttpdConnData *connData)
} }
} }
if (GET_ARG("theme")) {
dbg("Screen color theme: %s", buff);
int theme = atoi(buff);
if (theme >= 0 && theme <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME!
termconf->theme = (u8) theme;
} else {
warn("Bad theme num: %s", buff);
redir_url += sprintf(redir_url, "theme,");
}
}
if (GET_ARG("term_title")) { if (GET_ARG("term_title")) {
dbg("Terminal title default text: \"%s\"", buff); dbg("Terminal title default text: \"%s\"", buff);
strncpy_safe(termconf->title, buff, 64); // ATTN those must match the values in strncpy_safe(termconf->title, buff, 64); // ATTN those must match the values in
@ -148,6 +159,9 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
else if (streq(token, "term_height")) { else if (streq(token, "term_height")) {
sprintf(buff, "%d", termconf->height); sprintf(buff, "%d", termconf->height);
} }
else if (streq(token, "theme")) {
sprintf(buff, "%d", termconf->theme);
}
else if (streq(token, "default_bg")) { else if (streq(token, "default_bg")) {
sprintf(buff, "%d", termconf->default_bg); sprintf(buff, "%d", termconf->default_bg);
} }

@ -105,7 +105,15 @@ persist_load(void)
} }
if (hard_reset) { if (hard_reset) {
// Zero all out
memset(&persist, 0, sizeof(PersistBlock));
persist_load_hard_default(); persist_load_hard_default();
// write them also as defaults
memcpy(&persist.defaults, &persist.current, sizeof(AppConfigBundle));
persist_store();
// this also stores them to flash and applies to modules // this also stores them to flash and applies to modules
} else { } else {
apply_live_settings(); apply_live_settings();
@ -141,9 +149,6 @@ persist_load_hard_default(void)
restore_live_settings_to_hard_defaults(); restore_live_settings_to_hard_defaults();
persist_store(); persist_store();
// // Store current -> default
// memcpy(&persist.defaults, &persist.current, sizeof(AppConfigBundle));
info("[Persist] Settings restored to hard defaults."); info("[Persist] Settings restored to hard defaults.");
apply_live_settings(); // apply apply_live_settings(); // apply

@ -16,7 +16,7 @@
// Changing this could be used to force-erase the config area // Changing this could be used to force-erase the config area
// after a firmware upgrade // after a firmware upgrade
#define CHECKSUM_SALT 1 #define CHECKSUM_SALT 2
#define APPCONF_SIZE 2048 #define APPCONF_SIZE 2048

@ -671,7 +671,25 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
ss->lastFg = 0; ss->lastFg = 0;
ss->lastChar = '\0'; ss->lastChar = '\0';
bufprint("{\n \"w\": %d, \"h\": %d,\n \"x\": %d, \"y\": %d,\n \"cv\": %d,\n \"screen\": \"", W, H, cursor.x, cursor.y, cursor.visible); // TODO implement the new more efficient encoder!
bufprint(
"{"
"\"w\":%d,"
"\"h\":%d,"
"\"x\":%d,"
"\"y\":%d,"
"\"fg\":%d,"
"\"bg\":%d,"
"\"cv\":%d,"
"\"screen\":\"",
W,
H,
cursor.x,
cursor.y,
cursor.fg,
cursor.bg,
cursor.visible);
} }
int i = ss->index; int i = ss->index;

@ -52,6 +52,7 @@ typedef struct {
char btn3[TERM_BTN_LEN]; char btn3[TERM_BTN_LEN];
char btn4[TERM_BTN_LEN]; char btn4[TERM_BTN_LEN];
char btn5[TERM_BTN_LEN]; char btn5[TERM_BTN_LEN];
u8 theme;
u8 _filler[ u8 _filler[
TERMCONF_SIZE TERMCONF_SIZE
@ -59,6 +60,7 @@ typedef struct {
- 4 - 4
- 1 - 1
- 1 - 1
- 1
- TERM_TITLE_LEN - TERM_TITLE_LEN
- TERM_BTN_LEN * 5 - TERM_BTN_LEN * 5
]; ];

Loading…
Cancel
Save