mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
[mouse] Decode ESC [ < . Refs #246
It is based on links code. Was not tested too much.
This commit is contained in:
parent
61ceecdbd8
commit
e4fb9a80df
@ -733,70 +733,20 @@ free_and_return:
|
|||||||
free_itrm(itrm);
|
free_itrm(itrm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
/** Parse an ECMA-48 control sequence that was received from a
|
get_esc_code(unsigned char *str, int len, unsigned char *code, int *num, int *el)
|
||||||
* terminal. Extract the Final Byte (if there are no Intermediate
|
|
||||||
* Bytes) and the value of the first parameter (if it is an integer).
|
|
||||||
*
|
|
||||||
* This function assumes the control sequence begins with a CSI -
|
|
||||||
* CONTROL SEQUENCE INTRODUCER encoded as ESC [. (ECMA-48 also allows
|
|
||||||
* 0x9B as a single-byte CSI, but we don't support that here.)
|
|
||||||
*
|
|
||||||
* @returns one of:
|
|
||||||
* - -1 if the control sequence is not yet complete; the caller sets a timer.
|
|
||||||
* - 0 if the control sequence does not comply with ECMA-48.
|
|
||||||
* - The length of the control sequence otherwise. */
|
|
||||||
static inline int
|
|
||||||
get_esc_code(unsigned char *str, int len, char *final_byte,
|
|
||||||
int *first_param_value)
|
|
||||||
{
|
{
|
||||||
const int parameter_pos = 2;
|
|
||||||
int intermediate_pos;
|
|
||||||
int final_pos;
|
|
||||||
int pos;
|
int pos;
|
||||||
|
*num = 0;
|
||||||
*final_byte = '\0';
|
for (pos = 2; pos < len; pos++) {
|
||||||
*first_param_value = 0;
|
if (str[pos] < '0' || str[pos] > '9' || pos > 7) {
|
||||||
|
*el = pos + 1;
|
||||||
/* Parameter Bytes */
|
*code = str[pos];
|
||||||
pos = parameter_pos;
|
|
||||||
while (pos < len && str[pos] >= 0x30 && str[pos] <= 0x3F)
|
|
||||||
++pos;
|
|
||||||
|
|
||||||
/* Intermediate Bytes */
|
|
||||||
intermediate_pos = pos;
|
|
||||||
while (pos < len && str[pos] >= 0x20 && str[pos] <= 0x2F)
|
|
||||||
++pos;
|
|
||||||
|
|
||||||
/* Final Byte */
|
|
||||||
final_pos = pos;
|
|
||||||
if (pos >= len)
|
|
||||||
return -1;
|
|
||||||
if (!(str[pos] >= 0x40 && str[pos] <= 0x7E))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
/* The control sequence seems OK. If the first Parameter
|
*num = *num * 10 + str[pos] - '0';
|
||||||
* Byte indicates that the parameter string is formatted
|
}
|
||||||
* as specified in clause 5.4.2 of ECMA-48, and the first
|
return -1;
|
||||||
* parameter is an integer, then compute its value.
|
|
||||||
* (We need not check @len here because the loop cannot get
|
|
||||||
* past the Final Byte.) */
|
|
||||||
for (pos = parameter_pos; str[pos] >= 0x30 && str[pos] <= 0x39; ++pos)
|
|
||||||
*first_param_value = *first_param_value * 10 + str[pos] - 0x30;
|
|
||||||
/* If the first parameter contains an embedded separator, then
|
|
||||||
* the value is not an integer, so discard what we computed. */
|
|
||||||
if (str[pos] == 0x3A)
|
|
||||||
*first_param_value = 0;
|
|
||||||
|
|
||||||
/* The meaning of the Final Byte depends on the Intermediate
|
|
||||||
* Bytes. Because we don't currently need to recognize any
|
|
||||||
* control sequences that use Intermediate Bytes, we just
|
|
||||||
* discard the Final Byte if there are any Intermediate
|
|
||||||
* Bytes. */
|
|
||||||
if (intermediate_pos == final_pos)
|
|
||||||
*final_byte = str[final_pos];
|
|
||||||
|
|
||||||
return final_pos + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Define it to dump queue content in a readable form,
|
/* Define it to dump queue content in a readable form,
|
||||||
@ -830,9 +780,10 @@ static int
|
|||||||
decode_terminal_escape_sequence(struct itrm *itrm, struct interlink_event *ev)
|
decode_terminal_escape_sequence(struct itrm *itrm, struct interlink_event *ev)
|
||||||
{
|
{
|
||||||
struct term_event_keyboard kbd = { KBD_UNDEF, KBD_MOD_NONE };
|
struct term_event_keyboard kbd = { KBD_UNDEF, KBD_MOD_NONE };
|
||||||
char c;
|
unsigned char c;
|
||||||
int v;
|
int v;
|
||||||
int el;
|
int el;
|
||||||
|
int res;
|
||||||
|
|
||||||
if (itrm->in.queue.len == 2 && itrm->in.queue.data[1] == ASCII_ESC && get_ui_double_esc()) {
|
if (itrm->in.queue.len == 2 && itrm->in.queue.data[1] == ASCII_ESC && get_ui_double_esc()) {
|
||||||
kbd.key = KBD_ESC;
|
kbd.key = KBD_ESC;
|
||||||
@ -857,8 +808,9 @@ decode_terminal_escape_sequence(struct itrm *itrm, struct interlink_event *ev)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
el = get_esc_code(itrm->in.queue.data, itrm->in.queue.len, &c, &v);
|
res = get_esc_code(itrm->in.queue.data, itrm->in.queue.len, &c, &v, &el);
|
||||||
if (el == -1) {
|
|
||||||
|
if (res == -1) {
|
||||||
/* If the control sequence is incomplete but itrm->in.queue
|
/* If the control sequence is incomplete but itrm->in.queue
|
||||||
* is already full, then we must not wait for more input:
|
* is already full, then we must not wait for more input:
|
||||||
* kbd_timeout might call in_kbd and thus process_input
|
* kbd_timeout might call in_kbd and thus process_input
|
||||||
@ -982,6 +934,12 @@ decode_terminal_escape_sequence(struct itrm *itrm, struct interlink_event *ev)
|
|||||||
case 'M': /* (DL) kmous xterm */
|
case 'M': /* (DL) kmous xterm */
|
||||||
#ifdef CONFIG_MOUSE
|
#ifdef CONFIG_MOUSE
|
||||||
el = decode_terminal_mouse_escape_sequence(itrm, ev, el, v);
|
el = decode_terminal_mouse_escape_sequence(itrm, ev, el, v);
|
||||||
|
#endif /* CONFIG_MOUSE */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<': /* (DL) kmous xterm */
|
||||||
|
#ifdef CONFIG_MOUSE
|
||||||
|
el = decode_terminal_mouse_escape_sequence_256(itrm, ev, el, v);
|
||||||
#endif /* CONFIG_MOUSE */
|
#endif /* CONFIG_MOUSE */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ extern struct itrm *ditrm;
|
|||||||
|
|
||||||
|
|
||||||
#define INIT_TWIN_MOUSE_SEQ "\033[?9h" /**< Send MIT Mouse Row & Column on Button Press */
|
#define INIT_TWIN_MOUSE_SEQ "\033[?9h" /**< Send MIT Mouse Row & Column on Button Press */
|
||||||
#define INIT_XWIN_MOUSE_SEQ "\033[?1000h" /**< Send Mouse X & Y on button press and release */
|
#define INIT_XWIN_MOUSE_SEQ "\033[?1000h\033[?1002h\033[?1005l\033[?1015l\033[?1006h" /**< Send Mouse X & Y on button press and release */
|
||||||
|
|
||||||
void
|
void
|
||||||
send_mouse_init_sequence(int h)
|
send_mouse_init_sequence(int h)
|
||||||
@ -60,7 +60,7 @@ send_mouse_init_sequence(int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define DONE_TWIN_MOUSE_SEQ "\033[?9l" /**< Don't Send MIT Mouse Row & Column on Button Press */
|
#define DONE_TWIN_MOUSE_SEQ "\033[?9l" /**< Don't Send MIT Mouse Row & Column on Button Press */
|
||||||
#define DONE_XWIN_MOUSE_SEQ "\033[?1000l" /**< Don't Send Mouse X & Y on button press and release */
|
#define DONE_XWIN_MOUSE_SEQ "\033[?1000l\033[?1002l\033[?1006l" /**< Don't Send Mouse X & Y on button press and release */
|
||||||
|
|
||||||
void
|
void
|
||||||
send_mouse_done_sequence(int h)
|
send_mouse_done_sequence(int h)
|
||||||
@ -152,13 +152,14 @@ decode_mouse_position(struct itrm *itrm, int from)
|
|||||||
#define TW_BUTT_MIDDLE 2
|
#define TW_BUTT_MIDDLE 2
|
||||||
#define TW_BUTT_RIGHT 4
|
#define TW_BUTT_RIGHT 4
|
||||||
|
|
||||||
|
static int xterm_button = -1;
|
||||||
|
|
||||||
/** @returns length of the escape sequence or -1 if the caller needs to set up
|
/** @returns length of the escape sequence or -1 if the caller needs to set up
|
||||||
* the ESC delay timer. */
|
* the ESC delay timer. */
|
||||||
int
|
int
|
||||||
decode_terminal_mouse_escape_sequence(struct itrm *itrm, struct interlink_event *ev,
|
decode_terminal_mouse_escape_sequence(struct itrm *itrm, struct interlink_event *ev,
|
||||||
int el, int v)
|
int el, int v)
|
||||||
{
|
{
|
||||||
static int xterm_button = -1;
|
|
||||||
struct interlink_event_mouse mouse;
|
struct interlink_event_mouse mouse;
|
||||||
|
|
||||||
if (itrm->in.queue.len - el < 3)
|
if (itrm->in.queue.len - el < 3)
|
||||||
@ -236,3 +237,71 @@ decode_terminal_mouse_escape_sequence(struct itrm *itrm, struct interlink_event
|
|||||||
|
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
decode_terminal_mouse_escape_sequence_256(struct itrm *itrm, struct interlink_event *ev,
|
||||||
|
int el, int v)
|
||||||
|
{
|
||||||
|
struct interlink_event_mouse mouse;
|
||||||
|
/* SGR 1006 mouse extension: \e[<b;x;yM where b, x and y are in decimal, no longer offset by 32,
|
||||||
|
and the trailing letter is 'm' instead of 'M' for mouse release so that the released button is reported. */
|
||||||
|
int eel;
|
||||||
|
int x = 0, y = 0, b = 0;
|
||||||
|
unsigned char ch = 0;
|
||||||
|
eel = el;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (el == itrm->in.queue.len) return -1;
|
||||||
|
if (el - eel >= 9) return el;
|
||||||
|
ch = itrm->in.queue.data[el++];
|
||||||
|
if (ch == ';') break;
|
||||||
|
if (ch < '0' || ch > '9') return el;
|
||||||
|
b = 10 * b + (ch - '0');
|
||||||
|
}
|
||||||
|
eel = el;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (el == itrm->in.queue.len) return -1;
|
||||||
|
if (el - eel >= 9) return el;
|
||||||
|
ch = itrm->in.queue.data[el++];
|
||||||
|
if (ch == ';') break;
|
||||||
|
if (ch < '0' || ch > '9') return el;
|
||||||
|
x = 10 * x + (ch - '0');
|
||||||
|
}
|
||||||
|
eel = el;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (el == itrm->in.queue.len) return -1;
|
||||||
|
if (el - eel >= 9) return el;
|
||||||
|
ch = itrm->in.queue.data[el++];
|
||||||
|
if (ch == 'M' || ch == 'm') break;
|
||||||
|
if (ch < '0' || ch > '9') return el;
|
||||||
|
y = 10 * y + (ch - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse.x = x - 1;
|
||||||
|
mouse.y = y - 1;
|
||||||
|
|
||||||
|
if (ch == 'm') mouse.button = B_UP;
|
||||||
|
else if ((b & 0x20) == 0x20) mouse.button = B_DRAG, b &= ~0x20;
|
||||||
|
else mouse.button = B_DOWN;
|
||||||
|
|
||||||
|
if (b == 0) mouse.button |= B_LEFT;
|
||||||
|
else if (b == 1) mouse.button |= B_MIDDLE;
|
||||||
|
else if (b == 2) mouse.button |= B_RIGHT;
|
||||||
|
else if (b == 3 && xterm_button >= 0) mouse.button |= xterm_button;
|
||||||
|
else if (b == 0x40) mouse.button |= B_WHEEL_UP;
|
||||||
|
else if (b == 0x41) mouse.button |= B_WHEEL_DOWN;
|
||||||
|
|
||||||
|
|
||||||
|
xterm_button = -1;
|
||||||
|
if (mouse_action_is(&mouse, B_DOWN)) {
|
||||||
|
xterm_button = mouse_get_button(&mouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Postpone changing of the event type until all sanity
|
||||||
|
* checks have been done. */
|
||||||
|
set_mouse_interlink_event(ev, mouse.x, mouse.y, mouse.button);
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
@ -126,6 +126,7 @@ void disable_mouse(void);
|
|||||||
void enable_mouse(void);
|
void enable_mouse(void);
|
||||||
void toggle_mouse(struct session *ses);
|
void toggle_mouse(struct session *ses);
|
||||||
int decode_terminal_mouse_escape_sequence(struct itrm *itrm, struct interlink_event *ev, int el, int v);
|
int decode_terminal_mouse_escape_sequence(struct itrm *itrm, struct interlink_event *ev, int el, int v);
|
||||||
|
int decode_terminal_mouse_escape_sequence_256(struct itrm *itrm, struct interlink_event *ev, int el, int v);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user