insert mode

pull/111/merge
Ondřej Hruška 7 years ago
parent ca410736f7
commit 89fca5c40a
  1. 79
      user/ansi_parser_callbacks.c
  2. 136
      user/screen.c
  3. 10
      user/screen.h

@ -65,10 +65,12 @@ apars_handle_plainchar(char c)
}
else {
if (c == 14) {
// ShiftIN
screen_set_charset_n(1);
return;
}
if (c == 15) {
// ShiftOUT
screen_set_charset_n(0);
return;
}
@ -97,6 +99,7 @@ apars_handle_characterSet(char leadchar, char c)
{
if (leadchar == '(') screen_set_charset(0, c);
else if (leadchar == ')') screen_set_charset(1, c);
// other alternatives * + . - / not implemented
}
void ICACHE_FLASH_ATTR
@ -119,6 +122,7 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
int n2 = params[1];
int n3 = params[2];
static char buf[20];
bool yn = 0; // for ? l h
// defaults
switch (keychar) {
@ -224,7 +228,6 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
case 'n': // queries
if (n1 == 6) {
// Query cursor position
char buf[20];
int x, y;
screen_cursor_get(&y, &x);
sprintf(buf, "\033[%d;%dR", y+1, x+1);
@ -242,43 +245,31 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
// DECTCEM feature enable / disable
case 'h': // feature enable
if (leadchar == '?') {
if (n1 == 25) screen_cursor_enable(1);
else if (n1 == 7) screen_wrap_enable(1);
else if (n1 == 1) {
// TODO something with arrow keys??
}
else {
ansi_warn("NOIMPL DEC opt %d", n1);
}
}
else {
if (n1 == 4) {
// TODO insert mode, i think this is to suppress user input
}
else {
ansi_warn("NOIMPL flag %d", n1);
}
}
break;
yn = 1;
case 'l': // feature disable
if (leadchar == '?') {
if (n1 == 25) screen_cursor_enable(0);
else if (n1 == 7) screen_wrap_enable(0);
else if (n1 == 1) {
// TODO see above
}
else {
ansi_warn("NOIMPL DEC opt %d", n1);
}
}
else {
if (n1 == 4) {
// TODO see above
for (int i = 0; i < count; i++) {
int n = params[i];
if (leadchar == '?') {
if (n == 25) {
screen_cursor_enable(yn);
}
else if (n == 7) {
screen_wrap_enable(yn);
}
else if (n == 1) {
screen_set_cursor_application_mode(yn);
}
else {
ansi_warn("NOIMPL DEC opt %d", n);
}
}
else {
ansi_warn("NOIMPL flag %d", n1);
if (n == 4) {
screen_set_insert_mode(yn);
}
else {
ansi_warn("NOIMPL flag %d", n);
}
}
}
break;
@ -320,7 +311,7 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
else if (n >= 90 && n <= 97) screen_set_fg((Color) (n - 90 + 8)); // AIX bright fg
else if (n >= 100 && n <= 107) screen_set_bg((Color) (n - 100 + 8)); // AIX bright bg
else {
ansi_warn("NOIMPL SGR attr %d", n);
ansi_warn("NOIMPL SGR attr %d", n);
}
}
break;
@ -379,19 +370,14 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
ansi_warn("NOIMPL cursor back tab");
break;
case 'q':
// TODO setmode (??)
ansi_warn("NOIMPL CSI setmode %d", n1);
break;
case 'p':
if (leadchar == '!') {
info("SOFT RESET!");
system_restart();
screen_reset(); // TODO do soft reset
}
break;
case 'c':
case 'c': // CSI-c
// report capabilities (pretend we're vt4xx)
UART_WriteString(UART0, "\033[?64;22;c", UART_TIMEOUT_US);
break;
@ -449,17 +435,16 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c)
// ansi_warn("NOIMPL set tab");
break;
// TODO those don't seem to do anything
case '>':
// ansi_warn("NOIMPL NUMKP");
screen_set_keypad_application_mode(false);
break;
case '<':
// ansi_warn("NOIMPL SETANSI");
// "Enter ANSI / VT100 mode" - no-op
break;
case '=':
// ansi_warn("NOIMPL ALTKP");
screen_set_keypad_application_mode(true);
break;
default:

@ -14,44 +14,6 @@ static void utf8_remap(char* out, char g, char table);
#define W termconf_scratch.width
#define H termconf_scratch.height
/**
* Restore hard defaults
*/
void terminal_restore_defaults(void)
{
termconf->default_bg = 0;
termconf->default_fg = 7;
termconf->width = 26;
termconf->height = 10;
termconf->parser_tout_ms = 10;
sprintf(termconf->title, "ESPTerm");
for(int i=1; i <= 5; i++) {
sprintf(termconf->btn[i-1], "%d", i);
}
}
/**
* Apply settings after eg. restore from defaults
*/
void terminal_apply_settings(void)
{
terminal_apply_settings_noclear();
screen_init();
}
void terminal_apply_settings_noclear(void)
{
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
if (W*H >= MAX_SCREEN_SIZE) {
error("BAD SCREEN SIZE: %d rows x %d cols", H, W);
error("reverting terminal settings to default");
terminal_restore_defaults();
persist_store();
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
screen_init();
}
}
/**
* Highest permissible value of the color attribute
*/
@ -79,6 +41,12 @@ static struct {
int x; //!< X coordinate
int y; //!< Y coordinate
bool autowrap; //!< Wrapping when EOL
bool insert_mode; //!< Insert mode (move rest of the line to the right)
// TODO use those for input processing
bool kp_alternate; //!< Application Mode - affects how user input of control keys is sent
bool curs_alternate; //!< Application mode for cursor keys
bool visible; //!< Visible (not attribute, DEC special)
bool inverse;
u8 attrs;
@ -121,6 +89,45 @@ static volatile int notifyLock = 0;
if (notifyLock == 0) screen_notifyChange(CHANGE_CONTENT); \
} while(0)
/**
* Restore hard defaults
*/
void terminal_restore_defaults(void)
{
termconf->default_bg = 0;
termconf->default_fg = 7;
termconf->width = 26;
termconf->height = 10;
termconf->parser_tout_ms = 10;
sprintf(termconf->title, "ESPTerm");
for(int i=1; i <= 5; i++) {
sprintf(termconf->btn[i-1], "%d", i);
}
}
/**
* Apply settings after eg. restore from defaults
*/
void terminal_apply_settings(void)
{
terminal_apply_settings_noclear();
screen_init();
}
/** this is used when changing terminal settings that do not affect the screen size */
void terminal_apply_settings_noclear(void)
{
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
if (W*H >= MAX_SCREEN_SIZE) {
error("BAD SCREEN SIZE: %d rows x %d cols", H, W);
error("reverting terminal settings to default");
terminal_restore_defaults();
persist_store();
memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle));
screen_init();
}
}
/**
* Clear range, inclusive
*/
@ -151,6 +158,8 @@ clear_range(unsigned int from, unsigned int to)
static void ICACHE_FLASH_ATTR
cursor_reset(void)
{
// TODO this should probably be public and invoked by "soft reset"
cursor.x = 0;
cursor.y = 0;
cursor.fg = termconf_scratch.default_fg;
@ -158,6 +167,10 @@ cursor_reset(void)
cursor.visible = 1;
cursor.autowrap = 1;
cursor.attrs = 0;
cursor.insert_mode = 0;
cursor.kp_alternate = 0;
cursor.curs_alternate = 0;
cursor.charset0 = 'B';
cursor.charset1 = '0';
@ -657,13 +670,27 @@ void ICACHE_FLASH_ATTR screen_set_charset(int Gx, char charset)
if (Gx == 1) cursor.charset1 = charset;
}
void ICACHE_FLASH_ATTR screen_set_insert_mode(bool insert)
{
cursor.insert_mode = insert;
}
void ICACHE_FLASH_ATTR screen_set_keypad_application_mode(bool app_mode)
{
cursor.kp_alternate = app_mode;
}
void ICACHE_FLASH_ATTR screen_set_cursor_application_mode(bool app_mode)
{
cursor.curs_alternate = app_mode;
}
/**
* Set a character in the cursor color, move to right with wrap.
*/
void ICACHE_FLASH_ATTR
screen_putchar(const char *ch)
{
char buf[4];
NOTIFY_LOCK();
Cell *c = &screen[cursor.x + cursor.y * W];
@ -681,18 +708,13 @@ screen_putchar(const char *ch)
case 8: // BS
if (cursor.x > 0) {
cursor.x--;
} else {
// wrap around start of line
if (cursor.autowrap && cursor.y>0) {
cursor.x=W-1;
cursor.y--;
}
}
// apparently backspace should not clear the cell
// we should not wrap around
// and apparently backspace should not even clear the cell
goto done;
case 9: // TAB
// TODO change if tab setting is ever implemented
// TODO change to "go to next tab stop"
if (cursor.x<((W-1)-(W-1)%4)) {
c->c[0] = ' ';
c->c[1] = 0;
@ -712,6 +734,9 @@ screen_putchar(const char *ch)
}
}
// 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 (ch[1] == 0 && ch[0] <= 0x7f) {
// we have len=1 and ASCII
utf8_remap(c->c, ch[0], (cursor.charsetN == 0) ? cursor.charset0 : cursor.charset1);
@ -801,29 +826,36 @@ utf8_remap(char *out, char g, char table)
utf = vt100_to_unicode[g - 0x41];
}
break;
case 'A': /* UK, replaces # with GBP */
if (g == '#') utf = 0x20a4;
break;
default:
// no remap
utf = (unsigned char)g;
break;
}
// Encode to UTF-8
if (utf > 0x7F) {
// formulas taken from: https://gist.github.com/yamamushi/5823402
if ((utf >= 0x80) && (utf <= 0x07FF)) {
// 2-byte unicode
out[0] = (char) ((utf >> 0x06) ^ 0xC0);
out[1] = (char) (((utf ^ 0xFFC0) | 0x80) & ~0x40);
out[2]=0;
}
else if ((utf >= 0x0800) && (utf <= 0xFFFF)) {
else {
// 3-byte unicode
out[0] = (char) (((utf ^ 0xFC0FFF) >> 0x0C) | 0xE0);
out[1] = (char) ((((utf ^ 0xFFF03F) >> 0x06) | 0x80) & ~0x40);
out[2] = (char) (((utf ^ 0xFFFC0) | 0x80) & ~0x40);
out[3]=0;
} else {
out[0] = g;
out[1] = 0;
}
} else {
out[0] = g;
// low ASCII
out[0] = (char) utf;
out[1] = 0;
}
}

@ -172,10 +172,18 @@ void screen_set_fg(Color color);
/** Set cursor background coloor */
void screen_set_bg(Color color);
// enable or disable attrs by bitmask
/** enable attrs by bitmask */
void screen_attr_enable(u8 attrs);
/** disable attrs by bitmask */
void screen_attr_disable(u8 attrs);
/** Set the inverse cursor attribute */
void screen_inverse_enable(bool ena);
/** Toggle INSERT / REPLACE */
void screen_set_insert_mode(bool insert);
/** Toggle application keypad mode */
void screen_set_keypad_application_mode(bool app_mode);
/** Toggle application cursor mode */
void screen_set_cursor_application_mode(bool app_mode);
void screen_set_charset_n(int Gx);
void screen_set_charset(int Gx, char charset);

Loading…
Cancel
Save