use xmacros for terminal config
This commit is contained in:
+1
-1
@@ -59,7 +59,7 @@ apars_handle_osc(char *buffer)
|
||||
}
|
||||
else if (n >= 91 && n <= 95) {
|
||||
// ESPTerm: action button message
|
||||
strncpy(termconf_live.btn_msg[n - 91], buffer, TERM_BTN_MSG_LEN);
|
||||
screen_set_button_message(n - 90, buffer);
|
||||
}
|
||||
else {
|
||||
ansi_noimpl("OSC %d ; %s ST", n, buffer);
|
||||
|
||||
+2
-2
@@ -271,8 +271,8 @@ static void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int
|
||||
case 'b':
|
||||
// action button press
|
||||
btnNum = (u8) (data[1]);
|
||||
if (btnNum > 0 && btnNum < 10) {
|
||||
UART_SendAsync(termconf_live.btn_msg[btnNum-1], -1);
|
||||
if (btnNum > 0 && btnNum <= TERM_BTN_COUNT) {
|
||||
UART_SendAsync(TERM_BM_N(&termconf_live, btnNum-1), -1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+10
-5
@@ -12,9 +12,6 @@
|
||||
#define SET_REDIR_SUC "/cfg/system"
|
||||
#define SET_REDIR_ERR SET_REDIR_SUC"?err="
|
||||
|
||||
// Select which struct we want to use for X tables
|
||||
#define XSTRUCT sysconf
|
||||
|
||||
static ETSTimer tmr;
|
||||
|
||||
static void ICACHE_FLASH_ATTR tmrCb(void *arg)
|
||||
@@ -99,7 +96,9 @@ cgiSystemCfgSetParams(HttpdConnData *connData)
|
||||
memcpy(sysconf_backup, sysconf, sizeof(SystemConfigBundle));
|
||||
|
||||
// flags for the template builder
|
||||
bool admin = false, tpl = false;
|
||||
bool uart_changed = false; //!< this is set in uart notify, for use in terminal settings (dummy here)
|
||||
bool admin = false;
|
||||
const bool tpl = false; // this optionally disables some fields
|
||||
do {
|
||||
// Check admin PW
|
||||
if (GET_ARG("pw")) {
|
||||
@@ -164,13 +163,16 @@ cgiSystemCfgSetParams(HttpdConnData *connData)
|
||||
}
|
||||
|
||||
// Settings in the system config block
|
||||
#define XSTRUCT sysconf
|
||||
#define X XSET_CGI_FUNC
|
||||
XTABLE_SYSCONF
|
||||
#undef X
|
||||
#undef XSTRUCT
|
||||
|
||||
} while (0);
|
||||
|
||||
(void)redir_url;
|
||||
(void)uart_changed; // unused
|
||||
|
||||
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
||||
// All was OK
|
||||
@@ -210,11 +212,14 @@ tplSystemCfg(HttpdConnData *connData, char *token, void **arg)
|
||||
|
||||
strcpy(buff, ""); // fallback
|
||||
|
||||
const bool admin = false, tpl=true;
|
||||
const bool admin = false;
|
||||
const bool tpl=true;
|
||||
|
||||
#define XSTRUCT sysconf
|
||||
#define X XGET_CGI_FUNC
|
||||
XTABLE_SYSCONF
|
||||
#undef X
|
||||
#undef XSTRUCT
|
||||
|
||||
if (streq(token, "def_access_name")) {
|
||||
sprintf(buff, "%s", DEF_ACCESS_NAME);
|
||||
|
||||
+35
-447
@@ -15,22 +15,6 @@ Cgi/template routines for configuring non-wifi settings
|
||||
#define SET_REDIR_SUC "/cfg/term"
|
||||
#define SET_REDIR_ERR SET_REDIR_SUC"?err="
|
||||
|
||||
/** convert hex number to int */
|
||||
static ICACHE_FLASH_ATTR u32
|
||||
decodehex(const char *buf) {
|
||||
u32 n = 0;
|
||||
char c;
|
||||
while ((c = *buf++) != 0) {
|
||||
if (c >= '0' && c <= '9') c -= '0';
|
||||
else if (c >= 'a' && c <= 'f') c -= 'a'-10;
|
||||
else if (c >= 'A' && c <= 'F') c -= 'A'-10;
|
||||
else c = 0;
|
||||
n *= 16;
|
||||
n += c;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Universal CGI endpoint to set Terminal params.
|
||||
*/
|
||||
@@ -39,15 +23,11 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
||||
{
|
||||
char buff[50];
|
||||
char redir_url_buf[100];
|
||||
int32 n, w, h;
|
||||
ScreenNotifyTopics topics = 0;
|
||||
|
||||
bool shall_clear_screen = false;
|
||||
bool shall_init_uart = false;
|
||||
|
||||
char *redir_url = redir_url_buf;
|
||||
redir_url += sprintf(redir_url, SET_REDIR_ERR);
|
||||
// we'll test if anything was printed by looking for \0 in failed_keys_buf
|
||||
// we'll test if anything was printed by looking for \0 in redir_url
|
||||
|
||||
SystemConfigBundle *sysconf_backup = malloc(sizeof(SystemConfigBundle));
|
||||
TerminalConfigBundle *termconf_backup = malloc(sizeof(TerminalConfigBundle));
|
||||
@@ -59,328 +39,29 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
#define XSTRUCT termconf
|
||||
#define X XSET_CGI_FUNC
|
||||
XTABLE_TERMCONF
|
||||
#undef X
|
||||
#undef XSTRUCT
|
||||
|
||||
// width and height must always go together so we can do max size validation
|
||||
if (GET_ARG("term_width")) {
|
||||
do {
|
||||
cgi_dbg("Default screen width: %s", buff);
|
||||
w = atoi(buff);
|
||||
if (w < 1) {
|
||||
cgi_warn("Bad width: \"%s\"", buff);
|
||||
redir_url += sprintf(redir_url, "term_width,");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!GET_ARG("term_height")) {
|
||||
cgi_warn("Missing height arg!");
|
||||
// this wont happen normally when the form is used
|
||||
redir_url += sprintf(redir_url, "term_height,");
|
||||
break;
|
||||
}
|
||||
|
||||
cgi_dbg("Default screen height: %s", buff);
|
||||
h = atoi(buff);
|
||||
if (h < 1) {
|
||||
cgi_warn("Bad height: \"%s\"", buff);
|
||||
redir_url += sprintf(redir_url, "term_height,");
|
||||
break;
|
||||
}
|
||||
|
||||
if (w * h > MAX_SCREEN_SIZE) {
|
||||
cgi_warn("Bad dimensions: %d x %d (total %d)", w, h, w * h);
|
||||
redir_url += sprintf(redir_url, "term_width,term_height,");
|
||||
break;
|
||||
}
|
||||
|
||||
if (termconf->width != w || termconf->height != h) {
|
||||
termconf->width = w;
|
||||
termconf->height = h;
|
||||
shall_clear_screen = true;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS | TOPIC_CHANGE_CONTENT_ALL;
|
||||
}
|
||||
} while (0);
|
||||
u32 siz = termconf->width*termconf->height;
|
||||
if (siz == 0 || siz > MAX_SCREEN_SIZE) {
|
||||
cgi_warn("Bad dimensions: %d x %d (total %d)", termconf->width, termconf->height, termconf->width*termconf->height);
|
||||
redir_url += sprintf(redir_url, "term_width,term_height,");
|
||||
}
|
||||
|
||||
if (GET_ARG("default_bg")) {
|
||||
cgi_dbg("Screen default BG: %s", buff);
|
||||
|
||||
if (buff[0] == '#') {
|
||||
// decode hex
|
||||
n = decodehex(buff+1);
|
||||
n += 256;
|
||||
} else {
|
||||
n = atoi(buff);
|
||||
}
|
||||
|
||||
if (termconf->default_bg != n) {
|
||||
termconf->default_bg = n; // this is current not sent through socket, no use to notify
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("default_fg")) {
|
||||
cgi_dbg("Screen default FG: %s", buff);
|
||||
|
||||
if (buff[0] == '#') {
|
||||
// decode hex
|
||||
n = decodehex(buff+1);
|
||||
n += 256;
|
||||
} else {
|
||||
n = atoi(buff);
|
||||
}
|
||||
|
||||
if (termconf->default_fg != n) {
|
||||
termconf->default_fg = n; // this is current not sent through socket, no use to notify
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("parser_tout_ms")) {
|
||||
cgi_dbg("Parser timeout: %s ms", buff);
|
||||
n = atoi(buff);
|
||||
if (n >= 0) {
|
||||
termconf->parser_tout_ms = n;
|
||||
} else {
|
||||
cgi_warn("Bad parser timeout %s", buff);
|
||||
redir_url += sprintf(redir_url, "parser_tout_ms,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("display_tout_ms")) {
|
||||
cgi_dbg("Display update idle timeout: %s ms", buff);
|
||||
n = atoi(buff);
|
||||
if (n >= 0) {
|
||||
termconf->display_tout_ms = n;
|
||||
} else {
|
||||
cgi_warn("Bad update timeout %s", buff);
|
||||
redir_url += sprintf(redir_url, "display_tout_ms,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("display_cooldown_ms")) {
|
||||
cgi_dbg("Display update cooldown: %s ms", buff);
|
||||
n = atoi(buff);
|
||||
if (n > 0) {
|
||||
termconf->display_cooldown_ms = n;
|
||||
} else {
|
||||
cgi_warn("Bad cooldown %s", buff);
|
||||
redir_url += sprintf(redir_url, "display_cooldown_ms,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("fn_alt_mode")) {
|
||||
cgi_dbg("FN alt mode: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->fn_alt_mode = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("want_all_fn")) {
|
||||
cgi_dbg("AllFN mode: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->want_all_fn = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("crlf_mode")) {
|
||||
cgi_dbg("CRLF mode: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->crlf_mode = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("show_buttons")) {
|
||||
cgi_dbg("Show buttons: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->show_buttons = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("show_config_links")) {
|
||||
cgi_dbg("Show config links: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->show_config_links = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("loopback")) {
|
||||
cgi_dbg("Loopback: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->loopback = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("debugbar")) {
|
||||
cgi_dbg("Debugbar: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->debugbar = (bool)n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
|
||||
if (GET_ARG("allow_decopt_12")) {
|
||||
cgi_dbg("DECOPT 12: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->allow_decopt_12 = (bool)n;
|
||||
}
|
||||
|
||||
if (GET_ARG("ascii_debug")) {
|
||||
cgi_dbg("ascii_debug: %s", buff);
|
||||
n = atoi(buff);
|
||||
termconf->ascii_debug = (bool)n;
|
||||
shall_clear_screen = true;
|
||||
}
|
||||
|
||||
if (GET_ARG("theme")) {
|
||||
cgi_dbg("Screen color theme: %s", buff);
|
||||
n = atoi(buff);
|
||||
if (n >= 0) {
|
||||
termconf->theme = (u8) n;
|
||||
// this can't be notified, page must reload.
|
||||
} else {
|
||||
cgi_warn("Bad theme num: %s", buff);
|
||||
redir_url += sprintf(redir_url, "theme,");
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("cursor_shape")) {
|
||||
cgi_dbg("Cursor shape: %s", buff);
|
||||
n = atoi(buff);
|
||||
if (n >= 0 && n <= 6 && n != 1) {
|
||||
termconf->cursor_shape = (enum CursorShape) n;
|
||||
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||
} else {
|
||||
cgi_warn("Bad cursor_shape num: %s", buff);
|
||||
redir_url += sprintf(redir_url, "cursor_shape,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("term_title")) {
|
||||
cgi_dbg("Terminal title default text: \"%s\"", buff);
|
||||
strncpy_safe(termconf->title, buff, TERM_TITLE_LEN); // ATTN those must match the values in
|
||||
topics |= TOPIC_CHANGE_TITLE;
|
||||
}
|
||||
|
||||
if (GET_ARG("backdrop")) {
|
||||
cgi_dbg("Terminal backdrop url: \"%s\"", buff);
|
||||
strncpy_safe(termconf->backdrop, buff, TERM_BACKDROP_LEN); // ATTN those must match the values in
|
||||
topics |= TOPIC_CHANGE_BACKDROP;
|
||||
}
|
||||
|
||||
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
||||
sprintf(buff, "btn%d", btn_i);
|
||||
if (GET_ARG(buff)) {
|
||||
cgi_dbg("Button%d default text: \"%s\"", btn_i, buff);
|
||||
strncpy_safe(termconf->btn[btn_i-1], buff, TERM_BTN_LEN);
|
||||
topics |= TOPIC_CHANGE_BUTTONS;
|
||||
}
|
||||
|
||||
sprintf(buff, "bm%d", btn_i);
|
||||
if (GET_ARG(buff)) {
|
||||
cgi_dbg("Button%d message (ASCII): \"%s\"", btn_i, buff);
|
||||
|
||||
// parse: comma,space or semicolon separated decimal values of ASCII codes
|
||||
char c;
|
||||
char *cp = buff;
|
||||
int char_i = 0;
|
||||
int acu = 0;
|
||||
bool lastsp = 1;
|
||||
char buff_bm[TERM_BTN_MSG_LEN];
|
||||
while ((c = *cp++) != 0) {
|
||||
if (c == ' ' || c == ',' || c == ';') {
|
||||
if(lastsp) continue;
|
||||
|
||||
if (acu==0 || acu>255) {
|
||||
cgi_warn("Bad value! %d", acu);
|
||||
redir_url += sprintf(redir_url, "bm%d,", btn_i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (char_i >= TERM_BTN_MSG_LEN-1) {
|
||||
cgi_warn("Too long! %d", acu);
|
||||
redir_url += sprintf(redir_url, "bm%d,", btn_i);
|
||||
break;
|
||||
}
|
||||
|
||||
cgi_dbg("acu %d", acu);
|
||||
buff_bm[char_i++] = (char)acu;
|
||||
|
||||
// prepare for next char
|
||||
acu = 0;
|
||||
lastsp = 1;
|
||||
} else if (c>='0'&&c<='9') {
|
||||
lastsp = 0;
|
||||
acu *= 10;
|
||||
acu += c - '0';
|
||||
} else {
|
||||
cgi_warn("Bad syntax!");
|
||||
redir_url += sprintf(redir_url, "bm%d,", btn_i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastsp && char_i == 0) {
|
||||
cgi_warn("Required!");
|
||||
redir_url += sprintf(redir_url, "bm%d,", btn_i);
|
||||
}
|
||||
if (!lastsp) {
|
||||
buff_bm[char_i++] = (char)acu;
|
||||
}
|
||||
buff_bm[char_i] = 0;
|
||||
cgi_dbg("%s, chari = %d", buff_bm, char_i);
|
||||
|
||||
strncpy(termconf->btn_msg[btn_i-1], buff_bm, TERM_BTN_MSG_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("uart_baud")) {
|
||||
cgi_dbg("Baud rate: %s", buff);
|
||||
int baud = atoi(buff);
|
||||
if (baud == BIT_RATE_300 ||
|
||||
baud == BIT_RATE_600 ||
|
||||
baud == BIT_RATE_1200 ||
|
||||
baud == BIT_RATE_2400 ||
|
||||
baud == BIT_RATE_4800 ||
|
||||
baud == BIT_RATE_9600 ||
|
||||
baud == BIT_RATE_19200 ||
|
||||
baud == BIT_RATE_38400 ||
|
||||
baud == BIT_RATE_57600 ||
|
||||
baud == BIT_RATE_74880 ||
|
||||
baud == BIT_RATE_115200 ||
|
||||
baud == BIT_RATE_230400 ||
|
||||
baud == BIT_RATE_460800 ||
|
||||
baud == BIT_RATE_921600 ||
|
||||
baud == BIT_RATE_1843200 ||
|
||||
baud == BIT_RATE_3686400) {
|
||||
sysconf->uart_baudrate = (u32) baud;
|
||||
shall_init_uart = true;
|
||||
} else {
|
||||
cgi_warn("Bad baud rate %s", buff);
|
||||
redir_url += sprintf(redir_url, "uart_baud,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("uart_parity")) {
|
||||
cgi_dbg("Parity: %s", buff);
|
||||
int parity = atoi(buff);
|
||||
if (parity >= 0 && parity <= 2) {
|
||||
sysconf->uart_parity = (UartParityMode) parity;
|
||||
shall_init_uart = true;
|
||||
} else {
|
||||
cgi_warn("Bad parity %s", buff);
|
||||
redir_url += sprintf(redir_url, "uart_parity,");
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_ARG("uart_stopbits")) {
|
||||
cgi_dbg("Stop bits: %s", buff);
|
||||
int stopbits = atoi(buff);
|
||||
if (stopbits >= 1 && stopbits <= 3) {
|
||||
sysconf->uart_stopbits = (UartStopBitsNum) stopbits;
|
||||
shall_init_uart = true;
|
||||
} else {
|
||||
cgi_warn("Bad stopbits %s", buff);
|
||||
redir_url += sprintf(redir_url, "uart_stopbits,");
|
||||
}
|
||||
}
|
||||
// Settings from SysConf - UART
|
||||
bool uart_changed = false;
|
||||
// restrict what keys are allowed
|
||||
#define admin 0
|
||||
#define tpl 0
|
||||
#define XSTRUCT sysconf
|
||||
#define X XSET_CGI_FUNC
|
||||
XTABLE_SYSCONF
|
||||
#undef X
|
||||
#undef XSTRUCT
|
||||
|
||||
(void)redir_url;
|
||||
|
||||
@@ -390,17 +71,23 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
||||
|
||||
persist_store();
|
||||
|
||||
bool shall_clear_screen = false;
|
||||
shall_clear_screen |= (termconf_backup->width != termconf->width);
|
||||
shall_clear_screen |= (termconf_backup->height != termconf->height);
|
||||
shall_clear_screen |= (termconf_backup->ascii_debug != termconf->ascii_debug);
|
||||
|
||||
if (shall_clear_screen) {
|
||||
terminal_apply_settings();
|
||||
} else {
|
||||
terminal_apply_settings_noclear();
|
||||
}
|
||||
|
||||
if (shall_init_uart) {
|
||||
serialInit();
|
||||
if (uart_changed) {
|
||||
sysconf_apply_settings();
|
||||
}
|
||||
|
||||
if (topics) screen_notifyChange(topics);
|
||||
// Trigger a full reload
|
||||
screen_notifyChange(TOPIC_INITIAL);
|
||||
|
||||
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||
} else {
|
||||
@@ -424,7 +111,6 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
||||
{
|
||||
#define BUFLEN 100 // large enough for backdrop
|
||||
char buff[BUFLEN];
|
||||
char buff2[10];
|
||||
|
||||
if (token == NULL) {
|
||||
// We're done
|
||||
@@ -433,109 +119,11 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
||||
|
||||
strcpy(buff, ""); // fallback
|
||||
|
||||
if (streq(token, "term_width")) {
|
||||
sprintf(buff, "%d", termconf->width);
|
||||
}
|
||||
else if (streq(token, "term_height")) {
|
||||
sprintf(buff, "%d", termconf->height);
|
||||
}
|
||||
else if (streq(token, "parser_tout_ms")) {
|
||||
sprintf(buff, "%d", termconf->parser_tout_ms);
|
||||
}
|
||||
else if (streq(token, "display_tout_ms")) {
|
||||
sprintf(buff, "%d", termconf->display_tout_ms);
|
||||
}
|
||||
else if (streq(token, "display_cooldown_ms")) {
|
||||
sprintf(buff, "%d", termconf->display_cooldown_ms);
|
||||
}
|
||||
else if (streq(token, "fn_alt_mode")) {
|
||||
sprintf(buff, "%d", (int)termconf->fn_alt_mode);
|
||||
}
|
||||
else if (streq(token, "want_all_fn")) {
|
||||
sprintf(buff, "%d", (int)termconf->want_all_fn);
|
||||
}
|
||||
else if (streq(token, "crlf_mode")) {
|
||||
sprintf(buff, "%d", (int)termconf->crlf_mode);
|
||||
}
|
||||
else if (streq(token, "show_buttons")) {
|
||||
sprintf(buff, "%d", (int)termconf->show_buttons);
|
||||
}
|
||||
else if (streq(token, "show_config_links")) {
|
||||
sprintf(buff, "%d", (int)termconf->show_config_links);
|
||||
}
|
||||
else if (streq(token, "allow_decopt_12")) {
|
||||
sprintf(buff, "%d", (int)termconf->allow_decopt_12);
|
||||
}
|
||||
else if (streq(token, "ascii_debug")) {
|
||||
sprintf(buff, "%d", (int)termconf->ascii_debug);
|
||||
}
|
||||
else if (streq(token, "loopback")) {
|
||||
sprintf(buff, "%d", (int)termconf->loopback);
|
||||
}
|
||||
else if (streq(token, "debugbar")) {
|
||||
sprintf(buff, "%d", (int)termconf->debugbar);
|
||||
}
|
||||
else if (streq(token, "theme")) {
|
||||
sprintf(buff, "%d", termconf->theme);
|
||||
}
|
||||
else if (streq(token, "default_bg")) {
|
||||
if (termconf->default_bg < 256) {
|
||||
sprintf(buff, "%d", termconf->default_bg);
|
||||
} else {
|
||||
sprintf(buff, "#%06X", termconf->default_bg - 256);
|
||||
}
|
||||
}
|
||||
else if (streq(token, "default_fg")) {
|
||||
if (termconf->default_fg < 256) {
|
||||
sprintf(buff, "%d", termconf->default_fg);
|
||||
} else {
|
||||
sprintf(buff, "#%06X", termconf->default_fg - 256);
|
||||
}
|
||||
}
|
||||
else if (streq(token, "cursor_shape")) {
|
||||
sprintf(buff, "%d", termconf->cursor_shape);
|
||||
}
|
||||
else if (streq(token, "term_title")) {
|
||||
strncpy_safe(buff, termconf->title, BUFLEN);
|
||||
}
|
||||
else if (streq(token, "backdrop")) {
|
||||
strncpy_safe(buff, termconf->backdrop, BUFLEN);
|
||||
}
|
||||
else if (streq(token, "uart_baud")) {
|
||||
sprintf(buff, "%d", sysconf->uart_baudrate);
|
||||
}
|
||||
else if (streq(token, "uart_parity")) {
|
||||
sprintf(buff, "%d", sysconf->uart_parity);
|
||||
}
|
||||
else if (streq(token, "uart_stopbits")) {
|
||||
sprintf(buff, "%d", sysconf->uart_stopbits);
|
||||
}
|
||||
else {
|
||||
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
||||
sprintf(buff2, "btn%d", btn_i);
|
||||
if (streq(token, buff2)) {
|
||||
strncpy_safe(buff, termconf->btn[btn_i-1], BUFLEN);
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buff2, "bm%d", btn_i);
|
||||
if (streq(token, buff2)) {
|
||||
char c;
|
||||
char *bp = buff;
|
||||
char *cp = termconf->btn_msg[btn_i-1];
|
||||
int n = 0;
|
||||
while((c = *cp++) != 0) {
|
||||
if(n>0) {
|
||||
*bp = ',';
|
||||
bp++;
|
||||
}
|
||||
bp += sprintf(bp, "%d", (int)c);
|
||||
n++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#define XSTRUCT termconf
|
||||
#define X XGET_CGI_FUNC
|
||||
XTABLE_TERMCONF
|
||||
#undef X
|
||||
#undef XSTRUCT
|
||||
|
||||
tplSend(connData, buff, -1);
|
||||
return HTTPD_CGI_DONE;
|
||||
|
||||
@@ -80,6 +80,32 @@ xset_u8(const char *name, u8 *field, const char *buff, const void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_u32(const char *name, u32 *field, const char *buff, const void *arg)
|
||||
{
|
||||
cgi_dbg("Setting %s = %s", name, buff);
|
||||
u32 val = (u32) atoi(buff);
|
||||
|
||||
if (*field != val) {
|
||||
*field = (u32) val;
|
||||
return XSET_SET;
|
||||
}
|
||||
return XSET_UNCHANGED;
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_u16(const char *name, u16 *field, const char *buff, const void *arg)
|
||||
{
|
||||
cgi_dbg("Setting %s = %s", name, buff);
|
||||
u16 val = (u16) atoi(buff);
|
||||
|
||||
if (*field != val) {
|
||||
*field = (u16) val;
|
||||
return XSET_SET;
|
||||
}
|
||||
return XSET_UNCHANGED;
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_string(const char *name, s8 **field, const char *buff, const void *arg)
|
||||
{
|
||||
|
||||
@@ -60,6 +60,8 @@ static inline enum xset_result xset_dummy(const char *name, void *field, const c
|
||||
enum xset_result xset_ip(const char *name, struct ip_addr *field, const char *buff, const void *arg);
|
||||
enum xset_result xset_bool(const char *name, bool *field, const char *buff, const void *arg);
|
||||
enum xset_result xset_u8(const char *name, u8 *field, const char *buff, const void *arg);
|
||||
enum xset_result xset_u32(const char *name, u32 *field, const char *buff, const void *arg);
|
||||
enum xset_result xset_u16(const char *name, u16 *field, const char *buff, const void *arg);
|
||||
|
||||
/**
|
||||
* @param arg - max string length
|
||||
@@ -73,17 +75,17 @@ enum xset_result xset_ustring(const char *name, u8 **field, const char *buff, co
|
||||
* If 'name' is found in connData->getArgs, xset() is called.
|
||||
* If the result is SET, xnotify() is fired. Else, 'name,' is appended to the redir_url buffer.
|
||||
*/
|
||||
#define XSET_CGI_FUNC(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \
|
||||
#define XSET_CGI_FUNC(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify, allow) \
|
||||
if ((allow) && GET_ARG(#name)) { \
|
||||
enum xset_result res = xset(#name, cast &XSTRUCT->name, buff, (const void*) (xsarg)); \
|
||||
if (res == XSET_SET) { xnotify(); } \
|
||||
if (res == XSET_SET) { xnotify; } \
|
||||
else if (res == XSET_FAIL) { redir_url += sprintf(redir_url, #name","); } \
|
||||
}
|
||||
|
||||
#define XGET_CGI_FUNC(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \
|
||||
#define XGET_CGI_FUNC(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify, allow) \
|
||||
if ((allow) && streq(token, #name)) xget(buff, deref XSTRUCT->name);
|
||||
|
||||
#define XSTRUCT_FIELD(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \
|
||||
#define XSTRUCT_FIELD(type, name, suffix, deref, xget, cast, xset, xsarg, xnotify, allow) \
|
||||
type name suffix;
|
||||
|
||||
#define XDUMP_FIELD(type, name, suffix, deref, xget, allow, cast, xset, xsarg, xnotify) \
|
||||
|
||||
+260
-55
@@ -8,6 +8,7 @@
|
||||
#include "character_sets.h"
|
||||
#include "utf8.h"
|
||||
#include "cgi_sockets.h"
|
||||
#include "cgi_logging.h"
|
||||
|
||||
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
||||
TerminalConfigBundle termconf_live;
|
||||
@@ -106,8 +107,19 @@ bool cursor_saved = false;
|
||||
static struct {
|
||||
bool alternate_active;
|
||||
char title[TERM_TITLE_LEN];
|
||||
char btn[TERM_BTN_COUNT][TERM_BTN_LEN];
|
||||
char btn_msg[TERM_BTN_COUNT][TERM_BTN_MSG_LEN];
|
||||
|
||||
char btn1[TERM_BTN_LEN];
|
||||
char btn2[TERM_BTN_LEN];
|
||||
char btn3[TERM_BTN_LEN];
|
||||
char btn4[TERM_BTN_LEN];
|
||||
char btn5[TERM_BTN_LEN];
|
||||
|
||||
char btn1_msg[TERM_BTN_MSG_LEN];
|
||||
char btn2_msg[TERM_BTN_MSG_LEN];
|
||||
char btn3_msg[TERM_BTN_MSG_LEN];
|
||||
char btn4_msg[TERM_BTN_MSG_LEN];
|
||||
char btn5_msg[TERM_BTN_MSG_LEN];
|
||||
|
||||
u32 width;
|
||||
u32 height;
|
||||
int vm0;
|
||||
@@ -143,46 +155,194 @@ static struct {
|
||||
int x_min, y_min, x_max, y_max;
|
||||
} scr_dirty;
|
||||
|
||||
#define reset_screen_dirty() do { \
|
||||
scr_dirty.x_min = W; \
|
||||
scr_dirty.x_max = -1; \
|
||||
scr_dirty.y_min = H; \
|
||||
scr_dirty.y_max = -1; \
|
||||
} while(0)
|
||||
static void ICACHE_FLASH_ATTR reset_screen_dirty(void)
|
||||
{
|
||||
scr_dirty.x_min = W;
|
||||
scr_dirty.x_max = -1;
|
||||
scr_dirty.y_min = H;
|
||||
scr_dirty.y_max = -1;
|
||||
}
|
||||
|
||||
#define expand_dirty(y0, y1, x0, x1) do { \
|
||||
seri_dbg("Expand: X: (%d..%d) -> %d..%d, Y: (%d..%d) -> %d..%d", scr_dirty.x_min, scr_dirty.x_max, x0, x1, scr_dirty.y_min, scr_dirty.y_max, y0, y1); \
|
||||
if ((int)(y0) < scr_dirty.y_min) scr_dirty.y_min = (y0); \
|
||||
if ((int)(x0) < scr_dirty.x_min) scr_dirty.x_min = (x0); \
|
||||
if ((int)(y1) > scr_dirty.y_max) scr_dirty.y_max = (y1); \
|
||||
if ((int)(x1) > scr_dirty.x_max) scr_dirty.x_max = (x1); \
|
||||
} while(0)
|
||||
static void ICACHE_FLASH_ATTR expand_dirty(int y0, int y1, int x0, int x1)
|
||||
{
|
||||
seri_dbg("Expand: X: (%d..%d) -> %d..%d, Y: (%d..%d) -> %d..%d",
|
||||
scr_dirty.x_min, scr_dirty.x_max, x0, x1, scr_dirty.y_min, scr_dirty.y_max, y0, y1);
|
||||
|
||||
#define NOTIFY_LOCK() do { \
|
||||
notifyLock++; \
|
||||
} while(0)
|
||||
|
||||
#define NOTIFY_DONE(updateTopics) do { \
|
||||
lockTopics |= (updateTopics); \
|
||||
if (notifyLock > 0) notifyLock--; \
|
||||
if (notifyLock == 0) { \
|
||||
screen_notifyChange(lockTopics); \
|
||||
lockTopics = 0;\
|
||||
} \
|
||||
} while(0)
|
||||
if ((y0) < scr_dirty.y_min) scr_dirty.y_min = (y0);
|
||||
if ((x0) < scr_dirty.x_min) scr_dirty.x_min = (x0);
|
||||
if ((y1) > scr_dirty.y_max) scr_dirty.y_max = (y1);
|
||||
if ((x1) > scr_dirty.x_max) scr_dirty.x_max = (x1);
|
||||
}
|
||||
|
||||
#define NOTIFY_LOCK() { notifyLock++; }
|
||||
|
||||
static void ICACHE_FLASH_ATTR NOTIFY_DONE(u32 updateTopics)
|
||||
{
|
||||
lockTopics |= (updateTopics);
|
||||
if (notifyLock > 0) notifyLock--;
|
||||
if (notifyLock == 0) {
|
||||
screen_notifyChange(lockTopics);
|
||||
lockTopics = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear the hanging attribute if the cursor is no longer >= W */
|
||||
#define clear_invalid_hanging() do { \
|
||||
if (cursor.hanging && cursor.x != W-1) { \
|
||||
cursor.hanging = false; \
|
||||
screen_notifyChange(TOPIC_CHANGE_CURSOR); \
|
||||
} \
|
||||
} while(false)
|
||||
static void ICACHE_FLASH_ATTR clear_invalid_hanging(void)
|
||||
{
|
||||
if (cursor.hanging && cursor.x != W-1) {
|
||||
cursor.hanging = false;
|
||||
screen_notifyChange(TOPIC_CHANGE_CURSOR);
|
||||
}
|
||||
}
|
||||
|
||||
#define cursor_inside_region() (cursor.y >= TOP && cursor.y <= BTM)
|
||||
|
||||
//region --- Settings ---
|
||||
|
||||
/** Export color for config */
|
||||
void ICACHE_FLASH_ATTR
|
||||
xget_term_color(char *buff, u32 value)
|
||||
{
|
||||
if (value < 256) {
|
||||
sprintf(buff, "%d", value);
|
||||
} else {
|
||||
sprintf(buff, "#%06X", value - 256);
|
||||
}
|
||||
}
|
||||
|
||||
/** Export button message as stirng for config */
|
||||
void ICACHE_FLASH_ATTR
|
||||
xget_term_bm(char *buff, char *value)
|
||||
{
|
||||
u8 c;
|
||||
char *bp = buff;
|
||||
char *cp = value;
|
||||
int n = 0;
|
||||
while((c = (u8) *cp++) != 0) {
|
||||
if(n>0) {
|
||||
*bp = ',';
|
||||
bp++;
|
||||
}
|
||||
bp += sprintf(bp, "%d", c);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_term_bm(const char *name, s8 **field, const char *buff, const void *arg)
|
||||
{
|
||||
cgi_dbg("Setting %s = %s", name, buff);
|
||||
|
||||
// parse: comma,space or semicolon separated decimal values of ASCII codes
|
||||
char c;
|
||||
const char *cp = buff;
|
||||
int char_i = 0;
|
||||
int acu = 0;
|
||||
bool lastsp = 1;
|
||||
char buff_bm[TERM_BTN_MSG_LEN];
|
||||
while ((c = *cp++) != 0) {
|
||||
if (c == ' ' || c == ',' || c == ';') {
|
||||
if(lastsp) continue;
|
||||
|
||||
if (acu==0 || acu>255) {
|
||||
cgi_warn("Bad value! %d", acu);
|
||||
return XSET_FAIL;
|
||||
}
|
||||
|
||||
if (char_i >= TERM_BTN_MSG_LEN-1) {
|
||||
cgi_warn("Too long! %d", acu);
|
||||
return XSET_FAIL;
|
||||
}
|
||||
|
||||
cgi_dbg("acu %d", acu);
|
||||
buff_bm[char_i++] = (char)acu;
|
||||
|
||||
// prepare for next char
|
||||
acu = 0;
|
||||
lastsp = 1;
|
||||
} else if (c>='0'&&c<='9') {
|
||||
lastsp = 0;
|
||||
acu *= 10;
|
||||
acu += c - '0';
|
||||
} else {
|
||||
cgi_warn("Bad syntax!");
|
||||
return XSET_FAIL;
|
||||
}
|
||||
}
|
||||
if (lastsp && char_i == 0) {
|
||||
cgi_warn("Required!");
|
||||
return XSET_FAIL;
|
||||
}
|
||||
if (!lastsp) {
|
||||
buff_bm[char_i++] = (char)acu;
|
||||
}
|
||||
buff_bm[char_i] = 0;
|
||||
cgi_dbg("%s, chari = %d", buff_bm, char_i);
|
||||
|
||||
if (!streq(*field, buff_bm)) {
|
||||
strncpy((char*)*field, buff_bm, TERM_BTN_MSG_LEN);
|
||||
return XSET_SET;
|
||||
}
|
||||
return XSET_UNCHANGED;
|
||||
}
|
||||
|
||||
/** convert hex number to int */
|
||||
static ICACHE_FLASH_ATTR u32
|
||||
decodehex(const char *buf) {
|
||||
u32 n = 0;
|
||||
char c;
|
||||
while ((c = *buf++) != 0) {
|
||||
if (c >= '0' && c <= '9') c -= '0';
|
||||
else if (c >= 'a' && c <= 'f') c -= 'a'-10;
|
||||
else if (c >= 'A' && c <= 'F') c -= 'A'-10;
|
||||
else c = 0;
|
||||
n *= 16;
|
||||
n += c;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_term_color(const char *name, u32 *field, const char *buff, const void *arg)
|
||||
{
|
||||
cgi_dbg("Setting %s = %s", name, buff);
|
||||
u32 n;
|
||||
|
||||
if (buff[0] == '#') {
|
||||
// decode hex
|
||||
n = decodehex(buff+1);
|
||||
n += 256;
|
||||
} else {
|
||||
n = atoi(buff);
|
||||
}
|
||||
|
||||
if (*field != n) {
|
||||
*field = n;
|
||||
return XSET_SET;
|
||||
}
|
||||
|
||||
return XSET_UNCHANGED;
|
||||
}
|
||||
|
||||
enum xset_result ICACHE_FLASH_ATTR
|
||||
xset_term_cursorshape(const char *name, u32 *field, const char *buff, const void *arg)
|
||||
{
|
||||
cgi_dbg("Setting %s = %s", name, buff);
|
||||
u32 n = atoi(buff);
|
||||
|
||||
if (n >= 0 && n <= 6 && n != 1) {
|
||||
if (*field != n) {
|
||||
*field = n;
|
||||
return XSET_SET;
|
||||
}
|
||||
return XSET_UNCHANGED;
|
||||
} else {
|
||||
cgi_warn("Bad cursor_shape num: %s", buff);
|
||||
return XSET_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore hard defaults
|
||||
*/
|
||||
@@ -194,10 +354,19 @@ terminal_restore_defaults(void)
|
||||
termconf->default_bg = 0;
|
||||
termconf->default_fg = 7;
|
||||
sprintf(termconf->title, SCR_DEF_TITLE);
|
||||
for(int i=1; i <= TERM_BTN_COUNT; i++) {
|
||||
sprintf(termconf->btn[i-1], "%d", i);
|
||||
sprintf(termconf->btn_msg[i-1], "%c", i);
|
||||
}
|
||||
|
||||
strcpy(termconf->btn1, "1");
|
||||
strcpy(termconf->btn2, "2");
|
||||
strcpy(termconf->btn3, "3");
|
||||
strcpy(termconf->btn4, "4");
|
||||
strcpy(termconf->btn5, "5");
|
||||
|
||||
strcpy(termconf->bm1, "\x01");
|
||||
strcpy(termconf->bm2, "\x02");
|
||||
strcpy(termconf->bm3, "\x03");
|
||||
strcpy(termconf->bm4, "\x04");
|
||||
strcpy(termconf->bm5, "\x05");
|
||||
|
||||
termconf->theme = 0;
|
||||
termconf->parser_tout_ms = SCR_DEF_PARSER_TOUT_MS;
|
||||
termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
||||
@@ -232,6 +401,13 @@ terminal_apply_settings_noclear(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
// char buff[64];
|
||||
//#define XSTRUCT termconf
|
||||
//#define X XDUMP_FIELD
|
||||
// XTABLE_TERMCONF
|
||||
//#undef X
|
||||
// return;
|
||||
|
||||
// Migrate
|
||||
if (termconf->config_version < 1) {
|
||||
persist_dbg("termconf: Updating to version %d", 1);
|
||||
@@ -393,10 +569,11 @@ screen_reset_do(bool size, bool labels)
|
||||
strcpy(termconf_live.title, termconf->title);
|
||||
strcpy(termconf_live.backdrop, termconf->backdrop);
|
||||
|
||||
for (int i = 1; i <= TERM_BTN_COUNT; i++) {
|
||||
strcpy(termconf_live.btn[i], termconf->btn[i]);
|
||||
strcpy(termconf_live.btn_msg[i], termconf->btn_msg[i]);
|
||||
}
|
||||
strcpy(termconf_live.btn1, termconf->btn1);
|
||||
strcpy(termconf_live.btn2, termconf->btn2);
|
||||
strcpy(termconf_live.btn3, termconf->btn3);
|
||||
strcpy(termconf_live.btn4, termconf->btn4);
|
||||
strcpy(termconf_live.btn5, termconf->btn5);
|
||||
|
||||
termconf_live.show_buttons = termconf->show_buttons;
|
||||
termconf_live.show_config_links = termconf->show_config_links;
|
||||
@@ -452,8 +629,11 @@ screen_swap_state(bool alternate)
|
||||
ansi_dbg("Swap to alternate");
|
||||
// store old state
|
||||
memcpy(state_backup.title, termconf_live.title, TERM_TITLE_LEN);
|
||||
memcpy(state_backup.btn, termconf_live.btn, sizeof(termconf_live.btn));
|
||||
memcpy(state_backup.btn_msg, termconf_live.btn_msg, sizeof(termconf_live.btn_msg));
|
||||
|
||||
// copy multiple fields at once
|
||||
memcpy(state_backup.btn1, termconf_live.btn1, sizeof(termconf_live.btn1)*TERM_BTN_COUNT);
|
||||
memcpy(state_backup.btn1_msg, termconf_live.bm1, sizeof(termconf_live.bm1)*TERM_BTN_COUNT);
|
||||
|
||||
memcpy(state_backup.tab_stops, scr.tab_stops, sizeof(scr.tab_stops));
|
||||
state_backup.vm0 = scr.vm0;
|
||||
state_backup.vm1 = scr.vm1;
|
||||
@@ -465,8 +645,11 @@ screen_swap_state(bool alternate)
|
||||
else {
|
||||
ansi_dbg("Unswap from alternate");
|
||||
memcpy(termconf_live.title, state_backup.title, TERM_TITLE_LEN);
|
||||
memcpy(termconf_live.btn, state_backup.btn, sizeof(termconf_live.btn));
|
||||
memcpy(termconf_live.btn_msg, state_backup.btn_msg, sizeof(termconf_live.btn_msg));
|
||||
|
||||
// copy multiple fields at once
|
||||
memcpy(termconf_live.btn1, state_backup.btn1, sizeof(termconf_live.btn1)*TERM_BTN_COUNT);
|
||||
memcpy(termconf_live.bm1, state_backup.btn1_msg, sizeof(termconf_live.bm1)*TERM_BTN_COUNT);
|
||||
|
||||
memcpy(scr.tab_stops, state_backup.tab_stops, sizeof(scr.tab_stops));
|
||||
scr.vm0 = state_backup.vm0;
|
||||
scr.vm1 = state_backup.vm1;
|
||||
@@ -989,8 +1172,8 @@ screen_resize(int rows, int cols)
|
||||
if (W == cols && H == rows) return; // Do nothing
|
||||
|
||||
NOTIFY_LOCK();
|
||||
W = cols;
|
||||
H = rows;
|
||||
W = (u32) cols;
|
||||
H = (u32) rows;
|
||||
screen_reset_on_resize();
|
||||
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS|TOPIC_CHANGE_CONTENT_ALL|TOPIC_CHANGE_CURSOR);
|
||||
}
|
||||
@@ -1012,7 +1195,28 @@ void ICACHE_FLASH_ATTR
|
||||
screen_set_button_text(int num, const char *text)
|
||||
{
|
||||
NOTIFY_LOCK();
|
||||
strncpy(termconf_live.btn[num-1], text, TERM_BTN_LEN);
|
||||
if (num == 1) strncpy(termconf_live.btn1, text, TERM_BTN_LEN);
|
||||
else if (num == 2) strncpy(termconf_live.btn2, text, TERM_BTN_LEN);
|
||||
else if (num == 3) strncpy(termconf_live.btn3, text, TERM_BTN_LEN);
|
||||
else if (num == 4) strncpy(termconf_live.btn4, text, TERM_BTN_LEN);
|
||||
else if (num == 5) strncpy(termconf_live.btn5, text, TERM_BTN_LEN);
|
||||
NOTIFY_DONE(TOPIC_CHANGE_BUTTONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to set terminal button label
|
||||
* @param num - button number 1-5
|
||||
* @param str - button text
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
screen_set_button_message(int num, const char *msg)
|
||||
{
|
||||
NOTIFY_LOCK();
|
||||
if (num == 1) strncpy(termconf_live.bm1, msg, TERM_BTN_MSG_LEN);
|
||||
else if (num == 2) strncpy(termconf_live.bm2, msg, TERM_BTN_MSG_LEN);
|
||||
else if (num == 3) strncpy(termconf_live.bm3, msg, TERM_BTN_MSG_LEN);
|
||||
else if (num == 4) strncpy(termconf_live.bm4, msg, TERM_BTN_MSG_LEN);
|
||||
else if (num == 5) strncpy(termconf_live.bm5, msg, TERM_BTN_MSG_LEN);
|
||||
NOTIFY_DONE(TOPIC_CHANGE_BUTTONS);
|
||||
}
|
||||
|
||||
@@ -1121,7 +1325,7 @@ void ICACHE_FLASH_ATTR
|
||||
screen_cursor_shape(enum CursorShape shape)
|
||||
{
|
||||
NOTIFY_LOCK();
|
||||
if (shape == CURSOR_DEFAULT) shape = termconf->cursor_shape;
|
||||
if (shape == CURSOR_DEFAULT) shape = (enum CursorShape) termconf->cursor_shape;
|
||||
termconf_live.cursor_shape = shape;
|
||||
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||
}
|
||||
@@ -1356,7 +1560,7 @@ screen_back_index(int count)
|
||||
cursor.x = new_x;
|
||||
} else {
|
||||
cursor.x = 0;
|
||||
screen_insert_characters(-new_x);
|
||||
screen_insert_characters((unsigned int) -new_x);
|
||||
topics |= TOPIC_CHANGE_CONTENT_PART;
|
||||
}
|
||||
NOTIFY_DONE(topics);
|
||||
@@ -1548,7 +1752,7 @@ do_save_private_opt(int n, bool save)
|
||||
{
|
||||
ScreenNotifyTopics topics = TOPIC_INTERNAL;
|
||||
if (!save) NOTIFY_LOCK();
|
||||
#define SAVE_RESTORE(sf, of) do { if (save) sf=(of); else of=(sf); } while(0)
|
||||
#define SAVE_RESTORE(sf, of) do { if (save) (sf)=(of); else (of)=(sf); } while(0)
|
||||
switch (n) {
|
||||
case 1:
|
||||
SAVE_RESTORE(opt_backup.cursors_alt_mode, scr.cursors_alt_mode);
|
||||
@@ -2044,7 +2248,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics,
|
||||
BEGIN_TOPIC(TOPIC_CHANGE_TITLE, TERM_TITLE_LEN+4+1)
|
||||
bufput_c(TOPICMARK_TITLE);
|
||||
|
||||
int len = (int) strlen(termconf_live.title);
|
||||
size_t len = strlen(termconf_live.title);
|
||||
if (len > 0) {
|
||||
memcpy(bb, termconf_live.title, len);
|
||||
bb += len;
|
||||
@@ -2059,20 +2263,21 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics,
|
||||
bufput_utf8(TERM_BTN_COUNT);
|
||||
|
||||
for (int i = 0; i < TERM_BTN_COUNT; i++) {
|
||||
int len = (int) strlen(termconf_live.btn[i]);
|
||||
size_t len = strlen(TERM_BTN_N(&termconf_live, i));
|
||||
if (len > 0) {
|
||||
memcpy(bb, termconf_live.btn[i], len);
|
||||
memcpy(bb, TERM_BTN_N(&termconf_live, i), len);
|
||||
bb += len;
|
||||
remain -= len;
|
||||
}
|
||||
bufput_c('\x01');
|
||||
}
|
||||
|
||||
END_TOPIC
|
||||
|
||||
BEGIN_TOPIC(TOPIC_CHANGE_BACKDROP, TERM_BACKDROP_LEN+1+1)
|
||||
bufput_c(TOPICMARK_BACKDROP);
|
||||
|
||||
int len = (int) strlen(termconf_live.backdrop);
|
||||
size_t len = strlen(termconf_live.backdrop);
|
||||
if (len > 0) {
|
||||
memcpy(bb, termconf_live.backdrop, len);
|
||||
bb += len;
|
||||
|
||||
+54
-23
@@ -5,6 +5,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp8266.h>
|
||||
#include <httpd.h>
|
||||
#include "config_xmacros.h"
|
||||
|
||||
/**
|
||||
* This module handles the virtual screen and operations on it.
|
||||
@@ -78,30 +79,59 @@ enum CursorShape {
|
||||
#define TERMCONF_SIZE 400
|
||||
#define TERMCONF_VERSION 4
|
||||
|
||||
//....Type................Name..Suffix...............Deref..XGET.........Cast..XSET.........................NOTIFY................Allow
|
||||
// Deref is used to pass the field to xget. Cast is used to convert the &'d field to what xset wants (needed for static arrays)
|
||||
#define XTABLE_TERMCONF \
|
||||
X(u32, width, /**/, /**/, xget_dec, /**/, xset_u32, NULL, /**/, 1) \
|
||||
X(u32, height, /**/, /**/, xget_dec, /**/, xset_u32, NULL, /**/, 1) \
|
||||
X(u32, default_bg, /**/, /**/, xget_term_color, /**/, xset_term_color, NULL, /**/, 1) \
|
||||
X(u32, default_fg, /**/, /**/, xget_term_color, /**/, xset_term_color, NULL, /**/, 1) \
|
||||
X(char, title, [TERM_TITLE_LEN], /**/, xget_string, (s8**), xset_string, TERM_TITLE_LEN, /**/, 1) \
|
||||
X(char, btn1, [TERM_BTN_LEN], /**/, xget_string, (s8**), xset_string, TERM_BTN_LEN, /**/, 1) \
|
||||
X(char, btn2, [TERM_BTN_LEN], /**/, xget_string, (s8**), xset_string, TERM_BTN_LEN, /**/, 1) \
|
||||
X(char, btn3, [TERM_BTN_LEN], /**/, xget_string, (s8**), xset_string, TERM_BTN_LEN, /**/, 1) \
|
||||
X(char, btn4, [TERM_BTN_LEN], /**/, xget_string, (s8**), xset_string, TERM_BTN_LEN, /**/, 1) \
|
||||
X(char, btn5, [TERM_BTN_LEN], /**/, xget_string, (s8**), xset_string, TERM_BTN_LEN, /**/, 1) \
|
||||
X(u8, theme, /**/, /**/, xget_dec, /**/, xset_u8, NULL, /**/, 1) \
|
||||
X(u32, parser_tout_ms, /**/, /**/, xget_dec, /**/, xset_u32, NULL, /**/, 1) \
|
||||
X(u32, display_tout_ms, /**/, /**/, xget_dec, /**/, xset_u32, NULL, /**/, 1) \
|
||||
X(bool, fn_alt_mode, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(u8, config_version, /**/, /**/, xget_dec, /**/, xset_u8, NULL, /**/, 1) \
|
||||
X(u32, display_cooldown_ms, /**/, /**/, xget_dec, /**/, xset_u32, NULL, /**/, 1) \
|
||||
X(bool, loopback, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, show_buttons, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, show_config_links, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(char, bm1, [TERM_BTN_MSG_LEN], /**/, xget_term_bm, (s8**), xset_term_bm, NULL, /**/, 1) \
|
||||
X(char, bm2, [TERM_BTN_MSG_LEN], /**/, xget_term_bm, (s8**), xset_term_bm, NULL, /**/, 1) \
|
||||
X(char, bm3, [TERM_BTN_MSG_LEN], /**/, xget_term_bm, (s8**), xset_term_bm, NULL, /**/, 1) \
|
||||
X(char, bm4, [TERM_BTN_MSG_LEN], /**/, xget_term_bm, (s8**), xset_term_bm, NULL, /**/, 1) \
|
||||
X(char, bm5, [TERM_BTN_MSG_LEN], /**/, xget_term_bm, (s8**), xset_term_bm, NULL, /**/, 1) \
|
||||
X(u32, cursor_shape, /**/, /**/, xget_dec, /**/, xset_term_cursorshape, NULL, /**/, 1) \
|
||||
X(bool, crlf_mode, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, want_all_fn, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, debugbar, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, allow_decopt_12, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(bool, ascii_debug, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
X(char, backdrop, [TERM_BACKDROP_LEN], /**/, xget_string, (s8**), xset_string, TERM_BACKDROP_LEN, /**/, 1)
|
||||
|
||||
#define TERM_BM_N(tc, n) ((tc)->bm1+(TERM_BTN_MSG_LEN*n))
|
||||
#define TERM_BTN_N(tc, n) ((tc)->btn1+(TERM_BTN_LEN*n))
|
||||
|
||||
/** Export color for config */
|
||||
void xget_term_color(char *buff, u32 value);
|
||||
/** Export button message as stirng for config */
|
||||
void xget_term_bm(char *buff, char *value);
|
||||
/** Set button message */
|
||||
enum xset_result xset_term_bm(const char *name, s8 **field, const char *buff, const void *arg);
|
||||
/** Set color */
|
||||
enum xset_result xset_term_color(const char *name, u32 *field, const char *buff, const void *arg);
|
||||
/** Set cursor shape */
|
||||
enum xset_result xset_term_cursorshape(const char *name, u32 *field, const char *buff, const void *arg);
|
||||
|
||||
typedef struct {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 default_bg; // 00-FFh - ANSI colors, (00:00:00-FF:FF:FF)+256 - True Color
|
||||
u32 default_fg;
|
||||
char title[TERM_TITLE_LEN];
|
||||
char btn[TERM_BTN_COUNT][TERM_BTN_LEN];
|
||||
u8 theme;
|
||||
u32 parser_tout_ms;
|
||||
u32 display_tout_ms;
|
||||
bool fn_alt_mode; // xterm compatibility mode (alternate codes for some FN keys)
|
||||
u8 config_version;
|
||||
u32 display_cooldown_ms;
|
||||
bool loopback;
|
||||
bool show_buttons;
|
||||
bool show_config_links;
|
||||
char btn_msg[TERM_BTN_COUNT][TERM_BTN_MSG_LEN];
|
||||
enum CursorShape cursor_shape;
|
||||
bool crlf_mode;
|
||||
bool want_all_fn;
|
||||
bool debugbar;
|
||||
bool allow_decopt_12;
|
||||
bool ascii_debug;
|
||||
char backdrop[TERM_BACKDROP_LEN];
|
||||
#define X XSTRUCT_FIELD
|
||||
XTABLE_TERMCONF
|
||||
#undef X
|
||||
} TerminalConfigBundle;
|
||||
|
||||
// Live config
|
||||
@@ -150,6 +180,7 @@ void screen_resize(int rows, int cols);
|
||||
void screen_set_title(const char *title);
|
||||
/** Set a button text */
|
||||
void screen_set_button_text(int num, const char *text);
|
||||
void screen_set_button_message(int num, const char *msg);
|
||||
/** Change backdrop */
|
||||
void screen_set_backdrop(const char *url);
|
||||
|
||||
|
||||
+9
-10
@@ -25,21 +25,20 @@ enum pwlock {
|
||||
PWLOCK_MAX = 5,
|
||||
};
|
||||
|
||||
|
||||
//....Type................Name..Suffix...............Deref..XGET........Allow..Cast..XSET.........................NOTIFY
|
||||
//....Type................Name..Suffix...............Deref..XGET..........Cast..XSET.........................NOTIFY....Allow
|
||||
// Deref is used to pass the field to xget. Cast is used to convert the &'d field to what xset wants (needed for static arrays)
|
||||
#define XTABLE_SYSCONF \
|
||||
X(u32, uart_baudrate, /**/, /**/, xget_dec, 1, /**/, xset_sys_baudrate, NULL, xnoop) \
|
||||
X(u8, uart_parity, /**/, /**/, xget_dec, 1, /**/, xset_sys_parity, NULL, xnoop) \
|
||||
X(u8, uart_stopbits, /**/, /**/, xget_dec, 1, /**/, xset_sys_stopbits, NULL, xnoop) \
|
||||
X(u32, uart_baudrate, /**/, /**/, xget_dec, /**/, xset_sys_baudrate, NULL, uart_changed=true, 1) \
|
||||
X(u8, uart_parity, /**/, /**/, xget_dec, /**/, xset_sys_parity, NULL, uart_changed=true, 1) \
|
||||
X(u8, uart_stopbits, /**/, /**/, xget_dec, /**/, xset_sys_stopbits, NULL, uart_changed=true, 1) \
|
||||
\
|
||||
X(u8, config_version, /**/, /**/, xget_dec, 0, /**/, xset_u8, NULL, xnoop) \
|
||||
X(u8, config_version, /**/, /**/, xget_dec, /**/, xset_u8, NULL, /**/, 1) \
|
||||
\
|
||||
X(u8, pwlock, /**/, /**/, xget_dec, admin|tpl, /**/, xset_sys_pwlock, NULL, xnoop) \
|
||||
X(u8, access_pw, [64], /**/, xget_ustring, admin, (u8**), xset_sys_accesspw, NULL, xnoop) \
|
||||
X(u8, access_name, [32], /**/, xget_ustring, admin|tpl, (u8**), xset_ustring, NULL, xnoop) \
|
||||
X(u8, pwlock, /**/, /**/, xget_dec, /**/, xset_sys_pwlock, NULL, /**/, admin|tpl) \
|
||||
X(u8, access_pw, [64], /**/, xget_ustring, (u8**), xset_sys_accesspw, NULL, /**/, admin) \
|
||||
X(u8, access_name, [32], /**/, xget_ustring, (u8**), xset_ustring, NULL, /**/, admin|tpl) \
|
||||
\
|
||||
X(bool, overclock, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, xnoop) \
|
||||
X(bool, overclock, /**/, /**/, xget_bool, /**/, xset_bool, NULL, /**/, 1) \
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
+21
-21
@@ -23,37 +23,37 @@
|
||||
#define wifimgr_notify_ap() { wifi_change_flags.ap = true; }
|
||||
#define wifimgr_notify_sta() { wifi_change_flags.ap = true; }
|
||||
|
||||
//....Type................Name..Suffix...............Deref..XGET.......Allow..Cast..XSET.........................NOTIFY
|
||||
//....Type................Name..Suffix...............Deref..XGET.........Cast..XSET.........................NOTIFY................Allow
|
||||
// Deref is used to pass the field to xget. Cast is used to convert the &'d field to what xset wants (needed for static arrays)
|
||||
#define XTABLE_WIFI \
|
||||
X(u8, opmode, /**/, /**/, xget_dec, 1, /**/, xset_wifi_opmode, NULL, xnoop) \
|
||||
X(u8, opmode, /**/, /**/, xget_dec, /**/, xset_wifi_opmode, NULL, /**/, 1) \
|
||||
\
|
||||
X(u8, tpw, /**/, /**/, xget_dec, 1, /**/, xset_wifi_tpw, NULL, wifimgr_notify_ap) \
|
||||
X(u8, ap_channel, /**/, /**/, xget_dec, 1, /**/, xset_wifi_ap_channel, NULL, wifimgr_notify_ap) \
|
||||
X(u8, ap_ssid, [SSID_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_ssid, 1, wifimgr_notify_ap) \
|
||||
X(u8, ap_password, [PASSWORD_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_ap) \
|
||||
X(bool, ap_hidden, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, wifimgr_notify_ap) \
|
||||
X(u8, tpw, /**/, /**/, xget_dec, /**/, xset_wifi_tpw, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(u8, ap_channel, /**/, /**/, xget_dec, /**/, xset_wifi_ap_channel, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(u8, ap_ssid, [SSID_LEN], /**/, xget_ustring, (u8**), xset_wifi_ssid, 1, wifimgr_notify_ap(), 1) \
|
||||
X(u8, ap_password, [PASSWORD_LEN], /**/, xget_ustring, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(bool, ap_hidden, /**/, /**/, xget_bool, /**/, xset_bool, NULL, wifimgr_notify_ap(), 1) \
|
||||
\
|
||||
X(u16, ap_dhcp_time, /**/, /**/, xget_dec, 1, /**/, xset_wifi_lease_time, NULL, wifimgr_notify_ap) \
|
||||
X(u32, unused1, /**/, /**/, xget_dummy, 0, /**/, xset_dummy, NULL, xnoop) \
|
||||
X(struct ip_addr, ap_dhcp_start, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \
|
||||
X(struct ip_addr, ap_dhcp_end, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \
|
||||
X(u16, ap_dhcp_time, /**/, /**/, xget_dec, /**/, xset_wifi_lease_time, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(u32, unused1, /**/, /**/, xget_dummy, /**/, xset_dummy, NULL, /**/, 0) \
|
||||
X(struct ip_addr, ap_dhcp_start, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(struct ip_addr, ap_dhcp_end, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap(), 1) \
|
||||
\
|
||||
X(struct ip_addr, ap_addr_ip, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \
|
||||
X(struct ip_addr, ap_addr_mask, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_ap) \
|
||||
X(struct ip_addr, ap_addr_ip, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap(), 1) \
|
||||
X(struct ip_addr, ap_addr_mask, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_ap(), 1) \
|
||||
\
|
||||
\
|
||||
X(u32, unused2, /**/, /**/, xget_dummy, 0, /**/, xset_dummy, NULL, xnoop) \
|
||||
X(u8, sta_ssid, [SSID_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_ssid, 0, wifimgr_notify_sta) \
|
||||
X(u8, sta_password, [PASSWORD_LEN], /**/, xget_ustring, 1, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_sta) \
|
||||
X(bool, sta_dhcp_enable, /**/, /**/, xget_bool, 1, /**/, xset_bool, NULL, wifimgr_notify_sta) \
|
||||
X(u32, unused2, /**/, /**/, xget_dummy, /**/, xset_dummy, NULL, /**/, 0) \
|
||||
X(u8, sta_ssid, [SSID_LEN], /**/, xget_ustring, (u8**), xset_wifi_ssid, 0, wifimgr_notify_sta(), 1) \
|
||||
X(u8, sta_password, [PASSWORD_LEN], /**/, xget_ustring, (u8**), xset_wifi_pwd, NULL, wifimgr_notify_sta(), 1) \
|
||||
X(bool, sta_dhcp_enable, /**/, /**/, xget_bool, /**/, xset_bool, NULL, wifimgr_notify_sta(), 1) \
|
||||
\
|
||||
X(struct ip_addr, sta_addr_ip, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \
|
||||
X(struct ip_addr, sta_addr_mask, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \
|
||||
X(struct ip_addr, sta_addr_gw, /**/, &, xget_ip, 1, /**/, xset_ip, NULL, wifimgr_notify_sta) \
|
||||
X(struct ip_addr, sta_addr_ip, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta(), 1) \
|
||||
X(struct ip_addr, sta_addr_mask, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta(), 1) \
|
||||
X(struct ip_addr, sta_addr_gw, /**/, &, xget_ip, /**/, xset_ip, NULL, wifimgr_notify_sta(), 1) \
|
||||
\
|
||||
\
|
||||
X(u8, config_version, /**/, /**/, xget_dec, 0, /**/, xset_u8, NULL, xnoop)
|
||||
X(u8, config_version, /**/, /**/, xget_dec, /**/, xset_u8, NULL, /**/, 1)
|
||||
|
||||
// unused1 - replaces 'enabled' bit from old dhcps_lease struct
|
||||
// unused2 - gap after 'ap_gw' which isn't used and doesn't make sense
|
||||
|
||||
Reference in New Issue
Block a user