tty: improvements (^V, fix nlcr behaviors, enter sends ^M)

This commit is contained in:
K. Lange 2018-10-26 10:15:16 +09:00
parent a78ffc513f
commit cc4874f90a
6 changed files with 83 additions and 28 deletions

View File

@ -108,6 +108,7 @@ static int show_settings(int all) {
print_cc(&t, "kill", VKILL, 21);
print_cc(&t, "eof", VEOF, 4);
print_cc(&t, "eol", VEOL, 0);
print_cc(&t, "lnext", VLNEXT, 22);
if (printed) { fprintf(stdout, "\n"); printed = 0; }
print_cc(&t, "start", VSTART, 17);
@ -241,6 +242,7 @@ int main(int argc, char * argv[]) {
t.c_cc[VSTOP] = 19; /* ^S */
t.c_cc[VSUSP] = 26; /* ^Z */
t.c_cc[VTIME] = 0;
t.c_cc[VLNEXT] = 22; /* ^V */
}
set_char("eof", VEOF);
@ -252,6 +254,7 @@ int main(int argc, char * argv[]) {
set_char("start", VSTART);
set_char("stop", VSTOP);
set_char("susp", VSUSP);
set_char("lnext", VLNEXT);
set_cflag("parenb", PARENB);

View File

@ -881,6 +881,13 @@ void key_event(int ret, key_event_t * event) {
handle_input_s("\033[Z");
return;
}
/* ENTER = reads as linefeed, should be carriage return */
if (event->keycode == 10) {
handle_input('\r');
return;
}
handle_input(event->key);
} else {
if (event->action == KEY_ACTION_UP) return;

View File

@ -1654,6 +1654,12 @@ static void key_event(int ret, key_event_t * event) {
return;
}
/* ENTER = reads as linefeed, should be carriage return */
if (event->keycode == 10) {
handle_input('\r');
return;
}
/* Pass key value to PTY */
handle_input(event->key);
} else {

View File

@ -33,6 +33,8 @@ typedef struct pty {
void (*write_in)(struct pty *, uint8_t);
void (*write_out)(struct pty *, uint8_t);
int next_is_verbatim;
} pty_t;
void tty_output_process_slave(pty_t * pty, uint8_t c);

View File

@ -34,6 +34,7 @@ typedef unsigned char cc_t;
#define VSTOP 9 /* ^S stop input */
#define VSUSP 10 /* ^Z suspend foreground applicatioan (send SIGTSTP) */
#define VTIME 11 /* Timeout for non-canonical read, deciseconds */
#define VLNEXT 12 /* ^V literal next */
/* flags for input modes */
#define BRKINT 0000001

View File

@ -78,7 +78,7 @@ void tty_output_process(pty_t * pty, uint8_t c) {
output_process_slave(pty, c);
}
static void erase_one(pty_t * pty) {
static void erase_one(pty_t * pty, int erase) {
if (pty->canon_buflen > 0) {
/* How many do we backspace? */
int vwidth = 1;
@ -88,17 +88,35 @@ static void erase_one(pty_t * pty) {
vwidth = 2;
}
pty->canon_buffer[pty->canon_buflen] = '\0';
if ((pty->tios.c_lflag & ECHO) && (pty->tios.c_lflag & ECHOE)) {
for (int i = 0; i < vwidth; ++i) {
output_process(pty, '\010');
output_process(pty, ' ');
output_process(pty, '\010');
if (pty->tios.c_lflag & ECHO) {
if (erase) {
for (int i = 0; i < vwidth; ++i) {
output_process(pty, '\010');
output_process(pty, ' ');
output_process(pty, '\010');
}
}
}
}
}
void tty_input_process(pty_t * pty, uint8_t c) {
if (pty->next_is_verbatim) {
pty->next_is_verbatim = 0;
if (pty->canon_buflen < pty->canon_bufsize) {
pty->canon_buffer[pty->canon_buflen] = c;
pty->canon_buflen++;
}
if (pty->tios.c_lflag & ECHO) {
if (c < ' ') {
output_process(pty, '^');
output_process(pty, '@'+c);
} else {
output_process(pty, c);
}
}
return;
}
if (pty->tios.c_lflag & ISIG) {
if (c == pty->tios.c_cc[VINTR]) {
if (pty->tios.c_lflag & ECHO) {
@ -131,16 +149,51 @@ void tty_input_process(pty_t * pty, uint8_t c) {
/* VSTOP, VSTART */
}
#endif
/* ISTRIP: Strip eighth bit */
if (pty->tios.c_iflag & ISTRIP) {
c &= 0x7F;
}
/* IGNCR: Ignore carriage return. */
if ((pty->tios.c_iflag & IGNCR) && c == '\r') {
return;
}
if ((pty->tios.c_iflag & INLCR) && c == '\n') {
/* INLCR: Translate NL to CR. */
c = '\r';
} else if ((pty->tios.c_iflag & ICRNL) && c == '\r') {
/* ICRNL: Convert carriage return. */
c = '\n';
}
if (pty->tios.c_lflag & ICANON) {
if (c == pty->tios.c_cc[VLNEXT] && (pty->tios.c_lflag & IEXTEN)) {
pty->next_is_verbatim = 1;
output_process(pty, '^');
output_process(pty, '\010');
return;
}
if (c == pty->tios.c_cc[VKILL]) {
while (pty->canon_buflen > 0) {
erase_one(pty);
erase_one(pty, pty->tios.c_lflag & ECHOK);
}
if ((pty->tios.c_lflag & ECHO) && ! (pty->tios.c_lflag & ECHOK)) {
output_process(pty, '^');
output_process(pty, '@' + c);
}
return;
}
if (c == pty->tios.c_cc[VERASE]) {
/* Backspace */
erase_one(pty);
erase_one(pty, pty->tios.c_lflag & ECHOE);
if ((pty->tios.c_lflag & ECHO) && ! (pty->tios.c_lflag & ECHOE)) {
output_process(pty, '^');
output_process(pty, '@' + c);
}
return;
}
if (c == pty->tios.c_cc[VEOF]) {
@ -152,26 +205,6 @@ void tty_input_process(pty_t * pty, uint8_t c) {
return;
}
/* ISTRIP: Strip eighth bit */
if (pty->tios.c_iflag & ISTRIP) {
c &= 0x7F;
}
/* IGNCR: Ignore carriage return. */
if ((pty->tios.c_iflag & IGNCR) && c == '\r') {
return;
}
/* INLCR: Translate NL to CR. */
if ((pty->tios.c_iflag & INLCR) && c == '\n') {
c = '\r';
}
/* ICRNL: Convert carriage return. */
if ((pty->tios.c_iflag & ICRNL) && c == '\r') {
c = '\n';
}
if (pty->canon_buflen < pty->canon_bufsize) {
pty->canon_buffer[pty->canon_buflen] = c;
pty->canon_buflen++;
@ -593,6 +626,8 @@ pty_t * pty_new(struct winsize * size) {
pty_t * pty = malloc(sizeof(pty_t));
pty->next_is_verbatim = 0;
/* stdin linkage; characters from terminal → PTY slave */
pty->in = ring_buffer_create(TTY_BUFFER_SIZE);
pty->out = ring_buffer_create(TTY_BUFFER_SIZE);
@ -640,6 +675,7 @@ pty_t * pty_new(struct winsize * size) {
pty->tios.c_cc[VSTOP] = 19; /* ^S */
pty->tios.c_cc[VSUSP] = 26; /* ^Z */
pty->tios.c_cc[VTIME] = 0;
pty->tios.c_cc[VLNEXT] = 22; /* ^V */
pty->canon_buffer = malloc(TTY_BUFFER_SIZE);
pty->canon_bufsize = TTY_BUFFER_SIZE-2;