edit: Clean up escape code parser
This commit is contained in:
parent
0bee81352f
commit
42034d6f60
1 changed files with 225 additions and 117 deletions
238
src/utils/edit.c
238
src/utils/edit.c
|
@ -464,6 +464,14 @@ enum edit_key_code {
|
|||
EDIT_KEY_ALT_DOWN,
|
||||
EDIT_KEY_ALT_RIGHT,
|
||||
EDIT_KEY_ALT_LEFT,
|
||||
EDIT_KEY_SHIFT_UP,
|
||||
EDIT_KEY_SHIFT_DOWN,
|
||||
EDIT_KEY_SHIFT_RIGHT,
|
||||
EDIT_KEY_SHIFT_LEFT,
|
||||
EDIT_KEY_ALT_SHIFT_UP,
|
||||
EDIT_KEY_ALT_SHIFT_DOWN,
|
||||
EDIT_KEY_ALT_SHIFT_RIGHT,
|
||||
EDIT_KEY_ALT_SHIFT_LEFT,
|
||||
EDIT_KEY_EOF
|
||||
};
|
||||
|
||||
|
@ -475,37 +483,9 @@ static void show_esc_buf(const char *esc_buf, char c, int i)
|
|||
}
|
||||
|
||||
|
||||
static enum edit_key_code edit_read_key(int sock)
|
||||
static enum edit_key_code esc_seq_to_key1_no(char last)
|
||||
{
|
||||
int c;
|
||||
unsigned char buf[1];
|
||||
int res;
|
||||
static int esc = -1;
|
||||
static char esc_buf[6];
|
||||
|
||||
res = read(sock, buf, 1);
|
||||
if (res < 0)
|
||||
perror("read");
|
||||
if (res <= 0)
|
||||
return EDIT_KEY_EOF;
|
||||
|
||||
c = buf[0];
|
||||
|
||||
if (esc >= 0) {
|
||||
if (esc == 5) {
|
||||
show_esc_buf(esc_buf, c, 0);
|
||||
esc = -1;
|
||||
} else {
|
||||
esc_buf[esc++] = c;
|
||||
esc_buf[esc] = '\0';
|
||||
if (esc == 1)
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (esc == 2 && esc_buf[0] == '[' && c >= 'A' && c <= 'Z') {
|
||||
esc = -1;
|
||||
switch (c) {
|
||||
switch (last) {
|
||||
case 'A':
|
||||
return EDIT_KEY_UP;
|
||||
case 'B':
|
||||
|
@ -515,37 +495,31 @@ static enum edit_key_code edit_read_key(int sock)
|
|||
case 'D':
|
||||
return EDIT_KEY_LEFT;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 1);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (esc > 1 && esc_buf[0] == '[') {
|
||||
if ((c >= '0' && c <= '9') || c == ';')
|
||||
return EDIT_KEY_NONE;
|
||||
|
||||
esc = -1;
|
||||
|
||||
if (esc_buf[1] == '1' && esc_buf[2] == ';' &&
|
||||
esc_buf[3] == '5') {
|
||||
switch (esc_buf[4]) {
|
||||
static enum edit_key_code esc_seq_to_key1_shift(char last)
|
||||
{
|
||||
switch (last) {
|
||||
case 'A':
|
||||
return EDIT_KEY_CTRL_UP;
|
||||
return EDIT_KEY_SHIFT_UP;
|
||||
case 'B':
|
||||
return EDIT_KEY_CTRL_DOWN;
|
||||
return EDIT_KEY_SHIFT_DOWN;
|
||||
case 'C':
|
||||
return EDIT_KEY_CTRL_RIGHT;
|
||||
return EDIT_KEY_SHIFT_RIGHT;
|
||||
case 'D':
|
||||
return EDIT_KEY_CTRL_LEFT;
|
||||
return EDIT_KEY_SHIFT_LEFT;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 2);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (esc_buf[1] == '1' && esc_buf[2] == ';' &&
|
||||
esc_buf[3] == '3') {
|
||||
switch (esc_buf[4]) {
|
||||
|
||||
static enum edit_key_code esc_seq_to_key1_alt(char last)
|
||||
{
|
||||
switch (last) {
|
||||
case 'A':
|
||||
return EDIT_KEY_ALT_UP;
|
||||
case 'B':
|
||||
|
@ -555,14 +529,68 @@ static enum edit_key_code edit_read_key(int sock)
|
|||
case 'D':
|
||||
return EDIT_KEY_ALT_LEFT;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 7);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '~':
|
||||
switch (atoi(&esc_buf[1])) {
|
||||
|
||||
static enum edit_key_code esc_seq_to_key1_alt_shift(char last)
|
||||
{
|
||||
switch (last) {
|
||||
case 'A':
|
||||
return EDIT_KEY_ALT_SHIFT_UP;
|
||||
case 'B':
|
||||
return EDIT_KEY_ALT_SHIFT_DOWN;
|
||||
case 'C':
|
||||
return EDIT_KEY_ALT_SHIFT_RIGHT;
|
||||
case 'D':
|
||||
return EDIT_KEY_ALT_SHIFT_LEFT;
|
||||
default:
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum edit_key_code esc_seq_to_key1_ctrl(char last)
|
||||
{
|
||||
switch (last) {
|
||||
case 'A':
|
||||
return EDIT_KEY_CTRL_UP;
|
||||
case 'B':
|
||||
return EDIT_KEY_CTRL_DOWN;
|
||||
case 'C':
|
||||
return EDIT_KEY_CTRL_RIGHT;
|
||||
case 'D':
|
||||
return EDIT_KEY_CTRL_LEFT;
|
||||
default:
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static enum edit_key_code esc_seq_to_key1(int param1, int param2, char last)
|
||||
{
|
||||
/* ESC-[<param1>;<param2><last> */
|
||||
|
||||
if (param1 < 0 && param2 < 0)
|
||||
return esc_seq_to_key1_no(last);
|
||||
|
||||
if (param1 == 1 && param2 == 2)
|
||||
return esc_seq_to_key1_shift(last);
|
||||
|
||||
if (param1 == 1 && param2 == 3)
|
||||
return esc_seq_to_key1_alt(last);
|
||||
|
||||
if (param1 == 1 && param2 == 4)
|
||||
return esc_seq_to_key1_alt_shift(last);
|
||||
|
||||
if (param1 == 1 && param2 == 5)
|
||||
return esc_seq_to_key1_ctrl(last);
|
||||
|
||||
if (param2 < 0) {
|
||||
if (last != '~')
|
||||
return EDIT_KEY_NONE;
|
||||
switch (param1) {
|
||||
case 2:
|
||||
return EDIT_KEY_INSERT;
|
||||
case 3:
|
||||
|
@ -587,20 +615,21 @@ static enum edit_key_code edit_read_key(int sock)
|
|||
return EDIT_KEY_F11;
|
||||
case 24:
|
||||
return EDIT_KEY_F12;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 3);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 4);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (esc > 1 && esc_buf[0] == 'O') {
|
||||
esc = -1;
|
||||
switch (esc_buf[1]) {
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
|
||||
|
||||
static enum edit_key_code esc_seq_to_key2(int param1, int param2, char last)
|
||||
{
|
||||
/* ESC-O<param1>;<param2><last> */
|
||||
|
||||
if (param1 >= 0 || param2 >= 0)
|
||||
return EDIT_KEY_NONE;
|
||||
|
||||
switch (last) {
|
||||
case 'F':
|
||||
return EDIT_KEY_END;
|
||||
case 'H':
|
||||
|
@ -614,14 +643,93 @@ static enum edit_key_code edit_read_key(int sock)
|
|||
case 'S':
|
||||
return EDIT_KEY_F4;
|
||||
default:
|
||||
show_esc_buf(esc_buf, c, 5);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (esc > 1) {
|
||||
|
||||
static enum edit_key_code esc_seq_to_key(char *seq)
|
||||
{
|
||||
char last, *pos;
|
||||
int param1 = -1, param2 = -1;
|
||||
enum edit_key_code ret = EDIT_KEY_NONE;
|
||||
|
||||
for (pos = seq; *pos; pos++)
|
||||
last = *pos;
|
||||
|
||||
if (seq[1] >= '0' && seq[1] <= '9') {
|
||||
param1 = atoi(&seq[1]);
|
||||
pos = os_strchr(seq, ';');
|
||||
if (pos)
|
||||
param2 = atoi(pos + 1);
|
||||
}
|
||||
|
||||
if (seq[0] == '[')
|
||||
ret = esc_seq_to_key1(param1, param2, last);
|
||||
else if (seq[0] == 'O')
|
||||
ret = esc_seq_to_key2(param1, param2, last);
|
||||
|
||||
if (ret != EDIT_KEY_NONE)
|
||||
return ret;
|
||||
|
||||
edit_clear_line();
|
||||
printf("\rUnknown escape sequence '%s'\n", seq);
|
||||
edit_redraw();
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
|
||||
|
||||
static enum edit_key_code edit_read_key(int sock)
|
||||
{
|
||||
int c;
|
||||
unsigned char buf[1];
|
||||
int res;
|
||||
static int esc = -1;
|
||||
static char esc_buf[7];
|
||||
|
||||
res = read(sock, buf, 1);
|
||||
if (res < 0)
|
||||
perror("read");
|
||||
if (res <= 0)
|
||||
return EDIT_KEY_EOF;
|
||||
|
||||
c = buf[0];
|
||||
|
||||
if (esc >= 0) {
|
||||
if (c == 27 /* ESC */) {
|
||||
esc = 0;
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
|
||||
if (esc == 6) {
|
||||
show_esc_buf(esc_buf, c, 0);
|
||||
esc = -1;
|
||||
} else {
|
||||
esc_buf[esc++] = c;
|
||||
esc_buf[esc] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (esc == 1) {
|
||||
if (esc_buf[0] != '[' && esc_buf[0] != 'O') {
|
||||
show_esc_buf(esc_buf, c, 1);
|
||||
esc = -1;
|
||||
return EDIT_KEY_NONE;
|
||||
} else
|
||||
return EDIT_KEY_NONE; /* Escape sequence continues */
|
||||
}
|
||||
|
||||
if (esc > 1) {
|
||||
if ((c >= '0' && c <= '9') || c == ';')
|
||||
return EDIT_KEY_NONE; /* Escape sequence continues */
|
||||
|
||||
if (c == '~' || (c >= 'A' && c <= 'Z')) {
|
||||
esc = -1;
|
||||
return esc_seq_to_key(esc_buf);
|
||||
}
|
||||
|
||||
show_esc_buf(esc_buf, c, 2);
|
||||
esc = -1;
|
||||
show_esc_buf(esc_buf, c, 6);
|
||||
return EDIT_KEY_NONE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue