summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/cli_readline.c98
1 files changed, 67 insertions, 31 deletions
diff --git a/common/cli_readline.c b/common/cli_readline.c
index c1476e4..ecded11 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -283,46 +283,82 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len,
* handle standard linux xterm esc sequences for arrow key, etc.
*/
if (esc_len != 0) {
+ enum { ESC_REJECT, ESC_SAVE, ESC_CONVERTED } act = ESC_REJECT;
+
if (esc_len == 1) {
- if (ichar == '[') {
- esc_save[esc_len] = ichar;
- esc_len = 2;
- } else {
- cread_add_str(esc_save, esc_len,
- insert, &num, &eol_num,
- buf, *len);
- esc_len = 0;
+ if (ichar == '[' || ichar == 'O')
+ act = ESC_SAVE;
+ } else if (esc_len == 2) {
+ switch (ichar) {
+ case 'D': /* <- key */
+ ichar = CTL_CH('b');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^B handler */
+ case 'C': /* -> key */
+ ichar = CTL_CH('f');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^F handler */
+ case 'H': /* Home key */
+ ichar = CTL_CH('a');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^A handler */
+ case 'F': /* End key */
+ ichar = CTL_CH('e');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^E handler */
+ case 'A': /* up arrow */
+ ichar = CTL_CH('p');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^P handler */
+ case 'B': /* down arrow */
+ ichar = CTL_CH('n');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^N handler */
+ case '1':
+ case '3':
+ case '4':
+ case '7':
+ case '8':
+ if (esc_save[1] == '[') {
+ /* see if next character is ~ */
+ act = ESC_SAVE;
+ }
+ break;
+ }
+ } else if (esc_len == 3) {
+ if (ichar == '~') {
+ switch (esc_save[2]) {
+ case '3': /* Delete key */
+ ichar = CTL_CH('d');
+ act = ESC_CONVERTED;
+ break; /* pass to ^D handler */
+ case '1': /* Home key */
+ case '7':
+ ichar = CTL_CH('a');
+ act = ESC_CONVERTED;
+ break; /* pass to ^A handler */
+ case '4': /* End key */
+ case '8':
+ ichar = CTL_CH('e');
+ act = ESC_CONVERTED;
+ break; /* pass to ^E handler */
+ }
}
- continue;
}
- switch (ichar) {
- case 'D': /* <- key */
- ichar = CTL_CH('b');
- esc_len = 0;
- break;
- case 'C': /* -> key */
- ichar = CTL_CH('f');
- esc_len = 0;
- break; /* pass off to ^F handler */
- case 'H': /* Home key */
- ichar = CTL_CH('a');
- esc_len = 0;
- break; /* pass off to ^A handler */
- case 'A': /* up arrow */
- ichar = CTL_CH('p');
- esc_len = 0;
- break; /* pass off to ^P handler */
- case 'B': /* down arrow */
- ichar = CTL_CH('n');
- esc_len = 0;
- break; /* pass off to ^N handler */
- default:
+ switch (act) {
+ case ESC_SAVE:
+ esc_save[esc_len++] = ichar;
+ continue;
+ case ESC_REJECT:
esc_save[esc_len++] = ichar;
cread_add_str(esc_save, esc_len, insert,
&num, &eol_num, buf, *len);
esc_len = 0;
continue;
+ case ESC_CONVERTED:
+ esc_len = 0;
+ break;
}
}