tty: improvements (^V, fix nlcr behaviors, enter sends ^M)
This commit is contained in:
parent
a78ffc513f
commit
cc4874f90a
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user