From a7be1b1dc5648999167321df657d5490caef6883 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 10 Apr 2021 00:22:45 +0200 Subject: Add support for cursor position and device status reports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- TODO | 1 - libterminput.c | 21 ++++++++++++++++++--- libterminput.h | 32 ++++++++++++++++++++++---------- libterminput_read.3 | 40 ++++++++++++++++++++++++++++++++++++---- libterminput_set_flags.3 | 35 +++++++++++++++++++++++------------ 5 files changed, 99 insertions(+), 30 deletions(-) diff --git a/TODO b/TODO index 50b03d9..057febf 100644 --- a/TODO +++ b/TODO @@ -1,2 +1 @@ -Add cursor position report support Add test diff --git a/libterminput.c b/libterminput.c index 147e756..5d6f401 100644 --- a/libterminput.c +++ b/libterminput.c @@ -398,9 +398,15 @@ parse_sequence(union libterminput_input *input, struct libterminput_state *ctx) } break; case 'P': - input->keypress.key = LIBTERMINPUT_F1; - if (ctx->flags & LIBTERMINPUT_PAUSE_ON_CSI_P) - input->keypress.key = LIBTERMINPUT_PAUSE; + if ((ctx->flags & LIBTERMINPUT_AWAITING_CURSOR_POSITION) && nnums == 2) { + input->position.type = LIBTERMINPUT_CURSOR_POSITION; + input->position.y = (size_t)nums[0] + (size_t)!nums[0]; + input->position.x = (size_t)nums[1] + (size_t)!nums[1]; + } else { + input->keypress.key = LIBTERMINPUT_F1; + if (ctx->flags & LIBTERMINPUT_PAUSE_ON_CSI_P) + input->keypress.key = LIBTERMINPUT_PAUSE; + } break; case 'Q': input->keypress.key = LIBTERMINPUT_F2; break; case 'R': input->keypress.key = LIBTERMINPUT_F3; break; @@ -460,6 +466,15 @@ parse_sequence(union libterminput_input *input, struct libterminput_state *ctx) input->keypress.key = LIBTERMINPUT_LEFT; input->keypress.mods |= LIBTERMINPUT_SHIFT; break; + case 'n': + if (nnums == 1 && nums[0] == '0') { + input->type = LIBTERMINPUT_TERMINAL_IS_OK; + } else if (nnums == 1 && nums[0] == '3') { + input->type = LIBTERMINPUT_TERMINAL_IS_NOT_OK; + } else { + goto suppress; + } + break; case 't': /* Parsing output for legacy mouse highlight tracking output (\e[?1001h). */ ctx->mouse_tracking = 0; diff --git a/libterminput.h b/libterminput.h index 0182a54..95eea11 100644 --- a/libterminput.h +++ b/libterminput.h @@ -12,11 +12,11 @@ * terminal support this flag if set. */ enum libterminput_flags { - LIBTERMINPUT_DECSET_1005 = 0x0001, - LIBTERMINPUT_MACRO_ON_CSI_M = 0x0002, - LIBTERMINPUT_PAUSE_ON_CSI_P = 0x0004, - LIBTERMINPUT_INS_ON_CSI_AT = 0x0008, - LIBTERMINPUT_SEPARATE_BACKTAB = 0x0010, + LIBTERMINPUT_DECSET_1005 = 0x0001, + LIBTERMINPUT_MACRO_ON_CSI_M = 0x0002, + LIBTERMINPUT_PAUSE_ON_CSI_P = 0x0004, + LIBTERMINPUT_INS_ON_CSI_AT = 0x0008, + LIBTERMINPUT_SEPARATE_BACKTAB = 0x0010, /** * If an ESC is received without anything after it, @@ -25,7 +25,9 @@ enum libterminput_flags { * simulate a keypress that terminal does not support * (yes, this is a real world issue). */ - LIBTERMINPUT_ESC_ON_BLOCK = 0x0020 + LIBTERMINPUT_ESC_ON_BLOCK = 0x0020, + + LIBTERMINPUT_AWAITING_CURSOR_POSITION = 0x0040 }; enum libterminput_mod { @@ -107,7 +109,10 @@ enum libterminput_type { LIBTERMINPUT_BRACKETED_PASTE_START, LIBTERMINPUT_BRACKETED_PASTE_END, LIBTERMINPUT_TEXT, - LIBTERMINPUT_MOUSEEVENT + LIBTERMINPUT_MOUSEEVENT, + LIBTERMINPUT_TERMINAL_IS_OK, /* response to CSI 5 n */ + LIBTERMINPUT_TERMINAL_IS_NOT_OK, /* response to CSI 5 n */ + LIBTERMINPUT_CURSOR_POSITION /* response to CSI 6 n */ }; enum libterminput_event { @@ -126,6 +131,12 @@ struct libterminput_keypress { char symbol[7]; /* use if .key == LIBTERMINPUT_SYMBOL */ }; +struct libterminput_text { + enum libterminput_type type; + size_t nbytes; + char bytes[512]; +}; + struct libterminput_mouseevent { enum libterminput_type type; enum libterminput_mod mods; /* Set to 0 for LIBTERMINPUT_HIGHLIGHT_INSIDE and LIBTERMINPUT_HIGHLIGHT_OUTSIDE */ @@ -139,10 +150,10 @@ struct libterminput_mouseevent { size_t end_y; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */ }; -struct libterminput_text { +struct libterminput_position { enum libterminput_type type; - size_t nbytes; - char bytes[512]; + size_t x; + size_t y; }; union libterminput_input { @@ -150,6 +161,7 @@ union libterminput_input { struct libterminput_keypress keypress; /* use if .type == LIBTERMINPUT_KEYPRESS */ struct libterminput_text text; /* use if .type == LIBTERMINPUT_TEXT */ struct libterminput_mouseevent mouseevent; /* use if .type == LIBTERMINPUT_MOUSEEVENT */ + struct libterminput_position position; /* use if .type == LIBTERMINPUT_CURSOR_POSITION */ }; diff --git a/libterminput_read.3 b/libterminput_read.3 index 2cf401b..09f0212 100644 --- a/libterminput_read.3 +++ b/libterminput_read.3 @@ -85,7 +85,10 @@ enum libterminput_type { LIBTERMINPUT_BRACKETED_PASTE_START, LIBTERMINPUT_BRACKETED_PASTE_END, LIBTERMINPUT_TEXT, - LIBTERMINPUT_MOUSEEVENT + LIBTERMINPUT_MOUSEEVENT, + LIBTERMINPUT_TERMINAL_IS_OK, + LIBTERMINPUT_TERMINAL_IS_NOT_OK, + LIBTERMINPUT_CURSOR_POSITION }; enum libterminput_event { @@ -104,6 +107,12 @@ struct libterminput_keypress { char symbol[7]; }; +struct libterminput_text { + enum libterminput_type type; + size_t nbytes; + char bytes[512]; +}; + struct libterminput_mouseevent { enum libterminput_type type; enum libterminput_mod mods; @@ -117,10 +126,10 @@ struct libterminput_mouseevent { size_t end_y; }; -struct libterminput_text { +struct libterminput_position { enum libterminput_type type; - size_t nbytes; - char bytes[512]; + size_t x; + size_t y; }; union libterminput_input { @@ -393,6 +402,29 @@ and will also be set to indicate the region selected by the application. .RE +.TP +.B LIBTERMINPUT_TERMINAL_IS_OK +OK response for a device status query. +.TP +.B LIBTERMINPUT_TERMINAL_IS_NOT_OK +Not-OK response for a device status query. +.TP +.B LIBTERMINPUT_CURSOR_POSITION +Cursor position report even as a response to a +cursor position query. The line (indexed starting +with 1 at the top) the cursor is on will be +stored in +.I input->position.y +and the column (indexed starting with 1 at the +left edge) will be stored in +.I input->position.x + +This event can conflict with both F1 and pause +key processes, therefore the +.B LIBTERMINPUT_AWAITING_CURSOR_POSITION +flag must be set with the +.BR libterminput_set_flags (3) +function. .SH RETURN VALUE The .BR libterminput_read () diff --git a/libterminput_set_flags.3 b/libterminput_set_flags.3 index 6b79998..4560971 100644 --- a/libterminput_set_flags.3 +++ b/libterminput_set_flags.3 @@ -34,15 +34,17 @@ The available flags are .B LIBTERMINPUT_DECSET_1005 The sequence .B CSI M -shall be parsed be parse as a DECSET 1005 sequence -which is incompatible with legacy mouse tracking. -This flag shall only be set if DECSET 1005 has sent -to the terminal and the user is sure it is supported -by the terminal. +shall be parsed be parse as a +.I DECSET 1005 +sequence which is incompatible with legacy mouse +tracking. This flag shall only be set if +.I DECSET 1005 +has sent to the terminal and the user is sure it +is supported by the terminal. .TP .B LIBTERMINPUT_MACRO_ON_CSI_M The sequence -.B CSI Pm M +.BI "CSI " Pm " M" shall be parsed as a key press of the macro key. This is incompatible with all mouse tracking modes except @@ -54,13 +56,13 @@ and therefore uses it, can safely use this flag. .TP .B LIBTERMINPUT_PAUSE_ON_CSI_P The sequence -.B CSI Pm M +.BI "CSI " Pm " M" shall be parsed as a key press of the pause key instead of the F1 key. .TP .B LIBTERMINPUT_INS_ON_CSI_AT The sequence -.B CSI Pm @ +.BI "CSI " Pm " @" shall be parsed as a key press of the insert key instead of a number of possible special keys combined with the control and shift modifiers. @@ -75,11 +77,20 @@ a forward arrow (tab); but most users are unfamiliar with backtab, and just see it as shift+tab. .TP .B LIBTERMINPUT_ESC_ON_BLOCK -If an ESC is received without anything after it, -it shall be parsed as an ESC keypress. This is not +If an ESC is received without anything after it, it +shall be parsed as an escape keypress. This is not always desirable behaviour as the user may manually -press ESC to simulate a keypress that terminal does -not support (yes, this is a real world issue). +press escape to simulate a keypress that terminal +does not support (yes, this is a real world issue). +.TP +.B LIBTERMINPUT_AWAITING_CURSOR_POSITION +The sequence +.BI "CSI " Ps " ; " Rs " R" +shall be parsed as a cursor position report rather +than as an F1 or pause key press. This flag takes +precedence over the +.B LIBTERMINPUT_PAUSE_ON_CSI_P +flag. .PP .I ctx must have been zero-initialised, e.g. with -- cgit v1.2.3-70-g09d2