new message format
This commit is contained in:
+2
-2
@@ -757,11 +757,11 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
}
|
}
|
||||||
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
||||||
termconf_live.show_buttons = yn;
|
termconf_live.show_buttons = yn;
|
||||||
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
screen_notifyChange(TOPIC_CHANGE_SCREEN_OPTS); // this info is included in the screen preamble
|
||||||
}
|
}
|
||||||
else if (n == 801) { // ESPTerm: Toggle display of config links
|
else if (n == 801) { // ESPTerm: Toggle display of config links
|
||||||
termconf_live.show_config_links = yn;
|
termconf_live.show_config_links = yn;
|
||||||
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
screen_notifyChange(TOPIC_CHANGE_SCREEN_OPTS); // this info is included in the screen preamble
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ansi_noimpl("?OPTION %d", n);
|
ansi_noimpl("?OPTION %d", n);
|
||||||
|
|||||||
+1
-5
@@ -25,11 +25,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token
|
|||||||
|
|
||||||
char buff[150];
|
char buff[150];
|
||||||
|
|
||||||
if (streq(token, "labels_seq")) {
|
if (streq(token, "theme")) {
|
||||||
screenSerializeLabelsToBuffer(buff, 150);
|
|
||||||
tplSend(connData, buff, -1);
|
|
||||||
}
|
|
||||||
else if (streq(token, "theme")) {
|
|
||||||
sprintf(buff, "%d", termconf->theme);
|
sprintf(buff, "%d", termconf->theme);
|
||||||
tplSend(connData, buff, -1);
|
tplSend(connData, buff, -1);
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-65
@@ -16,6 +16,8 @@
|
|||||||
// Must be less than httpd sendbuf
|
// Must be less than httpd sendbuf
|
||||||
#define SOCK_BUF_LEN 2000
|
#define SOCK_BUF_LEN 2000
|
||||||
|
|
||||||
|
volatile ScreenNotifyTopics pendingBroadcastTopics = 0;
|
||||||
|
|
||||||
// flags for screen update timeouts
|
// flags for screen update timeouts
|
||||||
volatile bool notify_available = true;
|
volatile bool notify_available = true;
|
||||||
volatile bool notify_cooldown = false;
|
volatile bool notify_cooldown = false;
|
||||||
@@ -24,12 +26,11 @@ volatile bool notify_cooldown = false;
|
|||||||
* and we have to tell it we're ready again */
|
* and we have to tell it we're ready again */
|
||||||
volatile bool browser_wants_xon = false;
|
volatile bool browser_wants_xon = false;
|
||||||
|
|
||||||
static ETSTimer notifyContentTim;
|
static ETSTimer updateNotifyTim;
|
||||||
static ETSTimer notifyLabelsTim;
|
|
||||||
static ETSTimer notifyCooldownTim;
|
static ETSTimer notifyCooldownTim;
|
||||||
static ETSTimer heartbeatTim;
|
static ETSTimer heartbeatTim;
|
||||||
|
|
||||||
volatile int active_clients = 0;
|
volatile int term_active_clients = 0;
|
||||||
|
|
||||||
// we're trying to do a kind of mutex here, without the actual primitives
|
// we're trying to do a kind of mutex here, without the actual primitives
|
||||||
// this might glitch, very rarely.
|
// this might glitch, very rarely.
|
||||||
@@ -52,25 +53,21 @@ notifyCooldownTimCb(void *arg)
|
|||||||
* @param arg
|
* @param arg
|
||||||
*/
|
*/
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
notifyContentTimCb(void *arg)
|
updateNotify_do(Websock *ws, ScreenNotifyTopics topics)
|
||||||
{
|
{
|
||||||
Websock *ws = arg;
|
|
||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
int max_bl, total_bl;
|
|
||||||
char sock_buff[SOCK_BUF_LEN];
|
char sock_buff[SOCK_BUF_LEN];
|
||||||
|
|
||||||
cgiWebsockMeasureBacklog(URL_WS_UPDATE, &max_bl, &total_bl);
|
|
||||||
|
|
||||||
if (!notify_available || notify_cooldown || (max_bl > 2048)) { // do not send if we have anything significant backlogged
|
|
||||||
// postpone a little
|
|
||||||
TIMER_START(¬ifyContentTim, notifyContentTimCb, 4, 0);
|
|
||||||
inp_dbg("postpone notify content");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
notify_available = false;
|
notify_available = false;
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, &data);
|
if (! ws) {
|
||||||
|
// broadcast
|
||||||
|
topics = pendingBroadcastTopics;
|
||||||
|
pendingBroadcastTopics = 0;
|
||||||
|
}
|
||||||
|
httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, topics, &data);
|
||||||
|
|
||||||
int flg = 0;
|
int flg = 0;
|
||||||
if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE;
|
if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE;
|
||||||
if (i > 0) flg |= WEBSOCK_FLAG_CONT;
|
if (i > 0) flg |= WEBSOCK_FLAG_CONT;
|
||||||
@@ -86,56 +83,42 @@ notifyContentTimCb(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
screenSerializeToBuffer(NULL, SOCK_BUF_LEN, &data);
|
screenSerializeToBuffer(NULL, 0, 0, &data);
|
||||||
|
|
||||||
notify_cooldown = true;
|
|
||||||
notify_available = true;
|
notify_available = true;
|
||||||
|
|
||||||
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell browsers about the new text labels
|
* Tell browser we have new content
|
||||||
* @param arg
|
* @param arg
|
||||||
*/
|
*/
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
notifyLabelsTimCb(void *arg)
|
updateNotifyCb(void *arg)
|
||||||
{
|
{
|
||||||
Websock *ws = arg;
|
int max_bl, total_bl;
|
||||||
char sock_buff[SOCK_BUF_LEN];
|
cgiWebsockMeasureBacklog(URL_WS_UPDATE, &max_bl, &total_bl);
|
||||||
|
|
||||||
if (!notify_available || notify_cooldown) {
|
if (!notify_available || notify_cooldown || (max_bl > 2048)) { // do not send if we have anything significant backlogged
|
||||||
// postpone a little
|
// postpone a little
|
||||||
TIMER_START(¬ifyLabelsTim, notifyLabelsTimCb, 7, 0);
|
TIMER_START(&updateNotifyTim, updateNotifyCb, 4, 0);
|
||||||
inp_dbg("postpone notify labels");
|
inp_dbg("postpone notify content");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
notify_available = false;
|
|
||||||
|
|
||||||
screenSerializeLabelsToBuffer(sock_buff, SOCK_BUF_LEN);
|
updateNotify_do(arg, 0);
|
||||||
|
|
||||||
if (ws) {
|
|
||||||
cgiWebsocketSend(ws, sock_buff, (int) strlen(sock_buff), 0);
|
|
||||||
} else {
|
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), 0);
|
|
||||||
resetHeartbeatTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
notify_cooldown = true;
|
notify_cooldown = true;
|
||||||
notify_available = true;
|
|
||||||
|
|
||||||
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Beep */
|
/** Beep */
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
send_beep(void)
|
send_beep(void)
|
||||||
{
|
{
|
||||||
if (active_clients == 0) return;
|
if (term_active_clients == 0) return;
|
||||||
|
screen_notifyChange(TOPIC_BELL); // XXX has latency, maybe better to send directly
|
||||||
// here's some potential for a race error with the other broadcast functions :C
|
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, "B", 1, 0);
|
|
||||||
resetHeartbeatTimer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -143,10 +126,10 @@ send_beep(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
notify_growl(char *msg)
|
notify_growl(char *msg)
|
||||||
{
|
{
|
||||||
if (active_clients == 0) return;
|
if (term_active_clients == 0) return;
|
||||||
|
|
||||||
// TODO via timer...
|
// here's some potential for a race error with the other broadcast functions
|
||||||
// here's some potential for a race error with the other broadcast functions :C
|
// - we assume app won't send notifications in the middle of updating content
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), 0);
|
cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), 0);
|
||||||
resetHeartbeatTimer();
|
resetHeartbeatTimer();
|
||||||
}
|
}
|
||||||
@@ -157,24 +140,17 @@ notify_growl(char *msg)
|
|||||||
* This is a callback for the Screen module,
|
* This is a callback for the Screen module,
|
||||||
* called after each visible screen modification.
|
* called after each visible screen modification.
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic)
|
void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyTopics topics)
|
||||||
{
|
{
|
||||||
if (active_clients == 0) return;
|
if (term_active_clients == 0) return;
|
||||||
|
|
||||||
// this is probably not needed here - ensure timeout is not 0
|
// this is probably not needed here - ensure timeout is not 0
|
||||||
if (termconf->display_tout_ms == 0)
|
if (termconf->display_tout_ms == 0) {
|
||||||
termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
||||||
|
|
||||||
// NOTE: the timers are restarted if already running
|
|
||||||
|
|
||||||
if (topic == CHANGE_LABELS) {
|
|
||||||
// separate timer from content change timer, to avoid losing that update
|
|
||||||
TIMER_START(¬ifyLabelsTim, notifyLabelsTimCb, termconf->display_tout_ms+2, 0); // this delay is useful when both are fired at once on screen reset
|
|
||||||
}
|
|
||||||
else if (topic == CHANGE_CONTENT) {
|
|
||||||
// throttle delay
|
|
||||||
TIMER_START(¬ifyContentTim, notifyContentTimCb, termconf->display_tout_ms, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: the timer is restarted if already running
|
||||||
|
TIMER_START(&updateNotifyTim, updateNotifyCb, termconf->display_tout_ms, 0); // note - this adds latency to beep
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,8 +272,7 @@ static void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int
|
|||||||
case 'i':
|
case 'i':
|
||||||
// requests initial load
|
// requests initial load
|
||||||
inp_dbg("Client requests initial load");
|
inp_dbg("Client requests initial load");
|
||||||
notifyContentTimCb(ws); // delay??
|
updateNotify_do(ws, TOPIC_INITIAL);
|
||||||
notifyLabelsTimCb(ws);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
@@ -322,7 +297,7 @@ static void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int
|
|||||||
/** Send a heartbeat msg */
|
/** Send a heartbeat msg */
|
||||||
static void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused)
|
static void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused)
|
||||||
{
|
{
|
||||||
if (active_clients > 0) {
|
if (term_active_clients > 0) {
|
||||||
if (notify_available) {
|
if (notify_available) {
|
||||||
inp_dbg(".");
|
inp_dbg(".");
|
||||||
|
|
||||||
@@ -348,9 +323,9 @@ static void ICACHE_FLASH_ATTR resetHeartbeatTimer(void)
|
|||||||
|
|
||||||
static void ICACHE_FLASH_ATTR closeSockCb(Websock *ws)
|
static void ICACHE_FLASH_ATTR closeSockCb(Websock *ws)
|
||||||
{
|
{
|
||||||
active_clients--;
|
term_active_clients--;
|
||||||
if (active_clients <= 0) {
|
if (term_active_clients <= 0) {
|
||||||
active_clients = 0;
|
term_active_clients = 0;
|
||||||
|
|
||||||
if (mouse_tracking.focus_tracking) {
|
if (mouse_tracking.focus_tracking) {
|
||||||
UART_SendAsync("\x1b[O", 3);
|
UART_SendAsync("\x1b[O", 3);
|
||||||
@@ -368,7 +343,7 @@ void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws)
|
|||||||
ws->recvCb = updateSockRx;
|
ws->recvCb = updateSockRx;
|
||||||
ws->closeCb = closeSockCb;
|
ws->closeCb = closeSockCb;
|
||||||
|
|
||||||
if (active_clients == 0) {
|
if (term_active_clients == 0) {
|
||||||
if (mouse_tracking.focus_tracking) {
|
if (mouse_tracking.focus_tracking) {
|
||||||
UART_SendAsync("\x1b[I", 3);
|
UART_SendAsync("\x1b[I", 3);
|
||||||
}
|
}
|
||||||
@@ -376,7 +351,7 @@ void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws)
|
|||||||
resetHeartbeatTimer();
|
resetHeartbeatTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
active_clients++;
|
term_active_clients++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ETSTimer xonTim;
|
ETSTimer xonTim;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ void send_beep(void);
|
|||||||
/** open pop-up notification */
|
/** open pop-up notification */
|
||||||
void notify_growl(char *msg);
|
void notify_growl(char *msg);
|
||||||
|
|
||||||
|
extern volatile int term_active_clients;
|
||||||
|
|
||||||
// defined in the makefile
|
// defined in the makefile
|
||||||
#if DEBUG_INPUT
|
#if DEBUG_INPUT
|
||||||
#define inp_warn warn
|
#define inp_warn warn
|
||||||
|
|||||||
+26
-16
@@ -40,7 +40,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
char buff[50];
|
char buff[50];
|
||||||
char redir_url_buf[100];
|
char redir_url_buf[100];
|
||||||
int32 n, w, h;
|
int32 n, w, h;
|
||||||
bool notify_screen_content = 0, notify_screen_labels = 0;
|
ScreenNotifyTopics topics = 0;
|
||||||
|
|
||||||
bool shall_clear_screen = false;
|
bool shall_clear_screen = false;
|
||||||
bool shall_init_uart = false;
|
bool shall_init_uart = false;
|
||||||
@@ -94,7 +94,8 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (termconf->width != w || termconf->height != h) {
|
if (termconf->width != w || termconf->height != h) {
|
||||||
termconf->width = w;
|
termconf->width = w;
|
||||||
termconf->height = h;
|
termconf->height = h;
|
||||||
shall_clear_screen = true; // this causes a notify
|
shall_clear_screen = true;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS | TOPIC_CHANGE_CONTENT_ALL;
|
||||||
}
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
}
|
}
|
||||||
@@ -112,6 +113,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
|
|
||||||
if (termconf->default_bg != n) {
|
if (termconf->default_bg != n) {
|
||||||
termconf->default_bg = n; // this is current not sent through socket, no use to notify
|
termconf->default_bg = n; // this is current not sent through socket, no use to notify
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +130,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
|
|
||||||
if (termconf->default_fg != n) {
|
if (termconf->default_fg != n) {
|
||||||
termconf->default_fg = n; // this is current not sent through socket, no use to notify
|
termconf->default_fg = n; // this is current not sent through socket, no use to notify
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,40 +171,49 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
cgi_dbg("FN alt mode: %s", buff);
|
cgi_dbg("FN alt mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->fn_alt_mode = (bool)n;
|
termconf->fn_alt_mode = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("want_all_fn")) {
|
if (GET_ARG("want_all_fn")) {
|
||||||
cgi_dbg("AllFN mode: %s", buff);
|
cgi_dbg("AllFN mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->want_all_fn = (bool)n;
|
termconf->want_all_fn = (bool)n;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("crlf_mode")) {
|
if (GET_ARG("crlf_mode")) {
|
||||||
cgi_dbg("CRLF mode: %s", buff);
|
cgi_dbg("CRLF mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->crlf_mode = (bool)n;
|
termconf->crlf_mode = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("show_buttons")) {
|
if (GET_ARG("show_buttons")) {
|
||||||
cgi_dbg("Show buttons: %s", buff);
|
cgi_dbg("Show buttons: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->show_buttons = (bool)n;
|
termconf->show_buttons = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("show_config_links")) {
|
if (GET_ARG("show_config_links")) {
|
||||||
cgi_dbg("Show config links: %s", buff);
|
cgi_dbg("Show config links: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->show_config_links = (bool)n;
|
termconf->show_config_links = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("loopback")) {
|
if (GET_ARG("loopback")) {
|
||||||
cgi_dbg("Loopback: %s", buff);
|
cgi_dbg("Loopback: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->loopback = (bool)n;
|
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("theme")) {
|
if (GET_ARG("theme")) {
|
||||||
@@ -213,6 +225,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad theme num: %s", buff);
|
cgi_warn("Bad theme num: %s", buff);
|
||||||
redir_url += sprintf(redir_url, "theme,");
|
redir_url += sprintf(redir_url, "theme,");
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +234,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
if (n >= 0 && n <= 6 && n != 1) {
|
if (n >= 0 && n <= 6 && n != 1) {
|
||||||
termconf->cursor_shape = (enum CursorShape) n;
|
termconf->cursor_shape = (enum CursorShape) n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad cursor_shape num: %s", buff);
|
cgi_warn("Bad cursor_shape num: %s", buff);
|
||||||
redir_url += sprintf(redir_url, "cursor_shape,");
|
redir_url += sprintf(redir_url, "cursor_shape,");
|
||||||
@@ -231,7 +244,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (GET_ARG("term_title")) {
|
if (GET_ARG("term_title")) {
|
||||||
cgi_dbg("Terminal title default text: \"%s\"", buff);
|
cgi_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
|
||||||
notify_screen_labels = true;
|
topics |= TOPIC_CHANGE_TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
||||||
@@ -239,7 +252,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (GET_ARG(buff)) {
|
if (GET_ARG(buff)) {
|
||||||
cgi_dbg("Button%d default text: \"%s\"", btn_i, buff);
|
cgi_dbg("Button%d default text: \"%s\"", btn_i, buff);
|
||||||
strncpy_safe(termconf->btn[btn_i-1], buff, TERM_BTN_LEN);
|
strncpy_safe(termconf->btn[btn_i-1], buff, TERM_BTN_LEN);
|
||||||
notify_screen_labels = true;
|
topics |= TOPIC_CHANGE_BUTTONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(buff, "bm%d", btn_i);
|
sprintf(buff, "bm%d", btn_i);
|
||||||
@@ -368,13 +381,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
serialInit();
|
serialInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notify_screen_content) {
|
if (topics) screen_notifyChange(topics);
|
||||||
screen_notifyChange(CHANGE_CONTENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notify_screen_labels) {
|
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
|
||||||
}
|
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||||
} else {
|
} else {
|
||||||
@@ -440,6 +447,9 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
|||||||
else if (streq(token, "loopback")) {
|
else if (streq(token, "loopback")) {
|
||||||
sprintf(buff, "%d", (int)termconf->loopback);
|
sprintf(buff, "%d", (int)termconf->loopback);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "debugbar")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->debugbar);
|
||||||
|
}
|
||||||
else if (streq(token, "theme")) {
|
else if (streq(token, "theme")) {
|
||||||
sprintf(buff, "%d", termconf->theme);
|
sprintf(buff, "%d", termconf->theme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,4 @@
|
|||||||
|
|
||||||
extern const HttpdBuiltInUrl routes[];
|
extern const HttpdBuiltInUrl routes[];
|
||||||
|
|
||||||
/** Broadcast screen state to sockets */
|
|
||||||
void screen_notifyChange();
|
|
||||||
|
|
||||||
#endif //ROUTES_H
|
#endif //ROUTES_H
|
||||||
|
|||||||
+285
-102
@@ -5,10 +5,9 @@
|
|||||||
#include "sgr.h"
|
#include "sgr.h"
|
||||||
#include "ascii.h"
|
#include "ascii.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
#include "jstring.h"
|
|
||||||
#include "character_sets.h"
|
#include "character_sets.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "uart_buffer.h"
|
#include "cgi_sockets.h"
|
||||||
|
|
||||||
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
TerminalConfigBundle * const termconf = &persist.current.termconf;
|
||||||
TerminalConfigBundle termconf_live;
|
TerminalConfigBundle termconf_live;
|
||||||
@@ -74,7 +73,6 @@ typedef struct {
|
|||||||
bool hanging; //!< xenl state - cursor half-wrapped
|
bool hanging; //!< xenl state - cursor half-wrapped
|
||||||
|
|
||||||
/* SGR */
|
/* SGR */
|
||||||
bool inverse; //!< not in attrs bc it's applied immediately when writing the cell
|
|
||||||
bool conceal; //!< similar to inverse, causes all to be replaced by SP
|
bool conceal; //!< similar to inverse, causes all to be replaced by SP
|
||||||
u16 attrs;
|
u16 attrs;
|
||||||
Color fg; //!< Foreground color for writing
|
Color fg; //!< Foreground color for writing
|
||||||
@@ -139,14 +137,19 @@ static struct {
|
|||||||
* (from nested calls)
|
* (from nested calls)
|
||||||
*/
|
*/
|
||||||
static volatile int notifyLock = 0;
|
static volatile int notifyLock = 0;
|
||||||
|
static volatile ScreenNotifyTopics lockTopics = 0;
|
||||||
|
|
||||||
#define NOTIFY_LOCK() do { \
|
#define NOTIFY_LOCK() do { \
|
||||||
notifyLock++; \
|
notifyLock++; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define NOTIFY_DONE() do { \
|
#define NOTIFY_DONE(updateTopics) do { \
|
||||||
|
lockTopics |= (updateTopics); \
|
||||||
if (notifyLock > 0) notifyLock--; \
|
if (notifyLock > 0) notifyLock--; \
|
||||||
if (notifyLock == 0) screen_notifyChange(CHANGE_CONTENT); \
|
if (notifyLock == 0) { \
|
||||||
|
screen_notifyChange(lockTopics); \
|
||||||
|
lockTopics = 0;\
|
||||||
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/** Clear the hanging attribute if the cursor is no longer >= W */
|
/** Clear the hanging attribute if the cursor is no longer >= W */
|
||||||
@@ -185,6 +188,7 @@ terminal_restore_defaults(void)
|
|||||||
termconf->cursor_shape = SCR_DEF_CURSOR_SHAPE;
|
termconf->cursor_shape = SCR_DEF_CURSOR_SHAPE;
|
||||||
termconf->crlf_mode = SCR_DEF_CRLF;
|
termconf->crlf_mode = SCR_DEF_CRLF;
|
||||||
termconf->want_all_fn = SCR_DEF_ALLFN;
|
termconf->want_all_fn = SCR_DEF_ALLFN;
|
||||||
|
termconf->debugbar = SCR_DEF_DEBUGBAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,12 +207,12 @@ terminal_apply_settings_noclear(void)
|
|||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
// // Migrate to v1
|
// Migrate to v1
|
||||||
// if (termconf->config_version < 1) {
|
if (termconf->config_version < 1) {
|
||||||
// persist_dbg("termconf: Updating to version %d", 1);
|
persist_dbg("termconf: Updating to version %d", 1);
|
||||||
// termconf->display_cooldown_ms = SCR_DEF_DISPLAY_COOLDOWN_MS;
|
termconf->debugbar = SCR_DEF_DEBUGBAR;
|
||||||
// changed = 1;
|
changed = 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
termconf->config_version = TERMCONF_VERSION;
|
termconf->config_version = TERMCONF_VERSION;
|
||||||
|
|
||||||
@@ -257,6 +261,8 @@ screen_init(void)
|
|||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
cursor_reset(void)
|
cursor_reset(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
cursor.x = 0;
|
cursor.x = 0;
|
||||||
cursor.y = 0;
|
cursor.y = 0;
|
||||||
cursor.hanging = false;
|
cursor.hanging = false;
|
||||||
@@ -266,6 +272,8 @@ cursor_reset(void)
|
|||||||
cursor.charset1 = CS_0_DEC_SUPPLEMENTAL;
|
cursor.charset1 = CS_0_DEC_SUPPLEMENTAL;
|
||||||
|
|
||||||
screen_reset_sgr();
|
screen_reset_sgr();
|
||||||
|
|
||||||
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -285,7 +293,7 @@ screen_reset_on_resize(void)
|
|||||||
// size is left unchanged
|
// size is left unchanged
|
||||||
screen_clear(CLEAR_ALL); // also clears utf cache
|
screen_clear(CLEAR_ALL); // also clears utf cache
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -294,15 +302,20 @@ screen_reset_on_resize(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_reset_sgr(void)
|
screen_reset_sgr(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
cursor.fg = 0;
|
cursor.fg = 0;
|
||||||
cursor.bg = 0;
|
cursor.bg = 0;
|
||||||
cursor.attrs = 0;
|
cursor.attrs = 0;
|
||||||
cursor.conceal = false;
|
cursor.conceal = false;
|
||||||
|
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
screen_reset_do(bool size, bool labels)
|
screen_reset_do(bool size, bool labels)
|
||||||
{
|
{
|
||||||
|
ScreenNotifyTopics topics = TOPIC_CHANGE_SCREEN_OPTS | TOPIC_CHANGE_CURSOR | TOPIC_CHANGE_CONTENT_ALL;
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
// DECopts
|
// DECopts
|
||||||
@@ -350,7 +363,7 @@ screen_reset_do(bool size, bool labels)
|
|||||||
termconf_live.show_buttons = termconf->show_buttons;
|
termconf_live.show_buttons = termconf->show_buttons;
|
||||||
termconf_live.show_config_links = termconf->show_config_links;
|
termconf_live.show_config_links = termconf->show_config_links;
|
||||||
|
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
topics |= TOPIC_CHANGE_TITLE | TOPIC_CHANGE_BUTTONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial values in the save buffer in case of receiving restore without storing first
|
// initial values in the save buffer in case of receiving restore without storing first
|
||||||
@@ -368,7 +381,7 @@ screen_reset_do(bool size, bool labels)
|
|||||||
opt_backup.show_buttons = termconf_live.show_buttons;
|
opt_backup.show_buttons = termconf_live.show_buttons;
|
||||||
opt_backup.show_config_links = termconf_live.show_config_links;
|
opt_backup.show_config_links = termconf_live.show_config_links;
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(topics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -395,8 +408,11 @@ screen_swap_state(bool alternate)
|
|||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
|
||||||
if (alternate) {
|
if (alternate) {
|
||||||
ansi_dbg("Swap to alternate");
|
ansi_dbg("Swap to alternate");
|
||||||
|
NOTIFY_LOCK();
|
||||||
// store old state
|
// store old state
|
||||||
memcpy(state_backup.title, termconf_live.title, TERM_TITLE_LEN);
|
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, termconf_live.btn, sizeof(termconf_live.btn));
|
||||||
@@ -411,7 +427,6 @@ screen_swap_state(bool alternate)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ansi_dbg("Unswap from alternate");
|
ansi_dbg("Unswap from alternate");
|
||||||
NOTIFY_LOCK();
|
|
||||||
memcpy(termconf_live.title, state_backup.title, TERM_TITLE_LEN);
|
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, state_backup.btn, sizeof(termconf_live.btn));
|
||||||
memcpy(termconf_live.btn_msg, state_backup.btn_msg, sizeof(termconf_live.btn_msg));
|
memcpy(termconf_live.btn_msg, state_backup.btn_msg, sizeof(termconf_live.btn_msg));
|
||||||
@@ -421,11 +436,10 @@ screen_swap_state(bool alternate)
|
|||||||
// this may clear the screen as a side effect if size changed
|
// this may clear the screen as a side effect if size changed
|
||||||
screen_resize(state_backup.height, state_backup.width);
|
screen_resize(state_backup.height, state_backup.width);
|
||||||
// TODO restore screen content (if this is ever possible)
|
// TODO restore screen content (if this is ever possible)
|
||||||
NOTIFY_DONE();
|
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state_backup.alternate_active = alternate;
|
state_backup.alternate_active = alternate;
|
||||||
|
NOTIFY_DONE(TOPIC_INITIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -435,19 +449,25 @@ screen_swap_state(bool alternate)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_clear_all_tabs(void)
|
screen_clear_all_tabs(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
memset(scr.tab_stops, 0, sizeof(scr.tab_stops));
|
memset(scr.tab_stops, 0, sizeof(scr.tab_stops));
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_tab(void)
|
screen_set_tab(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
scr.tab_stops[cursor.x/32] |= (1<<(cursor.x%32));
|
scr.tab_stops[cursor.x/32] |= (1<<(cursor.x%32));
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_clear_tab(void)
|
screen_clear_tab(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
scr.tab_stops[cursor.x/32] &= ~(1<<(cursor.x%32));
|
scr.tab_stops[cursor.x/32] &= ~(1<<(cursor.x%32));
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -529,7 +549,7 @@ screen_tab_forward(int count)
|
|||||||
cursor.x = W - 1;
|
cursor.x = W - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -544,7 +564,7 @@ screen_tab_reverse(int count)
|
|||||||
cursor.x = 0;
|
cursor.x = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -733,7 +753,7 @@ screen_clear(ClearMode mode)
|
|||||||
clear_range_utf(0, (cursor.y * W) + cursor.x);
|
clear_range_utf(0, (cursor.y * W) + cursor.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(mode == CLEAR_ALL ? TOPIC_CHANGE_CONTENT_ALL : TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -756,7 +776,7 @@ screen_clear_line(ClearMode mode)
|
|||||||
clear_range_utf(cursor.y * W, cursor.y * W + cursor.x);
|
clear_range_utf(cursor.y * W, cursor.y * W + cursor.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -768,7 +788,7 @@ screen_clear_in_line(unsigned int count)
|
|||||||
} else {
|
} else {
|
||||||
clear_range_utf(cursor.y * W + cursor.x, cursor.y * W + cursor.x + count - 1);
|
clear_range_utf(cursor.y * W + cursor.x, cursor.y * W + cursor.x + count - 1);
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -796,7 +816,7 @@ screen_insert_lines(unsigned int lines)
|
|||||||
copy_row(i, cursor.y);
|
copy_row(i, cursor.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -821,7 +841,7 @@ screen_delete_lines(unsigned int lines)
|
|||||||
clear_range_noutf((movedBlockEnd+1)*W, (BTM+1)*W-1);
|
clear_range_noutf((movedBlockEnd+1)*W, (BTM+1)*W-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -844,7 +864,7 @@ screen_insert_characters(unsigned int count)
|
|||||||
}
|
}
|
||||||
clear_range_utf(cursor.y * W + cursor.x, cursor.y * W + targetStart - 1);
|
clear_range_utf(cursor.y * W + cursor.x, cursor.y * W + targetStart - 1);
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -870,7 +890,7 @@ screen_delete_characters(unsigned int count)
|
|||||||
screen_clear_line(CLEAR_FROM_CURSOR);
|
screen_clear_line(CLEAR_FROM_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
@@ -891,7 +911,7 @@ screen_fill_with_E(void)
|
|||||||
for (unsigned int i = 0; i <= W*H-1; i++) {
|
for (unsigned int i = 0; i <= W*H-1; i++) {
|
||||||
memcpy(&screen[i], &sample, sizeof(Cell));
|
memcpy(&screen[i], &sample, sizeof(Cell));
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -920,14 +940,15 @@ screen_resize(int rows, int cols)
|
|||||||
W = cols;
|
W = cols;
|
||||||
H = rows;
|
H = rows;
|
||||||
screen_reset_on_resize();
|
screen_reset_on_resize();
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS|TOPIC_CHANGE_CONTENT_ALL|TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_title(const char *title)
|
screen_set_title(const char *title)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
strncpy(termconf_live.title, title, TERM_TITLE_LEN);
|
strncpy(termconf_live.title, title, TERM_TITLE_LEN);
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
NOTIFY_DONE(TOPIC_CHANGE_TITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -938,8 +959,9 @@ screen_set_title(const char *title)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_button_text(int num, const char *text)
|
screen_set_button_text(int num, const char *text)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
strncpy(termconf_live.btn[num-1], text, TERM_BTN_LEN);
|
strncpy(termconf_live.btn[num-1], text, TERM_BTN_LEN);
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
NOTIFY_DONE(TOPIC_CHANGE_BUTTONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -970,7 +992,7 @@ screen_scroll_up(unsigned int lines)
|
|||||||
clear_range_noutf(y * W, (BTM + 1) * W - 1);
|
clear_range_noutf(y * W, (BTM + 1) * W - 1);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1000,13 +1022,14 @@ screen_scroll_down(unsigned int lines)
|
|||||||
|
|
||||||
clear_range_noutf(TOP * W, TOP * W + lines * W - 1);
|
clear_range_noutf(TOP * W, TOP * W + lines * W - 1);
|
||||||
done:
|
done:
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set scrolling region */
|
/** Set scrolling region */
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_scrolling_region(int from, int to)
|
screen_set_scrolling_region(int from, int to)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (from <= 0 && to <= 0) {
|
if (from <= 0 && to <= 0) {
|
||||||
scr.vm0 = 0;
|
scr.vm0 = 0;
|
||||||
scr.vm1 = H-1;
|
scr.vm1 = H-1;
|
||||||
@@ -1020,6 +1043,7 @@ screen_set_scrolling_region(int from, int to)
|
|||||||
|
|
||||||
// Always move cursor home (may be translated due to DECOM)
|
// Always move cursor home (may be translated due to DECOM)
|
||||||
screen_cursor_set(0, 0);
|
screen_cursor_set(0, 0);
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -1033,7 +1057,7 @@ screen_cursor_shape(enum CursorShape shape)
|
|||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
if (shape == CURSOR_DEFAULT) shape = termconf->cursor_shape;
|
if (shape == CURSOR_DEFAULT) shape = termconf->cursor_shape;
|
||||||
termconf_live.cursor_shape = shape;
|
termconf_live.cursor_shape = shape;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set cursor blink option */
|
/** set cursor blink option */
|
||||||
@@ -1050,7 +1074,7 @@ screen_cursor_blink(bool blink)
|
|||||||
if (termconf_live.cursor_shape == CURSOR_BAR_BL) termconf_live.cursor_shape = CURSOR_BAR;
|
if (termconf_live.cursor_shape == CURSOR_BAR_BL) termconf_live.cursor_shape = CURSOR_BAR;
|
||||||
if (termconf_live.cursor_shape == CURSOR_UNDERLINE_BL) termconf_live.cursor_shape = CURSOR_UNDERLINE;
|
if (termconf_live.cursor_shape == CURSOR_UNDERLINE_BL) termconf_live.cursor_shape = CURSOR_UNDERLINE;
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1062,7 +1086,7 @@ screen_cursor_set(int y, int x)
|
|||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
screen_cursor_set_x(x);
|
screen_cursor_set_x(x);
|
||||||
screen_cursor_set_y(y);
|
screen_cursor_set_y(y);
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1093,7 +1117,7 @@ screen_cursor_set_x(int x)
|
|||||||
// hanging happens when the cursor is virtually at col=81, which
|
// hanging happens when the cursor is virtually at col=81, which
|
||||||
// cannot be set using the cursor-set commands.
|
// cannot be set using the cursor-set commands.
|
||||||
cursor.hanging = false;
|
cursor.hanging = false;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1112,7 +1136,7 @@ screen_cursor_set_y(int y)
|
|||||||
if (y < 0) y = 0;
|
if (y < 0) y = 0;
|
||||||
}
|
}
|
||||||
cursor.y = y;
|
cursor.y = y;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1195,7 +1219,7 @@ screen_cursor_move(int dy, int dx, bool scroll)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR | (scroll*TOPIC_CHANGE_CONTENT_PART));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1232,21 +1256,23 @@ screen_cursor_restore(bool withAttrs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_back_index(int count)
|
screen_back_index(int count)
|
||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
|
ScreenNotifyTopics topics = TOPIC_CHANGE_CURSOR;
|
||||||
int new_x = cursor.x - count;
|
int new_x = cursor.x - count;
|
||||||
if (new_x >= 0) {
|
if (new_x >= 0) {
|
||||||
cursor.x = new_x;
|
cursor.x = new_x;
|
||||||
} else {
|
} else {
|
||||||
cursor.x = 0;
|
cursor.x = 0;
|
||||||
screen_insert_characters(-new_x);
|
screen_insert_characters(-new_x);
|
||||||
|
topics |= TOPIC_CHANGE_CONTENT_PART;
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(topics);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -1261,7 +1287,7 @@ screen_set_cursor_visible(bool visible)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
scr.cursor_visible = visible;
|
scr.cursor_visible = visible;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1270,7 +1296,9 @@ screen_set_cursor_visible(bool visible)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_wrap_enable(bool enable)
|
screen_wrap_enable(bool enable)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.auto_wrap = enable;
|
cursor.auto_wrap = enable;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1279,7 +1307,9 @@ screen_wrap_enable(bool enable)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_reverse_wrap_enable(bool enable)
|
screen_reverse_wrap_enable(bool enable)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.reverse_wrap = enable;
|
cursor.reverse_wrap = enable;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1288,8 +1318,10 @@ screen_reverse_wrap_enable(bool enable)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_fg(Color color)
|
screen_set_fg(Color color)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.fg = color;
|
cursor.fg = color;
|
||||||
cursor.attrs |= ATTR_FG;
|
cursor.attrs |= ATTR_FG;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1298,8 +1330,10 @@ screen_set_fg(Color color)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_bg(Color color)
|
screen_set_bg(Color color)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.bg = color;
|
cursor.bg = color;
|
||||||
cursor.attrs |= ATTR_BG;
|
cursor.attrs |= ATTR_BG;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1308,8 +1342,10 @@ screen_set_bg(Color color)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_default_fg(void)
|
screen_set_default_fg(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.fg = 0;
|
cursor.fg = 0;
|
||||||
cursor.attrs &= ~ATTR_FG;
|
cursor.attrs &= ~ATTR_FG;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1318,45 +1354,57 @@ screen_set_default_fg(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_default_bg(void)
|
screen_set_default_bg(void)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.bg = 0;
|
cursor.bg = 0;
|
||||||
cursor.attrs &= ~ATTR_BG;
|
cursor.attrs &= ~ATTR_BG;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_sgr(CellAttrs attrs, bool ena)
|
screen_set_sgr(CellAttrs attrs, bool ena)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (ena) {
|
if (ena) {
|
||||||
cursor.attrs |= attrs;
|
cursor.attrs |= attrs;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cursor.attrs &= ~attrs;
|
cursor.attrs &= ~attrs;
|
||||||
}
|
}
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_sgr_conceal(bool ena)
|
screen_set_sgr_conceal(bool ena)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.conceal = ena;
|
cursor.conceal = ena;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_charset_n(int Gx)
|
screen_set_charset_n(int Gx)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (Gx < 0 || Gx > 1) return; // bad n
|
if (Gx < 0 || Gx > 1) return; // bad n
|
||||||
cursor.charsetN = Gx;
|
cursor.charsetN = Gx;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_charset(int Gx, char charset)
|
screen_set_charset(int Gx, char charset)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
if (Gx == 0) cursor.charset0 = charset;
|
if (Gx == 0) cursor.charset0 = charset;
|
||||||
else if (Gx == 1) cursor.charset1 = charset;
|
else if (Gx == 1) cursor.charset1 = charset;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_insert_mode(bool insert)
|
screen_set_insert_mode(bool insert)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
scr.insert_mode = insert;
|
scr.insert_mode = insert;
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1364,7 +1412,7 @@ screen_set_numpad_alt_mode(bool alt_mode)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
scr.numpad_alt_mode = alt_mode;
|
scr.numpad_alt_mode = alt_mode;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1372,7 +1420,7 @@ screen_set_cursors_alt_mode(bool alt_mode)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
scr.cursors_alt_mode = alt_mode;
|
scr.cursors_alt_mode = alt_mode;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1380,7 +1428,7 @@ screen_set_reverse_video(bool reverse)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
scr.reverse_video = reverse;
|
scr.reverse_video = reverse;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1388,7 +1436,7 @@ screen_set_bracketed_paste(bool ena)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
scr.bracketed_paste = ena;
|
scr.bracketed_paste = ena;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1396,29 +1444,34 @@ screen_set_newline_mode(bool nlm)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
termconf_live.crlf_mode = nlm;
|
termconf_live.crlf_mode = nlm;
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_set_origin_mode(bool region_origin)
|
screen_set_origin_mode(bool region_origin)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
cursor.origin_mode = region_origin;
|
cursor.origin_mode = region_origin;
|
||||||
screen_cursor_set(0, 0);
|
screen_cursor_set(0, 0);
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
do_save_private_opt(int n, bool save)
|
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) {
|
switch (n) {
|
||||||
case 1:
|
case 1:
|
||||||
SAVE_RESTORE(opt_backup.cursors_alt_mode, scr.cursors_alt_mode);
|
SAVE_RESTORE(opt_backup.cursors_alt_mode, scr.cursors_alt_mode);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
SAVE_RESTORE(opt_backup.reverse_video, scr.reverse_video);
|
SAVE_RESTORE(opt_backup.reverse_video, scr.reverse_video);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
SAVE_RESTORE(opt_backup.origin_mode, cursor.origin_mode);
|
SAVE_RESTORE(opt_backup.origin_mode, cursor.origin_mode); // XXX maybe we should move cursor to 1,1 if it's restored to True
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
SAVE_RESTORE(opt_backup.auto_wrap, cursor.auto_wrap);
|
SAVE_RESTORE(opt_backup.auto_wrap, cursor.auto_wrap);
|
||||||
@@ -1429,14 +1482,17 @@ do_save_private_opt(int n, bool save)
|
|||||||
case 1002:
|
case 1002:
|
||||||
case 1003:
|
case 1003:
|
||||||
SAVE_RESTORE(opt_backup.mouse_tracking, mouse_tracking.mode);
|
SAVE_RESTORE(opt_backup.mouse_tracking, mouse_tracking.mode);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 1004:
|
case 1004:
|
||||||
SAVE_RESTORE(opt_backup.focus_tracking, mouse_tracking.focus_tracking);
|
SAVE_RESTORE(opt_backup.focus_tracking, mouse_tracking.focus_tracking);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 1005:
|
case 1005:
|
||||||
case 1006:
|
case 1006:
|
||||||
case 1015:
|
case 1015:
|
||||||
SAVE_RESTORE(opt_backup.mouse_encoding, mouse_tracking.encoding);
|
SAVE_RESTORE(opt_backup.mouse_encoding, mouse_tracking.encoding);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 12: // cursor blink
|
case 12: // cursor blink
|
||||||
if (save) {
|
if (save) {
|
||||||
@@ -1444,9 +1500,11 @@ do_save_private_opt(int n, bool save)
|
|||||||
} else {
|
} else {
|
||||||
screen_cursor_blink(opt_backup.cursor_blink);
|
screen_cursor_blink(opt_backup.cursor_blink);
|
||||||
}
|
}
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 25:
|
||||||
SAVE_RESTORE(opt_backup.cursor_visible, scr.cursor_visible);
|
SAVE_RESTORE(opt_backup.cursor_visible, scr.cursor_visible);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 45:
|
case 45:
|
||||||
SAVE_RESTORE(opt_backup.reverse_wrap, cursor.reverse_wrap);
|
SAVE_RESTORE(opt_backup.reverse_wrap, cursor.reverse_wrap);
|
||||||
@@ -1456,19 +1514,24 @@ do_save_private_opt(int n, bool save)
|
|||||||
break;
|
break;
|
||||||
case 800:
|
case 800:
|
||||||
SAVE_RESTORE(opt_backup.show_buttons, termconf_live.show_buttons);
|
SAVE_RESTORE(opt_backup.show_buttons, termconf_live.show_buttons);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
case 801:
|
case 801:
|
||||||
SAVE_RESTORE(opt_backup.show_config_links, termconf_live.show_config_links);
|
SAVE_RESTORE(opt_backup.show_config_links, termconf_live.show_config_links);
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ansi_warn("Cannot store ?%d", n);
|
ansi_warn("Cannot store ?%d", n);
|
||||||
}
|
}
|
||||||
|
if (!save) NOTIFY_DONE(topics);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
screen_save_private_opt(int n)
|
screen_save_private_opt(int n)
|
||||||
{
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
do_save_private_opt(n, true);
|
do_save_private_opt(n, true);
|
||||||
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1476,7 +1539,7 @@ screen_restore_private_opt(int n)
|
|||||||
{
|
{
|
||||||
NOTIFY_LOCK();
|
NOTIFY_LOCK();
|
||||||
do_save_private_opt(n, false);
|
do_save_private_opt(n, false);
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -1599,7 +1662,7 @@ screen_putchar(const char *ch)
|
|||||||
strncpy(scr.last_char, result, 4);
|
strncpy(scr.last_char, result, 4);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1621,7 +1684,7 @@ screen_repeat_last_character(int count)
|
|||||||
putchar_graphic(scr.last_char);
|
putchar_graphic(scr.last_char);
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE(TOPIC_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1674,29 +1737,12 @@ struct ScreenSerializeState {
|
|||||||
UnicodeCacheRef lastSymbol;
|
UnicodeCacheRef lastSymbol;
|
||||||
char lastChar[4];
|
char lastChar[4];
|
||||||
u8 lastCharLen;
|
u8 lastCharLen;
|
||||||
int index;
|
int index; // index in the screen buffer
|
||||||
|
ScreenNotifyTopics topics;
|
||||||
|
ScreenNotifyTopics last_topic;
|
||||||
|
ScreenNotifyTopics current_topic;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* buffer should be at least 64+5*10+6 long (title + buttons + 6), ie. 120
|
|
||||||
* @param buffer
|
|
||||||
* @param buf_len
|
|
||||||
*/
|
|
||||||
void ICACHE_FLASH_ATTR
|
|
||||||
screenSerializeLabelsToBuffer(char *buffer, size_t buf_len)
|
|
||||||
{
|
|
||||||
(void)buf_len;
|
|
||||||
// let's just assume it's long enough - called with the huge websocket buffer
|
|
||||||
sprintf(buffer, "T%s\x01%s\x01%s\x01%s\x01%s\x01%s", // use 0x01 as separator
|
|
||||||
termconf_live.title,
|
|
||||||
termconf_live.btn[0],
|
|
||||||
termconf_live.btn[1],
|
|
||||||
termconf_live.btn[2],
|
|
||||||
termconf_live.btn[3],
|
|
||||||
termconf_live.btn[4]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the screen to a data buffer. May need multiple calls if the buffer is insufficient in size.
|
* Serialize the screen to a data buffer. May need multiple calls if the buffer is insufficient in size.
|
||||||
*
|
*
|
||||||
@@ -1705,12 +1751,14 @@ screenSerializeLabelsToBuffer(char *buffer, size_t buf_len)
|
|||||||
*
|
*
|
||||||
* @param buffer - buffer array of limited size. If NULL, indicates this is the last call.
|
* @param buffer - buffer array of limited size. If NULL, indicates this is the last call.
|
||||||
* @param buf_len - buffer array size
|
* @param buf_len - buffer array size
|
||||||
|
* @param topics - what should be included in the message (ignored after the first call)
|
||||||
* @param data - opaque pointer to internal data structure for storing state between repeated calls
|
* @param data - opaque pointer to internal data structure for storing state between repeated calls
|
||||||
* if NULL, indicates this is the first call.
|
* if NULL, indicates this is the first call; the structure will be allocated.
|
||||||
* @return HTTPD_CGI_DONE or HTTPD_CGI_MORE. If more, repeat with the same DATA.
|
*
|
||||||
|
* @return HTTPD_CGI_DONE or HTTPD_CGI_MORE. If more, repeat with the same `data` pointer.
|
||||||
*/
|
*/
|
||||||
httpd_cgi_state ICACHE_FLASH_ATTR
|
httpd_cgi_state ICACHE_FLASH_ATTR
|
||||||
screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics, void **data)
|
||||||
{
|
{
|
||||||
struct ScreenSerializeState *ss = *data;
|
struct ScreenSerializeState *ss = *data;
|
||||||
|
|
||||||
@@ -1719,11 +1767,11 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell *cell, *cell0;
|
Cell *cell, *cell0; // temporary cell pointers for finding repetitions
|
||||||
|
|
||||||
u8 nbytes;
|
u8 nbytes; // temporary variable for utf writing utilities
|
||||||
size_t remain = buf_len;
|
size_t remain = buf_len; // remaining space in the output buffer
|
||||||
char *bb = buffer;
|
char *bb = buffer; // write pointer
|
||||||
|
|
||||||
#define bufput_c(c) do { \
|
#define bufput_c(c) do { \
|
||||||
*bb = (char)(c); \
|
*bb = (char)(c); \
|
||||||
@@ -1742,26 +1790,78 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
bufput_utf8((num)); \
|
bufput_utf8((num)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
// tags for screen serialization
|
||||||
|
#define SEQ_TAG_REPEAT '\x02'
|
||||||
|
#define SEQ_TAG_COLORS '\x03'
|
||||||
|
#define SEQ_TAG_ATTRS '\x04'
|
||||||
|
#define SEQ_TAG_FG '\x05'
|
||||||
|
#define SEQ_TAG_BG '\x06'
|
||||||
|
|
||||||
|
#define TOPICMARK_SCREEN_OPTS 'O'
|
||||||
|
#define TOPICMARK_TITLE 'T'
|
||||||
|
#define TOPICMARK_BUTTONS 'B'
|
||||||
|
#define TOPICMARK_DEBUG 'D'
|
||||||
|
#define TOPICMARK_BELL '!'
|
||||||
|
#define TOPICMARK_CURSOR 'C'
|
||||||
|
#define TOPICMARK_SCREEN_ALL 'S'
|
||||||
|
#define TOPICMARK_SCREEN_PART 's'
|
||||||
|
|
||||||
if (ss == NULL) {
|
if (ss == NULL) {
|
||||||
|
// START!
|
||||||
|
|
||||||
*data = ss = malloc(sizeof(struct ScreenSerializeState));
|
*data = ss = malloc(sizeof(struct ScreenSerializeState));
|
||||||
|
|
||||||
|
if (topics == 0 || termconf_live.debugbar) {
|
||||||
|
topics |= TOPIC_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
ss->index = 0;
|
ss->index = 0;
|
||||||
ss->lastBg = 0xFF;
|
|
||||||
ss->lastFg = 0xFF;
|
ss->topics = topics;
|
||||||
ss->lastAttrs = 0xFFFF;
|
ss->last_topic = 0; // to be filled
|
||||||
ss->lastCharLen = 0;
|
ss->current_topic = 0; // to be filled
|
||||||
ss->lastSymbol = 0;
|
|
||||||
strncpy(ss->lastChar, " ", 4);
|
strncpy(ss->lastChar, " ", 4);
|
||||||
|
|
||||||
bufput_c('S');
|
dbg("NOTIFY -> %02X", topics);
|
||||||
// H W X Y Attribs
|
|
||||||
|
bufput_c('U'); // - stands for "update"
|
||||||
|
|
||||||
|
bufput_utf8(topics & ~TOPIC_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int begun_topic = 0;
|
||||||
|
int prev_topic = 0;
|
||||||
|
|
||||||
|
#define BEGIN_TOPIC(topic, size) \
|
||||||
|
if (ss->last_topic == prev_topic) { \
|
||||||
|
begun_topic = (topic); \
|
||||||
|
if (ss->topics & (topic)) { \
|
||||||
|
if (remain < (size)) return HTTPD_CGI_MORE;
|
||||||
|
|
||||||
|
#define END_TOPIC \
|
||||||
|
} \
|
||||||
|
ss->last_topic = begun_topic; \
|
||||||
|
ss->current_topic = 0; \
|
||||||
|
} \
|
||||||
|
prev_topic = begun_topic;
|
||||||
|
|
||||||
|
if (ss->current_topic == 0) {
|
||||||
|
BEGIN_TOPIC(TOPIC_CHANGE_SCREEN_OPTS, 32+1)
|
||||||
|
bufput_c(TOPICMARK_SCREEN_OPTS);
|
||||||
|
|
||||||
bufput_utf8(H);
|
bufput_utf8(H);
|
||||||
bufput_utf8(W);
|
bufput_utf8(W);
|
||||||
bufput_utf8(cursor.y);
|
bufput_utf8(termconf_live.theme);
|
||||||
bufput_utf8(cursor.x);
|
|
||||||
// 3B has 18 free bits
|
bufput_utf8(termconf_live.default_fg & 0x000FFF);
|
||||||
|
bufput_utf8((termconf_live.default_fg & 0xFFF000) >> 12);
|
||||||
|
|
||||||
|
bufput_utf8(termconf_live.default_bg & 0x000FFF);
|
||||||
|
bufput_utf8((termconf_live.default_bg & 0xFFF000) >> 12);
|
||||||
|
|
||||||
bufput_utf8(
|
bufput_utf8(
|
||||||
(scr.cursor_visible << 0) |
|
(scr.cursor_visible << 0) |
|
||||||
(cursor.hanging << 1) |
|
(termconf_live.debugbar << 1) | // debugbar - this was previously "hanging"
|
||||||
(scr.cursors_alt_mode << 2) |
|
(scr.cursors_alt_mode << 2) |
|
||||||
(scr.numpad_alt_mode << 3) |
|
(scr.numpad_alt_mode << 3) |
|
||||||
(termconf_live.fn_alt_mode << 4) |
|
(termconf_live.fn_alt_mode << 4) |
|
||||||
@@ -1774,15 +1874,96 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
(scr.bracketed_paste << 13) |
|
(scr.bracketed_paste << 13) |
|
||||||
(scr.reverse_video << 14)
|
(scr.reverse_video << 14)
|
||||||
);
|
);
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
BEGIN_TOPIC(TOPIC_CHANGE_TITLE, TERM_TITLE_LEN+4+1)
|
||||||
|
bufput_c(TOPICMARK_TITLE);
|
||||||
|
|
||||||
|
int len = (int) strlen(termconf_live.title);
|
||||||
|
bufput_utf8(len);
|
||||||
|
memcpy(bb, termconf_live.title, len);
|
||||||
|
bb += len;
|
||||||
|
remain -= len;
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
BEGIN_TOPIC(TOPIC_CHANGE_BUTTONS, (TERM_BTN_LEN+4)*TERM_BTN_COUNT+1+4)
|
||||||
|
bufput_c(TOPICMARK_BUTTONS);
|
||||||
|
|
||||||
|
bufput_utf8(TERM_BTN_COUNT);
|
||||||
|
|
||||||
|
for (int i = 0; i < TERM_BTN_COUNT; i++) {
|
||||||
|
int len = (int) strlen(termconf_live.btn[i]);
|
||||||
|
bufput_utf8(len);
|
||||||
|
memcpy(bb, termconf_live.btn[i], len);
|
||||||
|
bb += len;
|
||||||
|
remain -= len;
|
||||||
|
}
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
BEGIN_TOPIC(TOPIC_INTERNAL, 45)
|
||||||
|
bufput_c(TOPICMARK_DEBUG);
|
||||||
|
// General flags
|
||||||
|
bufput_utf8(
|
||||||
|
(scr.insert_mode << 0) |
|
||||||
|
(cursor.conceal << 1) |
|
||||||
|
(cursor.auto_wrap << 2) |
|
||||||
|
(cursor.reverse_wrap << 3) |
|
||||||
|
(cursor.origin_mode << 4) |
|
||||||
|
(cursor_saved << 5) |
|
||||||
|
(state_backup.alternate_active << 6)
|
||||||
|
);
|
||||||
|
bufput_utf8(cursor.attrs);
|
||||||
|
bufput_utf8(scr.vm0);
|
||||||
|
bufput_utf8(scr.vm1);
|
||||||
|
bufput_utf8(cursor.charsetN);
|
||||||
|
bufput_c(cursor.charset0);
|
||||||
|
bufput_c(cursor.charset1);
|
||||||
|
bufput_utf8(system_get_free_heap_size());
|
||||||
|
bufput_utf8(term_active_clients);
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
BEGIN_TOPIC(TOPIC_BELL, 1)
|
||||||
|
bufput_c(TOPICMARK_BELL);
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
BEGIN_TOPIC(TOPIC_CHANGE_CURSOR, 13)
|
||||||
|
bufput_c(TOPICMARK_CURSOR);
|
||||||
|
bufput_utf8(cursor.y);
|
||||||
|
bufput_utf8(cursor.x);
|
||||||
|
bufput_utf8(
|
||||||
|
(cursor.hanging << 0)
|
||||||
|
);
|
||||||
|
END_TOPIC
|
||||||
|
|
||||||
|
if (ss->last_topic == TOPIC_CHANGE_CURSOR) {
|
||||||
|
// now we can begin any of the two screen sequences
|
||||||
|
|
||||||
|
if (ss->topics & TOPIC_CHANGE_CONTENT_ALL) {
|
||||||
|
ss->current_topic = TOPIC_CHANGE_CONTENT_ALL;
|
||||||
|
}
|
||||||
|
if (ss->topics & TOPIC_CHANGE_CONTENT_PART) {
|
||||||
|
ss->current_topic = TOPIC_CHANGE_CONTENT_PART;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SEQ_TAG_REPEAT '\x02'
|
if (ss->current_topic == 0) {
|
||||||
#define SEQ_TAG_COLORS '\x03'
|
// no screen mode - wrap it up
|
||||||
#define SEQ_TAG_ATTRS '\x04'
|
goto ser_done;
|
||||||
#define SEQ_TAG_FG '\x05'
|
}
|
||||||
#define SEQ_TAG_BG '\x06'
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// screen contents - TODO implement partial update
|
||||||
int i = ss->index;
|
int i = ss->index;
|
||||||
|
if (i == 0) {
|
||||||
|
bufput_c(TOPICMARK_SCREEN_ALL); // desired update mode is in `ss->current_topic`
|
||||||
|
|
||||||
|
ss->index = 0;
|
||||||
|
ss->lastBg = 0xFF;
|
||||||
|
ss->lastFg = 0xFF;
|
||||||
|
ss->lastAttrs = 0xFFFF;
|
||||||
|
ss->lastCharLen = 0;
|
||||||
|
ss->lastSymbol = 0;
|
||||||
|
}
|
||||||
while(i < W*H && remain > 12) {
|
while(i < W*H && remain > 12) {
|
||||||
cell = cell0 = &screen[i];
|
cell = cell0 = &screen[i];
|
||||||
|
|
||||||
@@ -1848,7 +2029,17 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ss->index = i;
|
ss->index = i;
|
||||||
|
if (i >= W*H-1) goto ser_done;
|
||||||
|
|
||||||
|
// MORE TO WRITE...
|
||||||
bufput_c('\0'); // terminate the string
|
bufput_c('\0'); // terminate the string
|
||||||
|
return HTTPD_CGI_MORE;
|
||||||
|
|
||||||
|
ser_done:
|
||||||
|
bufput_c('\0'); // terminate the string
|
||||||
|
return HTTPD_CGI_DONE;
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("MSG: ");
|
printf("MSG: ");
|
||||||
@@ -1857,11 +2048,3 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (i < W*H-1) {
|
|
||||||
return HTTPD_CGI_MORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HTTPD_CGI_DONE;
|
|
||||||
}
|
|
||||||
//endregion
|
|
||||||
|
|||||||
+30
-15
@@ -34,11 +34,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Size designed for the terminal config structure
|
|
||||||
// Must be constant to avoid corrupting user config after upgrade
|
|
||||||
#define TERMCONF_SIZE 300
|
|
||||||
#define TERMCONF_VERSION 0
|
|
||||||
|
|
||||||
#define TERM_BTN_LEN 10
|
#define TERM_BTN_LEN 10
|
||||||
#define TERM_BTN_MSG_LEN 10
|
#define TERM_BTN_MSG_LEN 10
|
||||||
#define TERM_TITLE_LEN 64
|
#define TERM_TITLE_LEN 64
|
||||||
@@ -70,10 +65,16 @@ enum CursorShape {
|
|||||||
#define SCR_DEF_CURSOR_SHAPE CURSOR_BLOCK_BL
|
#define SCR_DEF_CURSOR_SHAPE CURSOR_BLOCK_BL
|
||||||
#define SCR_DEF_CRLF 0 // enter sends CRLF
|
#define SCR_DEF_CRLF 0 // enter sends CRLF
|
||||||
#define SCR_DEF_ALLFN 0 // capture F5 etc
|
#define SCR_DEF_ALLFN 0 // capture F5 etc
|
||||||
|
#define SCR_DEF_DEBUGBAR 0
|
||||||
|
|
||||||
// --- Persistent Settings ---
|
// --- Persistent Settings ---
|
||||||
#define CURSOR_BLINKS(shape) ((shape)==CURSOR_BLOCK_BL||(shape)==CURSOR_UNDERLINE_BL||(shape)==CURSOR_BAR_BL)
|
#define CURSOR_BLINKS(shape) ((shape)==CURSOR_BLOCK_BL||(shape)==CURSOR_UNDERLINE_BL||(shape)==CURSOR_BAR_BL)
|
||||||
|
|
||||||
|
// Size designed for the terminal config structure
|
||||||
|
// Must be constant to avoid corrupting user config after upgrade
|
||||||
|
#define TERMCONF_SIZE 300
|
||||||
|
#define TERMCONF_VERSION 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
@@ -94,6 +95,7 @@ typedef struct {
|
|||||||
enum CursorShape cursor_shape;
|
enum CursorShape cursor_shape;
|
||||||
bool crlf_mode;
|
bool crlf_mode;
|
||||||
bool want_all_fn;
|
bool want_all_fn;
|
||||||
|
bool debugbar;
|
||||||
} TerminalConfigBundle;
|
} TerminalConfigBundle;
|
||||||
|
|
||||||
// Live config
|
// Live config
|
||||||
@@ -152,9 +154,29 @@ typedef enum {
|
|||||||
CS_1_DOS_437 = '1',
|
CS_1_DOS_437 = '1',
|
||||||
} CHARSET;
|
} CHARSET;
|
||||||
|
|
||||||
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
enum ScreenSerializeTopic {
|
||||||
|
TOPIC_CHANGE_SCREEN_OPTS = (1<<0),
|
||||||
|
TOPIC_CHANGE_TITLE = (1<<1),
|
||||||
|
TOPIC_CHANGE_BUTTONS = (1<<2),
|
||||||
|
TOPIC_BELL = (1<<3), // beep
|
||||||
|
TOPIC_CHANGE_CURSOR = (1<<4),
|
||||||
|
TOPIC_CHANGE_CONTENT_ALL = (1<<5),
|
||||||
|
TOPIC_CHANGE_CONTENT_PART = (1<<6),
|
||||||
|
TOPIC_INTERNAL = (1<<7), // debugging internal state
|
||||||
|
// combos
|
||||||
|
TOPIC_INITIAL =
|
||||||
|
TOPIC_CHANGE_SCREEN_OPTS |
|
||||||
|
TOPIC_CHANGE_CONTENT_ALL |
|
||||||
|
TOPIC_CHANGE_CURSOR |
|
||||||
|
TOPIC_CHANGE_TITLE |
|
||||||
|
TOPIC_CHANGE_BUTTONS,
|
||||||
|
|
||||||
void screenSerializeLabelsToBuffer(char *buffer, size_t buf_len);
|
TOPIC_WRITE = TOPIC_CHANGE_CURSOR | TOPIC_CHANGE_CONTENT_PART,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u16 ScreenNotifyTopics;
|
||||||
|
|
||||||
|
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics, void **data);
|
||||||
|
|
||||||
// --- Clearing ---
|
// --- Clearing ---
|
||||||
|
|
||||||
@@ -323,18 +345,11 @@ void screen_repeat_last_character(int count);
|
|||||||
/** Report current SGR as num;num;... for DAC query */
|
/** Report current SGR as num;num;... for DAC query */
|
||||||
void screen_report_sgr(char *buffer);
|
void screen_report_sgr(char *buffer);
|
||||||
|
|
||||||
// --- Notify ---
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CHANGE_CONTENT = 0,
|
|
||||||
CHANGE_LABELS = 1,
|
|
||||||
} ScreenNotifyChangeTopic;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the screen content or settings change
|
* Called when the screen content or settings change
|
||||||
* and the front-end should redraw / update.
|
* and the front-end should redraw / update.
|
||||||
* @param topic - what kind of change this is (chooses what message to send)
|
* @param topic - what kind of change this is (chooses what message to send)
|
||||||
*/
|
*/
|
||||||
extern void screen_notifyChange(ScreenNotifyChangeTopic topic);
|
extern void screen_notifyChange(ScreenNotifyTopics topics);
|
||||||
|
|
||||||
#endif // SCREEN_H
|
#endif // SCREEN_H
|
||||||
|
|||||||
Reference in New Issue
Block a user