Fixed a couple bugs and cleaned up the parser callbacks file for CSI

pull/111/merge
Ondřej Hruška 7 years ago
parent a78830f805
commit 116201e232
  1. 198
      user/ansi_parser.c
  2. 13
      user/ansi_parser.rl
  3. 651
      user/apars_csi.c
  4. 2
      user/apars_csi.h
  5. 59
      user/screen.c
  6. 2
      user/screen.h
  7. 8
      user/serial.c
  8. 2
      user/version.h

@ -13,22 +13,22 @@ static const char _ansi_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1, 0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 6, 1, 3, 1, 4, 1, 5, 1, 6, 1,
7, 1, 8, 1, 9, 1, 10, 1, 7, 1, 8, 1, 9, 1, 10, 1,
11, 1, 12, 1, 13, 1, 14, 2, 11, 1, 12, 1, 13, 1, 14, 1,
3, 6 15
}; };
static const char _ansi_eof_actions[] = { static const char _ansi_eof_actions[] = {
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 0, 0, 0, 0, 0 1, 1, 1, 0, 0, 0, 0
}; };
static const int ansi_start = 1; static const int ansi_start = 1;
static const int ansi_first_final = 10; static const int ansi_first_final = 11;
static const int ansi_error = 0; static const int ansi_error = 0;
static const int ansi_en_CSI_body = 5; static const int ansi_en_CSI_body = 5;
static const int ansi_en_STRCMD_body = 7; static const int ansi_en_STRCMD_body = 8;
static const int ansi_en_charsetcmd_body = 9; static const int ansi_en_charsetcmd_body = 10;
static const int ansi_en_main = 1; static const int ansi_en_main = 1;
@ -101,6 +101,7 @@ ansi_parser(char newchar)
{ {
// The CSI code is built here // The CSI code is built here
static char leadchar; static char leadchar;
static char interchar; // intermediate CSI char
static int arg_ni; static int arg_ni;
static int arg_cnt; static int arg_cnt;
static int arg[CSI_N_MAX]; static int arg[CSI_N_MAX];
@ -113,12 +114,12 @@ ansi_parser(char newchar)
// Init Ragel on the first run // Init Ragel on the first run
if (cs == -1) { if (cs == -1) {
/* #line 117 "user/ansi_parser.c" */ /* #line 118 "user/ansi_parser.c" */
{ {
cs = ansi_start; cs = ansi_start;
} }
/* #line 91 "user/ansi_parser.rl" */ /* #line 92 "user/ansi_parser.rl" */
#if DEBUG_ANSI #if DEBUG_ANSI
memset(history, 0, sizeof(history)); memset(history, 0, sizeof(history));
@ -198,7 +199,7 @@ ansi_parser(char newchar)
// The parser // The parser
/* #line 202 "user/ansi_parser.c" */ /* #line 203 "user/ansi_parser.c" */
{ {
const char *_acts; const char *_acts;
unsigned int _nacts; unsigned int _nacts;
@ -255,7 +256,7 @@ case 3:
} else if ( (*p) >= 70 ) } else if ( (*p) >= 70 )
goto tr9; goto tr9;
goto tr1; goto tr1;
case 10: case 11:
switch( (*p) ) { switch( (*p) ) {
case 7: goto tr1; case 7: goto tr1;
case 27: goto tr2; case 27: goto tr2;
@ -267,51 +268,63 @@ case 4:
goto tr1; goto tr1;
case 5: case 5:
switch( (*p) ) { switch( (*p) ) {
case 36: goto tr11;
case 59: goto tr13; case 59: goto tr13;
case 64: goto tr14;
} }
if ( (*p) < 60 ) { if ( (*p) < 48 ) {
if ( (*p) > 47 ) { if ( (*p) < 38 ) {
if ( 48 <= (*p) && (*p) <= 57 ) if ( 32 <= (*p) && (*p) <= 34 )
goto tr12; goto tr11;
} else if ( (*p) >= 32 ) } else if ( (*p) > 39 ) {
if ( 41 <= (*p) && (*p) <= 45 )
goto tr11; goto tr11;
} else if ( (*p) > 63 ) {
if ( (*p) > 90 ) {
if ( 96 <= (*p) && (*p) <= 122 )
goto tr15;
} else if ( (*p) >= 65 )
goto tr15;
} else } else
goto tr11; goto tr11;
goto tr1; } else if ( (*p) > 57 ) {
case 6:
if ( (*p) == 59 )
goto tr13;
if ( (*p) < 64 ) { if ( (*p) < 64 ) {
if ( 48 <= (*p) && (*p) <= 57 ) if ( 61 <= (*p) && (*p) <= 63 )
goto tr12; goto tr14;
} else if ( (*p) > 90 ) { } else if ( (*p) > 90 ) {
if ( 96 <= (*p) && (*p) <= 122 ) if ( 96 <= (*p) && (*p) <= 126 )
goto tr15; goto tr15;
} else } else
goto tr15; goto tr15;
} else
goto tr12;
goto tr1; goto tr1;
case 11: case 6:
if ( (*p) > 90 ) {
if ( 96 <= (*p) && (*p) <= 126 )
goto tr15;
} else if ( (*p) >= 64 )
goto tr15;
goto tr1; goto tr1;
case 12: case 12:
if ( (*p) == 59 ) goto tr1;
goto tr13; case 7:
switch( (*p) ) {
case 36: goto tr11;
case 59: goto tr13;
}
if ( (*p) < 41 ) {
if ( (*p) > 34 ) {
if ( 38 <= (*p) && (*p) <= 39 )
goto tr11;
} else if ( (*p) >= 32 )
goto tr11;
} else if ( (*p) > 45 ) {
if ( (*p) < 64 ) { if ( (*p) < 64 ) {
if ( 48 <= (*p) && (*p) <= 57 ) if ( 48 <= (*p) && (*p) <= 57 )
goto tr12; goto tr12;
} else if ( (*p) > 90 ) { } else if ( (*p) > 90 ) {
if ( 96 <= (*p) && (*p) <= 122 ) if ( 96 <= (*p) && (*p) <= 126 )
goto tr15; goto tr15;
} else } else
goto tr15; goto tr15;
} else
goto tr11;
goto tr1; goto tr1;
case 7: case 8:
switch( (*p) ) { switch( (*p) ) {
case 7: goto tr17; case 7: goto tr17;
case 27: goto tr18; case 27: goto tr18;
@ -319,11 +332,11 @@ case 7:
goto tr16; goto tr16;
case 13: case 13:
goto tr1; goto tr1;
case 8: case 9:
if ( (*p) == 92 ) if ( (*p) == 92 )
goto tr17; goto tr17;
goto tr1; goto tr1;
case 9: case 10:
switch( (*p) ) { switch( (*p) ) {
case 7: goto tr1; case 7: goto tr1;
case 27: goto tr1; case 27: goto tr1;
@ -339,44 +352,44 @@ case 14:
tr3: cs = 3; goto _again; tr3: cs = 3; goto _again;
tr4: cs = 4; goto _again; tr4: cs = 4; goto _again;
tr11: cs = 6; goto f8; tr11: cs = 6; goto f8;
tr12: cs = 6; goto f9; tr12: cs = 7; goto f9;
tr13: cs = 6; goto f10; tr13: cs = 7; goto f10;
tr16: cs = 7; goto f13; tr14: cs = 7; goto f11;
tr18: cs = 8; goto _again; tr16: cs = 8; goto f13;
tr5: cs = 10; goto f2; tr18: cs = 9; goto _again;
tr6: cs = 10; goto f3; tr5: cs = 11; goto f2;
tr7: cs = 10; goto f4; tr6: cs = 11; goto f3;
tr8: cs = 10; goto f5; tr7: cs = 11; goto f4;
tr9: cs = 10; goto f6; tr8: cs = 11; goto f5;
tr10: cs = 10; goto f7; tr9: cs = 11; goto f6;
tr15: cs = 11; goto f12; tr10: cs = 11; goto f7;
tr14: cs = 12; goto f11; tr15: cs = 12; goto f12;
tr17: cs = 13; goto f14; tr17: cs = 13; goto f14;
tr19: cs = 14; goto f15; tr19: cs = 14; goto f15;
f0: _acts = _ansi_actions + 1; goto execFuncs; f0: _acts = _ansi_actions + 1; goto execFuncs;
f1: _acts = _ansi_actions + 3; goto execFuncs; f1: _acts = _ansi_actions + 3; goto execFuncs;
f5: _acts = _ansi_actions + 5; goto execFuncs; f5: _acts = _ansi_actions + 5; goto execFuncs;
f8: _acts = _ansi_actions + 7; goto execFuncs; f11: _acts = _ansi_actions + 7; goto execFuncs;
f9: _acts = _ansi_actions + 9; goto execFuncs; f9: _acts = _ansi_actions + 9; goto execFuncs;
f10: _acts = _ansi_actions + 11; goto execFuncs; f10: _acts = _ansi_actions + 11; goto execFuncs;
f12: _acts = _ansi_actions + 13; goto execFuncs; f8: _acts = _ansi_actions + 13; goto execFuncs;
f4: _acts = _ansi_actions + 15; goto execFuncs; f12: _acts = _ansi_actions + 15; goto execFuncs;
f13: _acts = _ansi_actions + 17; goto execFuncs; f4: _acts = _ansi_actions + 17; goto execFuncs;
f14: _acts = _ansi_actions + 19; goto execFuncs; f13: _acts = _ansi_actions + 19; goto execFuncs;
f7: _acts = _ansi_actions + 21; goto execFuncs; f14: _acts = _ansi_actions + 21; goto execFuncs;
f3: _acts = _ansi_actions + 23; goto execFuncs; f7: _acts = _ansi_actions + 23; goto execFuncs;
f6: _acts = _ansi_actions + 25; goto execFuncs; f3: _acts = _ansi_actions + 25; goto execFuncs;
f2: _acts = _ansi_actions + 27; goto execFuncs; f6: _acts = _ansi_actions + 27; goto execFuncs;
f15: _acts = _ansi_actions + 29; goto execFuncs; f2: _acts = _ansi_actions + 29; goto execFuncs;
f11: _acts = _ansi_actions + 31; goto execFuncs; f15: _acts = _ansi_actions + 31; goto execFuncs;
execFuncs: execFuncs:
_nacts = *_acts++; _nacts = *_acts++;
while ( _nacts-- > 0 ) { while ( _nacts-- > 0 ) {
switch ( *_acts++ ) { switch ( *_acts++ ) {
case 0: case 0:
/* #line 178 "user/ansi_parser.rl" */ /* #line 179 "user/ansi_parser.rl" */
{ {
ansi_warn("Parser error."); ansi_warn("Parser error.");
apars_show_context(); apars_show_context();
@ -385,7 +398,7 @@ execFuncs:
} }
break; break;
case 1: case 1:
/* #line 187 "user/ansi_parser.rl" */ /* #line 188 "user/ansi_parser.rl" */
{ {
if ((*p) != 0) { if ((*p) != 0) {
apars_handle_plainchar((*p)); apars_handle_plainchar((*p));
@ -393,10 +406,11 @@ execFuncs:
} }
break; break;
case 2: case 2:
/* #line 195 "user/ansi_parser.rl" */ /* #line 196 "user/ansi_parser.rl" */
{ {
// Reset the CSI builder // Reset the CSI builder
leadchar = NUL; leadchar = NUL;
interchar = NUL;
arg_ni = 0; arg_ni = 0;
arg_cnt = 0; arg_cnt = 0;
@ -409,13 +423,13 @@ execFuncs:
} }
break; break;
case 3: case 3:
/* #line 209 "user/ansi_parser.rl" */ /* #line 211 "user/ansi_parser.rl" */
{ {
leadchar = (*p); leadchar = (*p);
} }
break; break;
case 4: case 4:
/* #line 213 "user/ansi_parser.rl" */ /* #line 215 "user/ansi_parser.rl" */
{ {
if (arg_cnt == 0) arg_cnt = 1; if (arg_cnt == 0) arg_cnt = 1;
// x10 + digit // x10 + digit
@ -425,7 +439,7 @@ execFuncs:
} }
break; break;
case 5: case 5:
/* #line 221 "user/ansi_parser.rl" */ /* #line 223 "user/ansi_parser.rl" */
{ {
if (arg_cnt == 0) arg_cnt = 1; // handle case when first arg is empty if (arg_cnt == 0) arg_cnt = 1; // handle case when first arg is empty
arg_cnt++; arg_cnt++;
@ -433,30 +447,36 @@ execFuncs:
} }
break; break;
case 6: case 6:
/* #line 227 "user/ansi_parser.rl" */ /* #line 229 "user/ansi_parser.rl" */
{ {
apars_handle_csi(leadchar, arg, arg_cnt, (*p)); interchar = (*p);
{cs = 1;goto _again;}
} }
break; break;
case 7: case 7:
/* #line 238 "user/ansi_parser.rl" */ /* #line 233 "user/ansi_parser.rl" */
{
apars_handle_csi(leadchar, arg, arg_cnt, interchar, (*p));
{cs = 1;goto _again;}
}
break;
case 8:
/* #line 245 "user/ansi_parser.rl" */
{ {
leadchar = (*p); leadchar = (*p);
str_ni = 0; str_ni = 0;
string_buffer[0] = '\0'; string_buffer[0] = '\0';
inside_string = true; inside_string = true;
{cs = 7;goto _again;} {cs = 8;goto _again;}
} }
break; break;
case 8: case 9:
/* #line 246 "user/ansi_parser.rl" */ /* #line 253 "user/ansi_parser.rl" */
{ {
string_buffer[str_ni++] = (*p); string_buffer[str_ni++] = (*p);
} }
break; break;
case 9: case 10:
/* #line 250 "user/ansi_parser.rl" */ /* #line 257 "user/ansi_parser.rl" */
{ {
inside_string = false; inside_string = false;
string_buffer[str_ni++] = '\0'; string_buffer[str_ni++] = '\0';
@ -464,42 +484,42 @@ execFuncs:
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 10: case 11:
/* #line 263 "user/ansi_parser.rl" */ /* #line 270 "user/ansi_parser.rl" */
{ {
apars_handle_hash_cmd((*p)); apars_handle_hash_cmd((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 11: case 12:
/* #line 268 "user/ansi_parser.rl" */ /* #line 275 "user/ansi_parser.rl" */
{ {
apars_handle_short_cmd((*p)); apars_handle_short_cmd((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 12: case 13:
/* #line 273 "user/ansi_parser.rl" */ /* #line 280 "user/ansi_parser.rl" */
{ {
apars_handle_space_cmd((*p)); apars_handle_space_cmd((*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
case 13: case 14:
/* #line 280 "user/ansi_parser.rl" */ /* #line 287 "user/ansi_parser.rl" */
{ {
leadchar = (*p); leadchar = (*p);
{cs = 9;goto _again;} {cs = 10;goto _again;}
} }
break; break;
case 14: case 15:
/* #line 285 "user/ansi_parser.rl" */ /* #line 292 "user/ansi_parser.rl" */
{ {
apars_handle_chs_designate(leadchar, (*p)); apars_handle_chs_designate(leadchar, (*p));
{cs = 1;goto _again;} {cs = 1;goto _again;}
} }
break; break;
/* #line 503 "user/ansi_parser.c" */ /* #line 523 "user/ansi_parser.c" */
} }
} }
goto _again; goto _again;
@ -517,7 +537,7 @@ _again:
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 0: case 0:
/* #line 178 "user/ansi_parser.rl" */ /* #line 179 "user/ansi_parser.rl" */
{ {
ansi_warn("Parser error."); ansi_warn("Parser error.");
apars_show_context(); apars_show_context();
@ -527,7 +547,7 @@ _again:
goto _again;} goto _again;}
} }
break; break;
/* #line 531 "user/ansi_parser.c" */ /* #line 551 "user/ansi_parser.c" */
} }
} }
} }
@ -535,6 +555,6 @@ goto _again;}
_out: {} _out: {}
} }
/* #line 308 "user/ansi_parser.rl" */ /* #line 315 "user/ansi_parser.rl" */
} }

@ -76,6 +76,7 @@ ansi_parser(char newchar)
{ {
// The CSI code is built here // The CSI code is built here
static char leadchar; static char leadchar;
static char interchar; // intermediate CSI char
static int arg_ni; static int arg_ni;
static int arg_cnt; static int arg_cnt;
static int arg[CSI_N_MAX]; static int arg[CSI_N_MAX];
@ -195,6 +196,7 @@ ansi_parser(char newchar)
action CSI_start { action CSI_start {
// Reset the CSI builder // Reset the CSI builder
leadchar = NUL; leadchar = NUL;
interchar = NUL;
arg_ni = 0; arg_ni = 0;
arg_cnt = 0; arg_cnt = 0;
@ -224,14 +226,19 @@ ansi_parser(char newchar)
arg_ni++; arg_ni++;
} }
action CSI_intermed {
interchar = fc;
}
action CSI_end { action CSI_end {
apars_handle_csi(leadchar, arg, arg_cnt, fc); apars_handle_csi(leadchar, arg, arg_cnt, interchar, fc);
fgoto main; fgoto main;
} }
CSI_body := ((32..47|60..64) @CSI_leading)? #(32..47|60..64)
CSI_body := ([?>=] @CSI_leading)?
((digit @CSI_digit)* ';' @CSI_semi)* ((digit @CSI_digit)* ';' @CSI_semi)*
(digit @CSI_digit)* (alpha|'`'|'@') @CSI_end $!errBadSeq; (digit @CSI_digit)* ([ $*"+,)'&!\-] @CSI_intermed)? (alpha|[`@{}~|]) @CSI_end $!errBadSeq;
# --- String commands --- # --- String commands ---

@ -3,19 +3,12 @@
// //
// Handle CSI sequences // Handle CSI sequences
// CSI <symbol?> Pm <symbol?> <char> // CSI <symbol?> Pm <symbol?> <char>
// (CSI = ESC [)
// //
// Example of those are cursor manipulation sequences and SGR. // Example of those are cursor manipulation sequences and SGR.
// //
// For details, see: // For details, see:
// http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Functions-using-CSI-_-ordered-by-the-final-character_s_ // http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Functions-using-CSI-_-ordered-by-the-final-character_s_
// //
// Note:
// not all sequences listed in the xterm manual are implemented, notably sequences with the trailing symbol,
// graphic mode sequences, mouse reporting and complex multi-argument sequences that operate on regions.
//
// The screen size can be set using the xterm sequence: CSI Py ; Px t
//
#include <esp8266.h> #include <esp8266.h>
#include "apars_csi.h" #include "apars_csi.h"
@ -29,86 +22,196 @@
#include "version.h" #include "version.h"
#include "syscfg.h" #include "syscfg.h"
// TODO simplify file - split to subroutines /** Struct passed to subroutines */
static void warn_bad_csi()
{
ansi_noimpl_r("Unknown CSI");
apars_show_context();
}
typedef struct { typedef struct {
char lead; char lead;
const int *n; const int *n;
int count; int count;
char aug; // augmenting char inter;
char key; char key;
} CSI_Data; } CSI_Data;
static void do_csi_privattr(CSI_Data *opts); // Disambiguations
static void do_csi_sgr(CSI_Data *opts); static inline void switch_csi_Plain(CSI_Data *opts);
static void do_csi_decreqtparm(CSI_Data *opts); static inline void switch_csi_NoLeadInterBang(CSI_Data *opts);
static inline void switch_csi_LeadGreater(CSI_Data *opts);
static inline void switch_csi_LeadQuest(CSI_Data *opts);
static inline void switch_csi_LeadEquals(CSI_Data *opts);
// Subroutines
static inline void do_csi_sgr(CSI_Data *opts);
static inline void do_csi_decreqtparm(CSI_Data *opts);
static inline void do_csi_set_option(CSI_Data *opts);
static inline void do_csi_xterm_screen_cmd(CSI_Data *opts);
static inline void do_csi_set_private_option(CSI_Data *opts);
/**
* Show warning and dump context for invalid CSI
*/
static void warn_bad_csi(void)
{
ansi_noimpl_r("Unknown CSI");
apars_show_context();
}
/** /**
* Handle fully received CSI ANSI sequence * Handle fully received CSI ANSI sequence
* @param leadchar - private range leading character, 0 if none *
* @param leadchar - leading character
* @param params - array of CSI_N_MAX ints holding the numeric arguments * @param params - array of CSI_N_MAX ints holding the numeric arguments
* @param keychar - the char terminating the sequence * @param count - actual amount of received numeric arguments
* @param keychar - intermediate character
* @param keychar - final character
*/ */
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
apars_handle_csi(char leadchar, const int *params, int count, char keychar) apars_handle_csi(char leadchar, const int *params, int count, char interchar, char keychar)
{ {
CSI_Data opts = {leadchar, params, count, NUL, keychar}; CSI_Data opts = {leadchar, params, count, interchar, keychar};
char buf[32];
bool yn = false; // for ? l h switch(leadchar) {
case '?':
int n1 = params[0]; switch_csi_LeadQuest(&opts);
int n2 = params[1]; break;
int n3 = params[2];
case '>':
// defaults - FIXME this may inadvertently affect some variants that should be left unchanged switch_csi_LeadGreater(&opts);
switch (keychar) { break;
case 'A': // move
case 'a': case '=':
case 'e': switch_csi_LeadEquals(&opts);
case 'B': break;
case 'C':
case 'D': case NUL:
case 'b': // No leading character, switch by intermediate character
case 'E': switch(interchar) {
case 'F': case NUL:
switch_csi_Plain(&opts);
break;
case '!':
switch_csi_NoLeadInterBang(&opts);
break;
// case '\'':
// switch_csi_NoLeadInterApos(opts);
// break;
// case '*':
// switch_csi_NoLeadInterStar(opts);
// break;
// case '+':
// switch_csi_NoLeadInterPlus(opts);
// break;
// case '"':
// switch_csi_NoLeadInterQuote(opts);
// break;
// case '|':
// switch_csi_NoLeadInterDollar(opts);
// break;
// case ' ':
// switch_csi_NoLeadInterSpace(opts);
// break;
// case ',':
// switch_csi_NoLeadInterComma(opts);
// break;
// case ')':
// switch_csi_NoLeadInterRparen(opts);
// break;
// case '&':
// switch_csi_NoLeadInterAmpers(opts);
// break;
// case '-':
// switch_csi_NoLeadInterDash(opts);
// break;
default:
warn_bad_csi();
}
break;
default:
warn_bad_csi();
}
}
/**
* CSI none Pm none key
* @param opts
*/
static inline void ICACHE_FLASH_ATTR
switch_csi_Plain(CSI_Data *opts)
{
char resp_buf[20];
int n1 = opts->n[0];
int n2 = opts->n[1];
// fix arguments (default values etc)
switch (opts->key) {
// Single argument, 1-based
case 'A': // up
case 'e': // down (old)
case 'B': // down
case 'a': // right (old)
case 'C': // right
case 'D': // left
case 'E': // cursor next line
case 'F': // cursor prev line
case 'b': // repeat last char
case 'G': // set X case 'G': // set X
case '`': case '`': // set X (alias)
case 'S': // scrolling
case 'T':
case 'X': // clear in line
case 'd': // set Y case 'd': // set Y
case 'L': case 'X': // clear in line
case 'M': case 'S': // scroll up
case '@': case 'T': // scroll down
case 'P': case 'L': // Insert lines
case 'I': case 'M': // Delete lines
case 'Z': case '@': // Insert in line
case 'P': // Delete in line
case 'I': // Tab forward
case 'Z': // Tab backward
if (n1 == 0) n1 = 1; if (n1 == 0) n1 = 1;
break; break;
case 'H': // Two arguments, 1-based
case 'H': // Absolute positioning
case 'f': case 'f':
if (n1 == 0) n1 = 1; if (n1 == 0) n1 = 1;
if (n2 == 0) n2 = 1; if (n2 == 0) n2 = 1;
break; break;
case 'J': // Erase modes 0,1,2
case 'K': case 'J': // Erase in screen
case 'K': // Erase in line
if (n1 > 2) n1 = 0; if (n1 > 2) n1 = 0;
break; break;
// No defaults
case 't': // Xterm window commands & reports
case 's': // Cursor save no attr
case 'r': // Set scrolling region
case 'u': // Cursor restore no attr
case 'h': // Option ON
case 'l': // Option OFF
case 'm': // SGR
case 'g': // Clear tabs
case 'n': // Queries 1 - device status
case 'c': // Queries 2 - primary DA
case 'x': // Queries 3 - DECREQTPARM
default: default:
// leave as is // leave as is
break; break;
} }
switch (keychar) { switch (opts->key) {
// CUU CUD CUF CUB // CUU CUD CUF CUB
case 'A': // Up case 'A': // Up
screen_cursor_move(-n1, 0, false); screen_cursor_move(-n1, 0, false);
@ -161,63 +264,15 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
// SU, SD - scroll up/down // SU, SD - scroll up/down
case 'S': case 'S':
if (leadchar == NUL && count <= 1) {
screen_scroll_up(n1); screen_scroll_up(n1);
}
else {
// other:
// CSI ? Pi; Pa; Pv S (sixel)
warn_bad_csi();
}
break; break;
case 'T': case 'T':
if (leadchar == NUL && count <= 1) {
// CSI Ps T
screen_scroll_down(n1); screen_scroll_down(n1);
}
else {
// other:
// CSI Ps ; Ps ; Ps ; Ps ; Ps T
// CSI > Ps; Ps T
warn_bad_csi();
}
break; break;
case 't': // xterm window commands case 't': // xterm window commands
if (leadchar == NUL && count <= 2) { do_csi_xterm_screen_cmd(opts);
// CSI Ps ; Ps ; Ps t
switch (n1) {
case 8: // set size
screen_resize(n2, n3);
break;
case 18: // report size
printf(buf, "\033[8;%d;%dt", termconf_scratch.height, termconf_scratch.width);
apars_respond(buf);
break;
case 21: // Report title
apars_respond("\033]L");
apars_respond(termconf_scratch.title);
apars_respond("\033\\");
break;
case 24: // Set Height only
screen_resize(n2, termconf_scratch.width);
break;
default:
ansi_noimpl("CSI %d t", n1);
break;
}
}
else {
// other:
// CSI > Ps; Ps t
// CSI Ps SP t,
warn_bad_csi();
}
break; break;
// CUP,HVP - set position // CUP,HVP - set position
@ -227,11 +282,6 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
break; // 1-based break; // 1-based
case 'J': // Erase screen case 'J': // Erase screen
if (leadchar == '?') {
// TODO selective erase
ansi_noimpl("Selective erase");
}
if (n1 == 0) { if (n1 == 0) {
screen_clear(CLEAR_FROM_CURSOR); screen_clear(CLEAR_FROM_CURSOR);
} else if (n1 == 1) { } else if (n1 == 1) {
@ -243,11 +293,6 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
break; break;
case 'K': // Erase lines case 'K': // Erase lines
if (leadchar == '?') {
// TODO selective erase
ansi_noimpl("Selective erase");
}
if (n1 == 0) { if (n1 == 0) {
screen_clear_line(CLEAR_FROM_CURSOR); screen_clear_line(CLEAR_FROM_CURSOR);
} else if (n1 == 1) { } else if (n1 == 1) {
@ -259,55 +304,25 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
// SCP, RCP - save/restore position // SCP, RCP - save/restore position
case 's': case 's':
if (leadchar == NUL && count == 0) {
screen_cursor_save(0); screen_cursor_save(0);
}
else if (leadchar == '?') {
// Save private attributes (CSI ? Pm h/l)
ansi_noimpl("Save private attrs");
apars_show_context();
}
else {
// other:
// CSI ? Pm s
// CSI Pl; Pr s
warn_bad_csi();
}
break; break;
case 'r': case 'r':
if (leadchar == NUL && (count == 2 || count == 0)) {
screen_set_scrolling_region(n1-1, n2-1); screen_set_scrolling_region(n1-1, n2-1);
}
else if (leadchar == '?') {
// Restore private attributes (CSI ? Pm h/l)
ansi_noimpl("Restore private attrs");
apars_show_context();
}
else {
// other:
// CSI ? Pm r
// CSI Pt; Pl; Pb; Pr; Ps$ r
warn_bad_csi();
}
break; break;
case 'u': case 'u':
if (leadchar == NUL && count == 0) {
screen_cursor_restore(0); screen_cursor_restore(0);
}
else {
warn_bad_csi();
}
break; break;
case 'h': // DEC feature enable case 'h': // DEC feature enable
case 'l': // DEC feature disable case 'l': // DEC feature disable
do_csi_privattr(&opts); // --- DEC standard attributes ---
do_csi_set_option(opts);
break; break;
case 'm': // SGR - set graphics rendition case 'm': // SGR - set graphics rendition
do_csi_sgr(&opts); do_csi_sgr(opts);
break; break;
case 'L': // Insert lines (shove down) case 'L': // Insert lines (shove down)
@ -343,31 +358,13 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
screen_tab_forward(n1); screen_tab_forward(n1);
break; break;
case 'p':
if (leadchar == '!') { // RIS
/* On real VT there are differences between soft and hard reset, we treat both equally */
screen_reset();
}
else {
warn_bad_csi();
}
break;
case 'n': // Queries case 'n': // Queries
if (leadchar == '>') {
// some xterm garbage - discard
// CSI > Ps n
ansi_noimpl("CSI > %d n", n1);
break;
}
if (leadchar == NUL) {
if (n1 == 6) { if (n1 == 6) {
// Query cursor position // Query cursor position
int x, y; int x, y;
screen_cursor_get(&y, &x); screen_cursor_get(&y, &x);
sprintf(buf, "\033[%d;%dR", y + 1, x + 1); sprintf(resp_buf, "\033[%d;%dR", y + 1, x + 1);
apars_respond(buf); apars_respond(resp_buf);
} }
else if (n1 == 5) { else if (n1 == 5) {
// Query device status - reply "Device is OK" // Query device status - reply "Device is OK"
@ -376,28 +373,115 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
else { else {
warn_bad_csi(); warn_bad_csi();
} }
} break;
else {
case 'c': // CSI-c - report capabilities
// Primary device attributes
apars_respond("\033[?64;22;9c"); // pretend we're vt420 with national character sets and colors.
break;
case 'x': // DECREQTPARM -> DECREPTPARM
do_csi_decreqtparm(opts);
break;
default:
warn_bad_csi(); warn_bad_csi();
} }
}
/**
* CSI none Pm ! key
*/
static inline void ICACHE_FLASH_ATTR
switch_csi_NoLeadInterBang(CSI_Data *opts)
{
switch(opts->key) {
case 'p':
// RIS - CSI ! p
// On real VT there are differences between soft and hard reset, we treat both equally
screen_reset();
break; break;
case 'c': // CSI-c - report capabilities default:
if (leadchar == NUL) { warn_bad_csi();
apars_respond("\033[?64;9c"); // pretend we're vt400 with national character sets
} }
else if (leadchar == '>') { }
// 41 - we're "VT400", 0 - ROM cartridge number
sprintf(buf, "\033[>41;%d;0c", FIRMWARE_VERSION_NUM);
apars_respond(buf); /**
* CSI > Pm inter key
*/
static inline void ICACHE_FLASH_ATTR
switch_csi_LeadGreater(CSI_Data *opts)
{
char resp_buf[20];
switch(opts->key) {
case 'c': // CSI > c - secondary device attributes query
// 41 - we're "VT400", FV wers, 0 - ROM cartridge number
sprintf(resp_buf, "\033[>41;%d;0c", FIRMWARE_VERSION_NUM);
apars_respond(resp_buf);
break;
default:
warn_bad_csi();
} }
else { }
/**
* CSI = Pm inter key
*/
static inline void ICACHE_FLASH_ATTR
switch_csi_LeadEquals(CSI_Data *opts)
{
char resp_buf[20];
u8 mac[6];
switch(opts->key) {
case 'c': // CSI = c - tertiary device attributes query
// report our unique ID number
wifi_get_macaddr(SOFTAP_IF, mac);
sprintf(resp_buf, "\033P!|%02X%02X%02X\033\\", mac[3], mac[4], mac[5]);
apars_respond(resp_buf);
break;
default:
warn_bad_csi(); warn_bad_csi();
} }
}
/**
* CSI ? Pm inter key
*/
static inline void ICACHE_FLASH_ATTR
switch_csi_LeadQuest(CSI_Data *opts)
{
switch(opts->key) {
case 's':
// Save private attributes
ansi_noimpl("Save private attrs");
apars_show_context(); // TODO priv attr s/r
break; break;
case 'x': // DECREQTPARM -> DECREPTPARM case 'r':
do_csi_decreqtparm(&opts); // Restore private attributes
ansi_noimpl("Restore private attrs");
apars_show_context(); // TODO priv attr s/r
break;
case 'J': // Erase screen selectively
// TODO selective erase
ansi_noimpl("Selective screen erase");
break;
case 'K': // Erase line selectively
// TODO selective erase
ansi_noimpl("Selective line erase");
break;
case 'l':
case 'h':
do_csi_set_private_option(opts);
break; break;
default: default:
@ -405,15 +489,95 @@ apars_handle_csi(char leadchar, const int *params, int count, char keychar)
} }
} }
/**
* CSI Pm m
* @param opts
*/
static inline void ICACHE_FLASH_ATTR
do_csi_sgr(CSI_Data *opts)
{
int count = opts->count;
if (count == 0) {
count = 1; // this makes it work as 0 (reset)
}
// iterate arguments
for (int i = 0; i < count; i++) {
int n = opts->n[i];
if (n == SGR_RESET) screen_reset_sgr();
// -- set color --
else if (n >= SGR_FG_START && n <= SGR_FG_END) screen_set_fg((Color) (n - SGR_FG_START)); // ANSI normal fg
else if (n >= SGR_BG_START && n <= SGR_BG_END) screen_set_bg((Color) (n - SGR_BG_START)); // ANSI normal bg
else if (n == SGR_FG_DEFAULT) screen_set_fg(termconf_scratch.default_fg); // default fg
else if (n == SGR_BG_DEFAULT) screen_set_bg(termconf_scratch.default_bg); // default bg
// -- set attr --
else if (n == SGR_BOLD) screen_set_sgr(ATTR_BOLD, 1);
else if (n == SGR_FAINT) screen_set_sgr(ATTR_FAINT, 1);
else if (n == SGR_ITALIC) screen_set_sgr(ATTR_ITALIC, 1);
else if (n == SGR_UNDERLINE) screen_set_sgr(ATTR_UNDERLINE, 1);
else if (n == SGR_BLINK || n == SGR_BLINK_FAST) screen_set_sgr(ATTR_BLINK, 1); // 6 - rapid blink, not supported
else if (n == SGR_STRIKE) screen_set_sgr(ATTR_STRIKE, 1);
else if (n == SGR_FRAKTUR) screen_set_sgr(ATTR_FRAKTUR, 1);
else if (n == SGR_INVERSE) screen_set_sgr_inverse(1);
// -- clear attr --
else if (n == SGR_OFF(SGR_BOLD)) screen_set_sgr(ATTR_BOLD, 0); // can also mean "Double Underline"
else if (n == SGR_OFF(SGR_FAINT)) screen_set_sgr(ATTR_FAINT | ATTR_BOLD, 0); // "normal"
else if (n == SGR_OFF(SGR_ITALIC)) screen_set_sgr(ATTR_ITALIC | ATTR_FRAKTUR, 0); // there is no dedicated OFF code for Fraktur
else if (n == SGR_OFF(SGR_UNDERLINE)) screen_set_sgr(ATTR_UNDERLINE, 0);
else if (n == SGR_OFF(SGR_BLINK)) screen_set_sgr(ATTR_BLINK, 0);
else if (n == SGR_OFF(SGR_STRIKE)) screen_set_sgr(ATTR_STRIKE, 0);
else if (n == SGR_OFF(SGR_INVERSE)) screen_set_sgr_inverse(0);
// -- AIX bright colors --
else if (n >= SGR_FG_BRT_START && n <= SGR_FG_BRT_END) screen_set_fg((Color) ((n - SGR_FG_BRT_START) + 8)); // AIX bright fg
else if (n >= SGR_BG_BRT_START && n <= SGR_BG_BRT_END) screen_set_bg((Color) ((n - SGR_BG_BRT_START) + 8)); // AIX bright bg
else {
ansi_noimpl("SGR %d", n);
}
}
}
/** /**
* CSI [?] Pm {h|l} * CSI Pm h or l
* @param opts * @param opts
*/ */
static void ICACHE_FLASH_ATTR do_csi_privattr(CSI_Data *opts) static inline void ICACHE_FLASH_ATTR
do_csi_set_option(CSI_Data *opts)
{
bool yn = (opts->key == 'h');
for (int i = 0; i < opts->count; i++) {
int n = opts->n[i];
if (n == 4) {
screen_set_insert_mode(yn);
}
else if (n == 12) {
// SRM is inverted, according to vt510 manual
termconf_scratch.loopback = !yn;
}
else if (n == 20) {
screen_set_newline_mode(yn);
}
else {
ansi_noimpl("OPTION %d", n);
}
}
}
/**
* CSI ? Pm h or l
* @param opts
*/
static inline void ICACHE_FLASH_ATTR
do_csi_set_private_option(CSI_Data *opts)
{ {
bool yn = (opts->key == 'h'); bool yn = (opts->key == 'h');
if (opts->lead == '?') {
// --- DEC private attributes --- // --- DEC private attributes ---
for (int i = 0; i < opts->count; i++) { for (int i = 0; i < opts->count; i++) {
int n = opts->n[i]; int n = opts->n[i];
@ -470,7 +634,11 @@ static void ICACHE_FLASH_ATTR do_csi_privattr(CSI_Data *opts)
else if (n == 1005) mouse_tracking.encoding = yn ? MTE_UTF8 : MTE_SIMPLE; else if (n == 1005) mouse_tracking.encoding = yn ? MTE_UTF8 : MTE_SIMPLE;
else if (n == 1006) mouse_tracking.encoding = yn ? MTE_SGR : MTE_SIMPLE; else if (n == 1006) mouse_tracking.encoding = yn ? MTE_SGR : MTE_SIMPLE;
else if (n == 1015) mouse_tracking.encoding = yn ? MTE_URXVT : MTE_SIMPLE; else if (n == 1015) mouse_tracking.encoding = yn ? MTE_URXVT : MTE_SIMPLE;
dbg("Mouse mode=%d, enc=%d, foctr=%d", mouse_tracking.mode, mouse_tracking.encoding, mouse_tracking.focus_tracking);
dbg("Mouse mode=%d, enc=%d, foctr=%d",
mouse_tracking.mode,
mouse_tracking.encoding,
mouse_tracking.focus_tracking);
} }
else if (n == 12) { else if (n == 12) {
// TODO Cursor blink on/off // TODO Cursor blink on/off
@ -516,19 +684,9 @@ static void ICACHE_FLASH_ATTR do_csi_privattr(CSI_Data *opts)
screen_cursor_restore(true); screen_cursor_restore(true);
} }
} }
else if (n >= 1050 && n <= 1053) {
// TODO Different kinds of function key emulation ?
// (In practice this seems hardly ever used)
// Ps = 1 0 5 0 -> Set terminfo/termcap function-key mode.
// Ps = 1 0 5 1 -> Set Sun function-key mode.
// Ps = 1 0 5 2 -> Set HP function-key mode.
// Ps = 1 0 5 3 -> Set SCO function-key mode.
ansi_noimpl("FN key emul type");
}
else if (n == 2004) { else if (n == 2004) {
// Bracketed paste mode // Bracketed paste mode
// Discard, we don't implement this ansi_noimpl("Bracketed paste");
} }
else if (n == 25) { else if (n == 25) {
screen_set_cursor_visible(yn); screen_set_cursor_visible(yn);
@ -542,89 +700,57 @@ static void ICACHE_FLASH_ATTR do_csi_privattr(CSI_Data *opts)
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
} }
else { else {
ansi_noimpl("CSI ? %d %c", n, opts->key); ansi_noimpl("?OPTION %d", n);
}
}
}
else {
// --- DEC standard attributes ---
for (int i = 0; i < opts->count; i++) {
int n = opts->n[i];
if (n == 4) {
screen_set_insert_mode(yn);
}
else if (n == 12) {
// SRM is inverted, according to vt510 manual
termconf_scratch.loopback = !yn;
}
else if (n == 20) {
screen_set_newline_mode(yn);
}
else {
ansi_noimpl("CSI %d %c", n, opts->key);
}
} }
} }
} }
/** /**
* CSI [ Pm m * CSI Ps ; Ps ; Ps t
* @param opts * @param opts
*/ */
static void ICACHE_FLASH_ATTR do_csi_sgr(CSI_Data *opts) static inline void ICACHE_FLASH_ATTR
do_csi_xterm_screen_cmd(CSI_Data *opts)
{ {
int count = opts->count; char resp_buf[20];
switch (opts->n[0]) {
case 8: // set size
screen_resize(opts->n[1], opts->n[2]);
break;
if (count == 0) { case 18: // Report the size of the text area in characters.
count = 1; // this makes it work as 0 (reset) case 19: // Report the size of the screen in characters.
} sprintf(resp_buf, "\033[8;%d;%dt", termconf_scratch.height, termconf_scratch.width);
apars_respond(resp_buf);
break;
if (opts->lead != NUL) { case 20: // Report icon
// some xterm garbage - discard case 21: // Report title
// CSI > Ps; Ps m apars_respond("\033]l");
return; apars_respond(termconf_scratch.title);
} apars_respond("\033\\");
break;
// iterate arguments case 22:
for (int i = 0; i < count; i++) { ansi_noimpl("Push title");
int n = opts->n[i]; break;
case 23:
ansi_noimpl("Pop title");
break;
if (n == SGR_RESET) screen_reset_sgr(); case 24: // Set Height only
// -- set color -- screen_resize(opts->n[1], termconf_scratch.width);
else if (n >= SGR_FG_START && n <= SGR_FG_END) screen_set_fg((Color) (n - SGR_FG_START)); // ANSI normal fg break;
else if (n >= SGR_BG_START && n <= SGR_BG_END) screen_set_bg((Color) (n - SGR_BG_START)); // ANSI normal bg
else if (n == SGR_FG_DEFAULT) screen_set_fg(termconf_scratch.default_fg); // default fg default:
else if (n == SGR_BG_DEFAULT) screen_set_bg(termconf_scratch.default_bg); // default bg ansi_noimpl("Xterm win report %d", opts->n[0]);
// -- set attr -- break;
else if (n == SGR_BOLD) screen_set_sgr(ATTR_BOLD, 1);
else if (n == SGR_FAINT) screen_set_sgr(ATTR_FAINT, 1);
else if (n == SGR_ITALIC) screen_set_sgr(ATTR_ITALIC, 1);
else if (n == SGR_UNDERLINE) screen_set_sgr(ATTR_UNDERLINE, 1);
else if (n == SGR_BLINK || n == SGR_BLINK_FAST) screen_set_sgr(ATTR_BLINK, 1); // 6 - rapid blink, not supported
else if (n == SGR_STRIKE) screen_set_sgr(ATTR_STRIKE, 1);
else if (n == SGR_FRAKTUR) screen_set_sgr(ATTR_FRAKTUR, 1);
else if (n == SGR_INVERSE) screen_set_sgr_inverse(1);
// -- clear attr --
else if (n == SGR_OFF(SGR_BOLD)) screen_set_sgr(ATTR_BOLD, 0); // can also mean "Double Underline"
else if (n == SGR_OFF(SGR_FAINT)) screen_set_sgr(ATTR_FAINT | ATTR_BOLD, 0); // "normal"
else if (n == SGR_OFF(SGR_ITALIC)) screen_set_sgr(ATTR_ITALIC | ATTR_FRAKTUR, 0); // there is no dedicated OFF code for Fraktur
else if (n == SGR_OFF(SGR_UNDERLINE)) screen_set_sgr(ATTR_UNDERLINE, 0);
else if (n == SGR_OFF(SGR_BLINK)) screen_set_sgr(ATTR_BLINK, 0);
else if (n == SGR_OFF(SGR_STRIKE)) screen_set_sgr(ATTR_STRIKE, 0);
else if (n == SGR_OFF(SGR_INVERSE)) screen_set_sgr_inverse(0);
// -- AIX bright colors --
else if (n >= SGR_FG_BRT_START && n <= SGR_FG_BRT_END) screen_set_fg((Color) ((n - SGR_FG_BRT_START) + 8)); // AIX bright fg
else if (n >= SGR_BG_BRT_START && n <= SGR_BG_BRT_END) screen_set_bg((Color) ((n - SGR_BG_BRT_START) + 8)); // AIX bright bg
else {
ansi_noimpl("SGR %d", n);
}
} }
} }
// data tables for the DECREPTPARM command response // data tables for the DECREPTPARM command response
struct DECREPTPARM_parity { int parity; const char * msg; }; struct DECREPTPARM_parity { int parity; const char * msg; };
static const struct DECREPTPARM_parity DECREPTPARM_parity_arr[] = { static const struct DECREPTPARM_parity DECREPTPARM_parity_arr[] = {
{PARITY_NONE, "1"}, {PARITY_NONE, "1"},
@ -655,10 +781,11 @@ static const struct DECREPTPARM_baud DECREPTPARM_baud_arr[] = {
}; };
/** /**
* CSI [ Ps x * CSI Ps x
* @param opts * @param opts
*/ */
static void ICACHE_FLASH_ATTR do_csi_decreqtparm(CSI_Data *opts) static inline void ICACHE_FLASH_ATTR
do_csi_decreqtparm(CSI_Data *opts)
{ {
const int n1 = opts->n[0]; const int n1 = opts->n[0];

@ -5,6 +5,6 @@
#ifndef ESP_VT100_FIRMWARE_APARS_CSI_H #ifndef ESP_VT100_FIRMWARE_APARS_CSI_H
#define ESP_VT100_FIRMWARE_APARS_CSI_H #define ESP_VT100_FIRMWARE_APARS_CSI_H
void apars_handle_csi(char leadchar, const int *params, int count, char keychar); void apars_handle_csi(char leadchar, const int *params, int count, char interchar, char keychar);
#endif //ESP_VT100_FIRMWARE_APARS_CSI_H #endif //ESP_VT100_FIRMWARE_APARS_CSI_H

@ -56,6 +56,9 @@ static struct {
bool newline_mode; //!< LNM - CR automatically sends LF bool newline_mode; //!< LNM - CR automatically sends LF
bool reverse; //!< DECSCNM - Reverse video bool reverse; //!< DECSCNM - Reverse video
bool insert_mode; //!< IRM - Insert mode (move rest of the line to the right)
bool cursor_visible; //!< DECTCEM - Cursor visible
// Vertical margin bounds (inclusive start/end of scrolling region) // Vertical margin bounds (inclusive start/end of scrolling region)
int vm0; int vm0;
int vm1; int vm1;
@ -64,6 +67,9 @@ static struct {
#define R0 scr.vm0 #define R0 scr.vm0
#define R1 scr.vm1 #define R1 scr.vm1
#define RH (scr.vm1 - scr.vm0 + 1) #define RH (scr.vm1 - scr.vm0 + 1)
// horizontal edges - will be useful if horizontal margin is implemented
#define C0 0
#define C1 (W-1)
typedef struct { typedef struct {
/* Cursor position */ /* Cursor position */
@ -84,12 +90,9 @@ typedef struct {
char charset0; char charset0;
char charset1; char charset1;
/** DEC private modes */ /** Options saved with cursor */
bool wraparound; //!< DECAWM - Wrapping when EOL bool auto_wrap; //!< DECAWM - Wrapping when EOL
bool origin_mode; //!< DECOM - absolute positioning is relative to vertical margins bool origin_mode; //!< DECOM - absolute positioning is relative to vertical margins
bool insert_mode; //!< IRM - Insert mode (move rest of the line to the right)
bool visible; //!< DECTCEM - Cursor visible
} CursorTypeDef; } CursorTypeDef;
/** /**
@ -246,18 +249,26 @@ cursor_reset(void)
cursor.x = 0; cursor.x = 0;
cursor.y = 0; cursor.y = 0;
cursor.hanging = false; cursor.hanging = false;
cursor.visible = true;
cursor.insert_mode = false;
cursor.origin_mode = false;
cursor.charsetN = 0; cursor.charsetN = 0;
cursor.charset0 = CS_B_USASCII; cursor.charset0 = CS_B_USASCII;
cursor.charset1 = CS_0_DEC_SUPPLEMENTAL; cursor.charset1 = CS_0_DEC_SUPPLEMENTAL;
cursor.wraparound = true;
screen_reset_sgr(); screen_reset_sgr();
} }
/**
* Reset the cursor position & colors
*/
static void ICACHE_FLASH_ATTR
decopt_reset(void)
{
scr.cursor_visible = true;
scr.insert_mode = false;
cursor.origin_mode = false;
cursor.auto_wrap = true;
}
/** /**
* Reset the cursor (\e[0m) * Reset the cursor (\e[0m)
*/ */
@ -279,6 +290,7 @@ screen_reset(void)
NOTIFY_LOCK(); NOTIFY_LOCK();
cursor_reset(); cursor_reset();
decopt_reset();
scr.numpad_alt_mode = false; scr.numpad_alt_mode = false;
scr.cursors_alt_mode = false; scr.cursors_alt_mode = false;
@ -774,6 +786,10 @@ screen_cursor_get(int *y, int *x)
{ {
*x = cursor.x; *x = cursor.x;
*y = cursor.y; *y = cursor.y;
if (cursor.origin_mode) {
*y -= R0;
}
} }
/** /**
@ -914,7 +930,7 @@ void ICACHE_FLASH_ATTR
screen_set_cursor_visible(bool visible) screen_set_cursor_visible(bool visible)
{ {
NOTIFY_LOCK(); NOTIFY_LOCK();
cursor.visible = visible; scr.cursor_visible = visible;
NOTIFY_DONE(); NOTIFY_DONE();
} }
@ -924,7 +940,7 @@ screen_set_cursor_visible(bool visible)
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
screen_wrap_enable(bool enable) screen_wrap_enable(bool enable)
{ {
cursor.wraparound = enable; cursor.auto_wrap = enable;
} }
/** /**
@ -964,19 +980,6 @@ screen_set_sgr_inverse(bool ena)
cursor.inverse = ena; cursor.inverse = ena;
} }
/**
* Check if coords are in range - used for verifying mouse clicks
*
* @param y
* @param x
* @return OK
*/
bool ICACHE_FLASH_ATTR
screen_isCoordValid(int y, int x)
{
return x >= 0 && y >= 0 && x < W && y < H;
}
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
screen_set_charset_n(int Gx) screen_set_charset_n(int Gx)
{ {
@ -994,7 +997,7 @@ screen_set_charset(int Gx, char charset)
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
screen_set_insert_mode(bool insert) screen_set_insert_mode(bool insert)
{ {
cursor.insert_mode = insert; scr.insert_mode = insert;
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -1099,7 +1102,7 @@ screen_putchar(const char *ch)
if (cursor.hanging) { if (cursor.hanging) {
// perform the scheduled wrap if hanging // perform the scheduled wrap if hanging
// if auto-wrap = off, it overwrites the last char // if auto-wrap = off, it overwrites the last char
if (cursor.wraparound) { if (cursor.auto_wrap) {
cursor.x = 0; cursor.x = 0;
cursor.y++; cursor.y++;
// Y wrap // Y wrap
@ -1116,7 +1119,7 @@ screen_putchar(const char *ch)
Cell *c = &screen[cursor.x + cursor.y * W]; Cell *c = &screen[cursor.x + cursor.y * W];
// move the rest of the line if we're in Insert Mode // move the rest of the line if we're in Insert Mode
if (cursor.x < W-1 && cursor.insert_mode) screen_insert_characters(1); if (cursor.x < W-1 && scr.insert_mode) screen_insert_characters(1);
if (ch[1] == 0 && ch[0] <= 0x7f) { if (ch[1] == 0 && ch[0] <= 0x7f) {
// we have len=1 and ASCII // we have len=1 and ASCII
@ -1289,7 +1292,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
encode2B((u16) cursor.y, &w3); encode2B((u16) cursor.y, &w3);
encode2B((u16) cursor.x, &w4); encode2B((u16) cursor.x, &w4);
encode2B((u16) ( encode2B((u16) (
(cursor.visible ? 1<<0 : 0) | (scr.cursor_visible ? 1<<0 : 0) |
(cursor.hanging ? 1<<1 : 0) | (cursor.hanging ? 1<<1 : 0) |
(scr.cursors_alt_mode ? 1<<2 : 0) | (scr.cursors_alt_mode ? 1<<2 : 0) |
(scr.numpad_alt_mode ? 1<<3 : 0) | (scr.numpad_alt_mode ? 1<<3 : 0) |

@ -271,8 +271,6 @@ void screen_fill_with_E(void);
// --- Queries --- // --- Queries ---
/** Check if coord is valid */
bool screen_isCoordValid(int y, int x);
/** 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);

@ -40,10 +40,10 @@ static void buf_pop(void *unused)
} }
} }
LOCAL void my_putc(char c) //LOCAL void my_putc(char c)
{ //{
UART_WriteCharCRLF(UART1, (u8) c, 10); // UART_WriteCharCRLF(UART1, (u8) c, 10);
} //}
/** /**
* Init the serial ports * Init the serial ports

@ -10,7 +10,7 @@
#define FW_V_PATCH 0 #define FW_V_PATCH 0
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH #define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH
#define FIRMWARE_VERSION_NUM (FW_V_MAJOR*10000 + FW_V_MINOR*100 + FW_V_PATCH) // this is used in ID queries #define FIRMWARE_VERSION_NUM (FW_V_MAJOR*1000 + FW_V_MINOR*10 + FW_V_PATCH) // this is used in ID queries
#define TERMINAL_GITHUB_REPO "https://github.com/MightyPork/ESPTerm" #define TERMINAL_GITHUB_REPO "https://github.com/MightyPork/ESPTerm"
#endif //ESP_VT100_FIRMWARE_VERSION_H #endif //ESP_VT100_FIRMWARE_VERSION_H

Loading…
Cancel
Save