Make mode 1015 and 1006 work, prepare for 1005

This commit is contained in:
Přemysl Eric Janouch 2014-10-13 23:36:14 +02:00
parent 456093e4ed
commit e330d751a4
4 changed files with 144 additions and 43 deletions

View File

@ -221,12 +221,12 @@ handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
{
// rxvt protocol
key->type = TERMKEY_TYPE_MOUSE;
key->code.mouse[0] = arg[0];
key->code.mouse.info = arg[0] - 0x20;
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
key->code.mouse[0] &= ~0x1c;
key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
key->code.mouse.info &= ~0x1c;
termkey_key_set_linecol (key, arg[1], arg[2]);
termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
return TERMKEY_RES_KEY;
}
@ -234,15 +234,15 @@ handle_csi_m (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
{
// SGR protocol
key->type = TERMKEY_TYPE_MOUSE;
key->code.mouse[0] = arg[0];
key->code.mouse.info = arg[0];
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
key->code.mouse[0] &= ~0x1c;
key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
key->code.mouse.info &= ~0x1c;
termkey_key_set_linecol (key, arg[1], arg[2]);
termkey_key_set_linecol (key, arg[2] - 1, arg[1] - 1);
if (cmd == 'm') // release
key->code.mouse[3] |= 0x80;
key->code.mouse.info |= 0x8000;
return TERMKEY_RES_KEY;
}
return TERMKEY_RES_NONE;
@ -267,7 +267,7 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
return TERMKEY_RES_KEY;
int btn = 0;
int code = key->code.mouse[0];
int code = key->code.mouse.info;
int drag = code & 0x20;
code &= ~0x3c;
@ -297,7 +297,7 @@ termkey_interpret_mouse (termkey_t *tk, const termkey_key_t *key,
if (button)
*button = btn;
if (key->code.mouse[3] & 0x80)
if (key->code.mouse.info & 0x8000)
*event = TERMKEY_MOUSE_RELEASE;
return TERMKEY_RES_KEY;
}
@ -355,10 +355,9 @@ handle_csi_y (termkey_t *tk, termkey_key_t *key, int cmd, long *arg, int args)
return TERMKEY_RES_NONE;
key->type = TERMKEY_TYPE_MODEREPORT;
key->code.mouse[0] = (cmd >> 8);
key->code.mouse[1] = arg[0] >> 8;
key->code.mouse[2] = arg[0] & 0xff;
key->code.mouse[3] = arg[1];
key->code.mode.initial = (cmd >> 8);
key->code.mode.mode = arg[0];
key->code.mode.value = arg[1];
return TERMKEY_RES_KEY;
default:
@ -376,11 +375,11 @@ termkey_interpret_modereport (termkey_t *tk,
return TERMKEY_RES_NONE;
if (initial)
*initial = key->code.mouse[0];
*initial = key->code.mode.initial;
if (mode)
*mode = (key->code.mouse[1] << 8) | key->code.mouse[2];
*mode = key->code.mode.mode;
if (value)
*value = key->code.mouse[3];
*value = key->code.mode.value;
return TERMKEY_RES_KEY;
}
@ -616,7 +615,7 @@ peekkey_csi (termkey_t *tk, termkey_csi_t *csi,
return TERMKEY_RES_KEY;
}
// Mouse in X10 encoding consumes the next 3 bytes also
// Mouse in X10 encoding consumes the next 3 bytes also (or more with 1005)
if (cmd == 'M' && args < 3)
{
tk->buffstart += csi_len;

View File

@ -86,26 +86,23 @@ static inline void
termkey_key_get_linecol (const termkey_key_t *key, int *line, int *col)
{
if (col)
*col = ((unsigned char) key->code.mouse[1]
| ((unsigned char) key->code.mouse[3] & 0x0f) << 8) - 1;
*col = key->code.mouse.x;
if (line)
*line = ((unsigned char) key->code.mouse[2]
| ((unsigned char) key->code.mouse[3] & 0x70) << 4) - 1;
*line = key->code.mouse.y;
}
static inline void
termkey_key_set_linecol (termkey_key_t *key, int line, int col)
{
if (++line > 0xfff)
line = 0xfff;
if (line > UINT16_MAX)
line = UINT16_MAX;
if (++col > 0x7ff)
col = 0x7ff;
if (col > UINT16_MAX)
col = UINT16_MAX;
key->code.mouse[1] = (line & 0x0ff);
key->code.mouse[2] = (col & 0x0ff);
key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
key->code.mouse.x = col;
key->code.mouse.y = line;
}
extern termkey_driver_t termkey_driver_csi;

View File

@ -966,22 +966,121 @@ peekkey_simple (termkey_t *tk, termkey_key_t *key, int force, size_t *nbytep)
}
}
// XXX: With the current infrastructure I'm not sure how to properly handle
// this. peekkey() isn't made for skipping invalid inputs.
#define INVALID_1005 0x20
static termkey_result_t
parse_1005_value (const unsigned char **bytes, size_t *len, uint32_t *cp)
{
unsigned int nbytes;
unsigned char b0 = (*bytes)[0];
if (b0 < 0x80)
{
// Single byte ASCII
*cp = b0;
nbytes = 1;
goto end;
}
else if (b0 < 0xc0)
{
// Starts with a continuation byte - that's not right
*cp = INVALID_1005;
nbytes = 1;
goto end;
}
else if (b0 < 0xe0)
{
nbytes = 2;
*cp = b0 & 0x1f;
}
else if (b0 < 0xf0)
{
nbytes = 3;
*cp = b0 & 0x0f;
}
else if (b0 < 0xf8)
{
nbytes = 4;
*cp = b0 & 0x07;
}
else if (b0 < 0xfc)
{
nbytes = 5;
*cp = b0 & 0x03;
}
else if (b0 < 0xfe)
{
nbytes = 6;
*cp = b0 & 0x01;
}
else
{
*cp = INVALID_1005;
nbytes = 1;
goto end;
}
for (unsigned int b = 1; b < nbytes; b++)
{
if (b >= *len)
return TERMKEY_RES_AGAIN;
unsigned char cb = (*bytes)[b];
if (cb < 0x80 || cb >= 0xc0)
{
*cp = INVALID_1005;
nbytes = b;
goto end;
}
*cp <<= 6;
*cp |= cb & 0x3f;
}
end:
(*bytes) += nbytes;
(*len) -= nbytes;
return TERMKEY_RES_KEY;
}
static termkey_result_t
peekkey_mouse (termkey_t *tk, termkey_key_t *key, size_t *nbytep)
{
if (tk->buffcount < 3)
return TERMKEY_RES_AGAIN;
uint32_t b, x, y;
// TODO: Add some API to switch on 1005 mode support
if (false)
{
const unsigned char *buff = tk->buffer + tk->buffstart;
size_t len = tk->buffcount;
if (parse_1005_value (&buff, &len, &b) == TERMKEY_RES_AGAIN
|| parse_1005_value (&buff, &len, &x) == TERMKEY_RES_AGAIN
|| parse_1005_value (&buff, &len, &y) == TERMKEY_RES_AGAIN)
return TERMKEY_RES_AGAIN;
*nbytep = tk->buffcount - len;
}
else
{
if (tk->buffcount < 3)
return TERMKEY_RES_AGAIN;
b = CHARAT (0);
x = CHARAT (1);
y = CHARAT (2);
*nbytep = 3;
}
key->type = TERMKEY_TYPE_MOUSE;
key->code.mouse[0] = CHARAT (0) - 0x20;
key->code.mouse[1] = CHARAT (1) - 0x20;
key->code.mouse[2] = CHARAT (2) - 0x20;
key->code.mouse[3] = 0;
key->code.mouse.info = b - 0x20;
key->code.mouse.x = x - 0x20 - 1;
key->code.mouse.y = y - 0x20 - 1;
key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
key->code.mouse[0] &= ~0x1c;
key->modifiers = (key->code.mouse.info & 0x1c) >> 2;
key->code.mouse.info &= ~0x1c;
*nbytep = 3;
return TERMKEY_RES_KEY;
}
@ -1525,7 +1624,8 @@ termkey_keycmp (termkey_t *tk,
break;
case TERMKEY_TYPE_MOUSE:
{
int cmp = strncmp (key1.code.mouse, key2.code.mouse, 4);
int cmp = memcmp (&key1.code.mouse, &key2.code.mouse,
sizeof key1.code.mouse);
if (cmp != 0)
return cmp;
break;

View File

@ -137,9 +137,14 @@ struct termkey_key
uint32_t codepoint; /* TERMKEY_TYPE_KEY */
int number; /* TERMKEY_TYPE_FUNCTION */
termkey_sym_t sym; /* TERMKEY_TYPE_KEYSYM */
// TODO: rewrite this insanity
char mouse[4]; /* TERMKEY_TYPE_MOUSE */
/* opaque, see termkey_interpret_mouse() */
/* TERMKEY_TYPE_MODEREPORT */
/* opaque, see termkey_interpret_modereport() */
struct { char initial; int mode, value; } mode;
/* TERMKEY_TYPE_MOUSE */
/* opaque, see termkey_interpret_mouse() */
struct { uint16_t x, y, info; } mouse;
} code;
int modifiers;