Handle ANSI and DEC mode report CSIs
This commit is contained in:
parent
c00f6cd3c6
commit
0be6f18019
15
demo.c
15
demo.c
|
@ -68,6 +68,18 @@ int main(int argc, char *argv[])
|
||||||
termkey_interpret_position(tk, &key, &line, &col);
|
termkey_interpret_position(tk, &key, &line, &col);
|
||||||
printf("Cursor position report at line=%d, col=%d\n", line, col);
|
printf("Cursor position report at line=%d, col=%d\n", line, col);
|
||||||
}
|
}
|
||||||
|
else if(key.type == TERMKEY_TYPE_MODEREPORT) {
|
||||||
|
int initial, mode, value;
|
||||||
|
termkey_interpret_modereport(tk, &key, &initial, &mode, &value);
|
||||||
|
printf("Mode report %s mode %d = %d\n", initial ? "DEC" : "ANSI", mode, value);
|
||||||
|
}
|
||||||
|
else if(key.type == TERMKEY_TYPE_UNKNOWN_CSI) {
|
||||||
|
long args[16];
|
||||||
|
size_t nargs = 16;
|
||||||
|
unsigned long command;
|
||||||
|
termkey_interpret_csi(tk, &key, args, &nargs, &command);
|
||||||
|
printf("Unrecognised CSI %c %ld;%ld %c%c\n", (char)(command >> 8), args[0], args[1], (char)(command >> 16), (char)command);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
printf("%s\n", buffer);
|
printf("%s\n", buffer);
|
||||||
}
|
}
|
||||||
|
@ -80,7 +92,8 @@ int main(int argc, char *argv[])
|
||||||
if(key.type == TERMKEY_TYPE_UNICODE &&
|
if(key.type == TERMKEY_TYPE_UNICODE &&
|
||||||
key.modifiers == 0 &&
|
key.modifiers == 0 &&
|
||||||
key.code.codepoint == '?') {
|
key.code.codepoint == '?') {
|
||||||
printf("\033[?6n");
|
// printf("\033[?6n"); // DECDSR 6 == request cursor position
|
||||||
|
printf("\033[?1$p"); // DECRQM == request mode, DEC origin mode
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
43
driver-csi.c
43
driver-csi.c
|
@ -287,6 +287,47 @@ TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int
|
||||||
return TERMKEY_RES_KEY;
|
return TERMKEY_RES_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for CSI $y mode status reports
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TermKeyResult handle_csi_y(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
|
||||||
|
{
|
||||||
|
switch(cmd) {
|
||||||
|
case 'y'|'$'<<16:
|
||||||
|
case 'y'|'$'<<16 | '?'<<8:
|
||||||
|
if(args < 2)
|
||||||
|
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];
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return TERMKEY_RES_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value)
|
||||||
|
{
|
||||||
|
if(key->type != TERMKEY_TYPE_MODEREPORT)
|
||||||
|
return TERMKEY_RES_NONE;
|
||||||
|
|
||||||
|
if(initial)
|
||||||
|
*initial = key->code.mouse[0];
|
||||||
|
|
||||||
|
if(mode)
|
||||||
|
*mode = (key->code.mouse[1] << 8) | key->code.mouse[2];
|
||||||
|
|
||||||
|
if(value)
|
||||||
|
*value = key->code.mouse[3];
|
||||||
|
|
||||||
|
return TERMKEY_RES_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
|
||||||
|
|
||||||
static TermKeyResult parse_csi(TermKey *tk, size_t introlen, size_t *csi_len, long args[], size_t *nargs, unsigned long *commandp)
|
static TermKeyResult parse_csi(TermKey *tk, size_t introlen, size_t *csi_len, long args[], size_t *nargs, unsigned long *commandp)
|
||||||
|
@ -450,6 +491,8 @@ static int register_keys(void)
|
||||||
|
|
||||||
csi_handlers['R' - 0x40] = &handle_csi_R;
|
csi_handlers['R' - 0x40] = &handle_csi_R;
|
||||||
|
|
||||||
|
csi_handlers['y' - 0x40] = &handle_csi_y;
|
||||||
|
|
||||||
keyinfo_initialised = 1;
|
keyinfo_initialised = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,9 @@ a mouse button press, release, or movement. The \fIcode.mouse\fP array should be
|
||||||
.B TERMKEY_TYPE_POSITION
|
.B TERMKEY_TYPE_POSITION
|
||||||
a cursor position report. The structure should be considered opaque; \fBtermkey_interpret_position\fP(3) may be used to interpret it.
|
a cursor position report. The structure should be considered opaque; \fBtermkey_interpret_position\fP(3) may be used to interpret it.
|
||||||
.TP
|
.TP
|
||||||
|
.B TERMKEY_TYPE_MODEREPORT
|
||||||
|
an ANSI or DEC mode value report. The structure should be considered opaque; \fBtermkey_interpret_modereport\fP(3) may be used to interpret it.
|
||||||
|
.TP
|
||||||
.B TERMKEY_TYPE_UNKNOWN_CSI
|
.B TERMKEY_TYPE_UNKNOWN_CSI
|
||||||
an unrecognised CSI sequence. The structure should be considered opaque; \fBtermkey_interpret_csi\fP(3) may be used to interpret it.
|
an unrecognised CSI sequence. The structure should be considered opaque; \fBtermkey_interpret_csi\fP(3) may be used to interpret it.
|
||||||
.PP
|
.PP
|
||||||
|
@ -133,6 +136,8 @@ protocol (\f(CWCSI M\fP followed by three bytes),
|
||||||
encoding (\f(CWCSI < ... M\fP, as requested by \f(CWCSI ? 1006 h\fP), and rxvt encoding (\f(CWCSI ... M\fP, as requested by \f(CWCSI ? 1015 h\fP). Which encoding is in use is inferred automatically by \fBtermkey\fP, and does not need to be specified explicitly.
|
encoding (\f(CWCSI < ... M\fP, as requested by \f(CWCSI ? 1006 h\fP), and rxvt encoding (\f(CWCSI ... M\fP, as requested by \f(CWCSI ? 1015 h\fP). Which encoding is in use is inferred automatically by \fBtermkey\fP, and does not need to be specified explicitly.
|
||||||
.SS Position Events
|
.SS Position Events
|
||||||
The \fBTERMKEY_TYPE_POSITION\fP event type indicates a cursor position report. This is typically sent by a terminal in response to the Report Cursor Position command (\f(CWCSI ? 6 n\fP). The event bytes are opaque, but can be obtained by calling \fBtermkey_interpret_position\fP(3) passing the event structure and pointers to integers to store the result in. Note that only a DEC CPR sequence (\f(CWCSI ? R\fP) is recognised, and not the non-DEC prefixed \f(CWCSI R\fP because the latter could be interpreted as the \f(CWF3\fP function key instead.
|
The \fBTERMKEY_TYPE_POSITION\fP event type indicates a cursor position report. This is typically sent by a terminal in response to the Report Cursor Position command (\f(CWCSI ? 6 n\fP). The event bytes are opaque, but can be obtained by calling \fBtermkey_interpret_position\fP(3) passing the event structure and pointers to integers to store the result in. Note that only a DEC CPR sequence (\f(CWCSI ? R\fP) is recognised, and not the non-DEC prefixed \f(CWCSI R\fP because the latter could be interpreted as the \f(CWF3\fP function key instead.
|
||||||
|
.SS Mode Reports
|
||||||
|
The \fBTERMKEY_TYPE_MODEREPORT\fP event type indicates an ANSI or DEC mode report. This is typically sent by a terminal in response to the Request Mode command (\f(CWCSI $p\fP or \f(CWCSI ? $p\fP). The event bytes are opaque, but can be obtained by calling \fBtermkey_interpret_modereport\fP(3) passing the event structure and pointers to integers to store the result in.
|
||||||
.SS Unrecognised CSIs
|
.SS Unrecognised CSIs
|
||||||
The \fBTERMKEY_TYPE_UNKNOWN_CSI\fP event type indicates a CSI sequence that the \fBtermkey\fP does not recognise. It will have been extracted from the stream, but is available to the application to inspect by calling \fBtermkey_interpret_csi\fP(3). It is important that if the application wishes to inspect this sequence it is done immediately, before any other IO operations on the \fBtermkey\fP instance (specifically, before calling \fBtermkey_waitkey\fP() or \fBtermkey_getkey\fP() again), otherwise the buffer space consumed by the sequence will be overwritten.
|
The \fBTERMKEY_TYPE_UNKNOWN_CSI\fP event type indicates a CSI sequence that the \fBtermkey\fP does not recognise. It will have been extracted from the stream, but is available to the application to inspect by calling \fBtermkey_interpret_csi\fP(3). It is important that if the application wishes to inspect this sequence it is done immediately, before any other IO operations on the \fBtermkey\fP instance (specifically, before calling \fBtermkey_waitkey\fP() or \fBtermkey_getkey\fP() again), otherwise the buffer space consumed by the sequence will be overwritten.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
.TH TERMKEY_INTERPRET_MODEREPORT 3
|
||||||
|
.SH NAME
|
||||||
|
termkey_interpret_modereport \- interpret opaque mode report data
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <termkey.h>
|
||||||
|
.sp
|
||||||
|
.BI "TermKeyResult termkey_interpret_modereport(TermKey *" tk ", const TermKeyKey *" key ", "
|
||||||
|
.BI " int *" initial ", int *" mode ", int *" value );
|
||||||
|
.fi
|
||||||
|
.sp
|
||||||
|
Link with \fI-ltermkey\fP.
|
||||||
|
.SH DESCRIPTION
|
||||||
|
\fBtermkey_interpret_modereport\fP() fills in variables in the passed pointers according to the mode report event found in \fIkey\fP. It should be called if \fBtermkey_getkey\fP(3) or similar have returned a key event with the type of \fBTERMKEY_TYPE_MODEREPORT\fP.
|
||||||
|
.PP
|
||||||
|
Any pointer may instead be given as \fBNULL\fP to not return that value.
|
||||||
|
.PP
|
||||||
|
The \fIinitial\fP variable will be filled with 0 for an ANSI mode report, or \f(CW'?'\fP for a DEC mode report. The \fImode\fP variable will be filled with the number of the mode, and \fIvalue\fP will be filled with the value from the report.
|
||||||
|
.SH "RETURN VALUE"
|
||||||
|
If passed a \fIkey\fP event of the type \fBTERMKEY_TYPE_MODEREPORT\fP, this function will return \fBTERMKEY_RES_KEY\fP and will affect the variables whose pointers were passed in, as described above.
|
||||||
|
.PP
|
||||||
|
For other event types it will return \fBTERMKEY_RES_NONE\fP, and its effects on any variables whose pointers were passed in, are undefined.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR termkey_waitkey (3),
|
||||||
|
.BR termkey_getkey (3),
|
||||||
|
.BR termkey (7)
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include "../termkey.h"
|
||||||
|
#include "taplib.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
TermKey *tk;
|
||||||
|
TermKeyKey key;
|
||||||
|
int initial, mode, value;
|
||||||
|
|
||||||
|
plan_tests(12);
|
||||||
|
|
||||||
|
tk = termkey_new_abstract("vt100", 0);
|
||||||
|
|
||||||
|
termkey_push_bytes(tk, "\e[?1;2$y", 8);
|
||||||
|
|
||||||
|
is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for mode report");
|
||||||
|
|
||||||
|
is_int(key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
|
||||||
|
|
||||||
|
is_int(termkey_interpret_modereport(tk, &key, &initial, &mode, &value), TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
|
||||||
|
|
||||||
|
is_int(initial, '?', "initial indicator from mode report");
|
||||||
|
is_int(mode, 1, "mode number from mode report");
|
||||||
|
is_int(value, 2, "mode value from mode report");
|
||||||
|
|
||||||
|
termkey_push_bytes(tk, "\e[4;1$y", 7);
|
||||||
|
|
||||||
|
is_int(termkey_getkey(tk, &key), TERMKEY_RES_KEY, "getkey yields RES_KEY for mode report");
|
||||||
|
|
||||||
|
is_int(key.type, TERMKEY_TYPE_MODEREPORT, "key.type for mode report");
|
||||||
|
|
||||||
|
is_int(termkey_interpret_modereport(tk, &key, &initial, &mode, &value), TERMKEY_RES_KEY, "interpret_modereoprt yields RES_KEY");
|
||||||
|
|
||||||
|
is_int(initial, 0, "initial indicator from mode report");
|
||||||
|
is_int(mode, 4, "mode number from mode report");
|
||||||
|
is_int(value, 1, "mode value from mode report");
|
||||||
|
|
||||||
|
termkey_destroy(tk);
|
||||||
|
|
||||||
|
return exit_status();
|
||||||
|
}
|
20
termkey.c
20
termkey.c
|
@ -1254,6 +1254,15 @@ size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, T
|
||||||
case TERMKEY_TYPE_POSITION:
|
case TERMKEY_TYPE_POSITION:
|
||||||
l = snprintf(buffer + pos, len - pos, "Position");
|
l = snprintf(buffer + pos, len - pos, "Position");
|
||||||
break;
|
break;
|
||||||
|
case TERMKEY_TYPE_MODEREPORT:
|
||||||
|
{
|
||||||
|
int initial, mode, value;
|
||||||
|
termkey_interpret_modereport(tk, key, &initial, &mode, &value);
|
||||||
|
if(initial)
|
||||||
|
l = snprintf(buffer + pos, len - pos, "Mode(%c%d=%d)", initial, mode, value);
|
||||||
|
else
|
||||||
|
l = snprintf(buffer + pos, len - pos, "Mode(%d=%d)", mode, value);
|
||||||
|
}
|
||||||
case TERMKEY_TYPE_UNKNOWN_CSI:
|
case TERMKEY_TYPE_UNKNOWN_CSI:
|
||||||
l = snprintf(buffer + pos, len - pos, "CSI %c", key->code.number & 0xff);
|
l = snprintf(buffer + pos, len - pos, "CSI %c", key->code.number & 0xff);
|
||||||
break;
|
break;
|
||||||
|
@ -1381,6 +1390,17 @@ int termkey_keycmp(TermKey *tk, const TermKeyKey *key1p, const TermKeyKey *key2p
|
||||||
return col1 - col2;
|
return col1 - col2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case TERMKEY_TYPE_MODEREPORT:
|
||||||
|
{
|
||||||
|
int initial1, initial2, mode1, mode2, value1, value2;
|
||||||
|
termkey_interpret_modereport(tk, &key1, &initial1, &mode1, &value1);
|
||||||
|
termkey_interpret_modereport(tk, &key2, &initial2, &mode2, &value2);
|
||||||
|
if(initial1 != initial2)
|
||||||
|
return initial1 - initial2;
|
||||||
|
if(mode1 != mode2)
|
||||||
|
return mode1 - mode2;
|
||||||
|
return value1 - value2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return key1.modifiers - key2.modifiers;
|
return key1.modifiers - key2.modifiers;
|
||||||
|
|
|
@ -97,6 +97,7 @@ typedef enum {
|
||||||
TERMKEY_TYPE_KEYSYM,
|
TERMKEY_TYPE_KEYSYM,
|
||||||
TERMKEY_TYPE_MOUSE,
|
TERMKEY_TYPE_MOUSE,
|
||||||
TERMKEY_TYPE_POSITION,
|
TERMKEY_TYPE_POSITION,
|
||||||
|
TERMKEY_TYPE_MODEREPORT,
|
||||||
/* add other recognised types here */
|
/* add other recognised types here */
|
||||||
|
|
||||||
TERMKEY_TYPE_UNKNOWN_CSI = -1
|
TERMKEY_TYPE_UNKNOWN_CSI = -1
|
||||||
|
@ -205,6 +206,8 @@ TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKe
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col);
|
TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col);
|
||||||
|
|
||||||
|
TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value);
|
||||||
|
|
||||||
TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd);
|
TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
Loading…
Reference in New Issue