aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile2
-rw-r--r--libterminput.c2
-rw-r--r--libterminput.h472
-rw-r--r--libterminput_is_ready.32
-rw-r--r--libterminput_read.32
5 files changed, 450 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index 81f42ff..5295a38 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ TESTS =\
LOBJ = $(OBJ:.o=.lo)
-all: libterminput.a libterminput.$(LIBEXT) $(TESTS)
+all: libterminput.a libterminput.$(LIBEXT) $(TESTS) interactive-test
$(OBJ): $(HDR)
$(LOBJ): $(HDR)
$(TESTS:=.o): $(HDR)
diff --git a/libterminput.c b/libterminput.c
index cb946d0..86666c5 100644
--- a/libterminput.c
+++ b/libterminput.c
@@ -919,4 +919,4 @@ libterminput_clear_flags(struct libterminput_state *ctx, enum libterminput_flags
}
-extern inline int libterminput_is_ready(union libterminput_input *input, struct libterminput_state *ctx);
+extern inline int libterminput_is_ready(const union libterminput_input *input, const struct libterminput_state *ctx);
diff --git a/libterminput.h b/libterminput.h
index d5c5439..7163140 100644
--- a/libterminput.h
+++ b/libterminput.h
@@ -9,13 +9,47 @@
* Flags for supporting incompatible input; the user must
* set or clear his flag after setting or clearing it on
* the terminal, and the user must make sure that the
- * terminal support this flag if set.
+ * terminal support this flag if set
*/
enum libterminput_flags {
+ /**
+ * The sequence 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
+ */
LIBTERMINPUT_DECSET_1005 = 0x0001,
+
+ /**
+ * Parse CSI M as Macro key presses rather rather than
+ * mouse tracking events
+ *
+ * This is incompatible with all mouse tracking modes except
+ * DECSET 1006
+ */
LIBTERMINPUT_MACRO_ON_CSI_M = 0x0002,
+
+ /**
+ * Parse CSI P as Pause key presses rather than F1 key presses
+ */
LIBTERMINPUT_PAUSE_ON_CSI_P = 0x0004,
+
+ /**
+ * Parse CSI @ as Insert key presses rather than a number of
+ * possible special keys combined with the control and shift
+ * modifiers
+ */
LIBTERMINPUT_INS_ON_CSI_AT = 0x0008,
+
+ /**
+ * Backtab shall be treated as a separate key, and not be
+ * reported as tab with the shift modifier. This flag is just
+ * a usability issue. Keyboards put backtab on shift+tab,
+ * which is why the tab keycap has both a backward arrow
+ * (backtab) and a forward arrow (tab); but most users are
+ * unfamiliar with backtab, and just see it as shift+tab.
+ */
LIBTERMINPUT_SEPARATE_BACKTAB = 0x0010,
/**
@@ -27,17 +61,62 @@ enum libterminput_flags {
*/
LIBTERMINPUT_ESC_ON_BLOCK = 0x0020,
+ /**
+ * This flag should be set, by the application, once
+ * the application sends an escape sequence requesting
+ * the terminal to report the cursor's position, and
+ * cleared once the position has been sent by the
+ * terminal and retreived by application
+ *
+ * This is required for distinguishing cursor position
+ * reports from F3 key presses
+ */
LIBTERMINPUT_AWAITING_CURSOR_POSITION = 0x0040
};
+/**
+ * Modifier keys
+ *
+ * These are the commonly reported modifiers,
+ * but additional modifiers are possible
+ */
enum libterminput_mod {
+ /**
+ * Shift modifier
+ */
LIBTERMINPUT_SHIFT = 0x01,
+
+ /**
+ * Meta/Alternative modifier
+ */
LIBTERMINPUT_META = 0x02,
+
+ /**
+ * Control modifier
+ */
LIBTERMINPUT_CTRL = 0x04
};
+/**
+ * Keyboard buttons
+ *
+ * Only listed values can be reported, however the value
+ * must be listed for the version the application is linked
+ * against, not compiled against, so other values can be
+ * reported the application is linked against a newer version
+ * of the library than it is compiled against
+ */
enum libterminput_key {
+ /**
+ * Non-special key
+ *
+ * Each code point that is generated as a keypress
+ * is reported separately, meaning that keypresses
+ * that generate multiple code points appear as
+ * multiple keypresses
+ */
LIBTERMINPUT_SYMBOL,
+
LIBTERMINPUT_UP,
LIBTERMINPUT_DOWN,
LIBTERMINPUT_RIGHT,
@@ -85,88 +164,399 @@ enum libterminput_key {
LIBTERMINPUT_KEYPAD_DECIMAL,
LIBTERMINPUT_KEYPAD_COMMA,
LIBTERMINPUT_KEYPAD_POINT,
- LIBTERMINPUT_KEYPAD_ENTER,
+ LIBTERMINPUT_KEYPAD_ENTER
};
+/**
+ * Mouse buttons
+ *
+ * It is possible that non-listed buttons are
+ * reported in events
+ */
enum libterminput_button {
+ /**
+ * No mouse button is held down
+ */
LIBTERMINPUT_NO_BUTTON,
- LIBTERMINPUT_BUTTON1, /* left (assuming right-handed) */
- LIBTERMINPUT_BUTTON2, /* middle */
- LIBTERMINPUT_BUTTON3, /* right (assuming right-handed) */
- LIBTERMINPUT_SCROLL_UP, /* no corresponding release event shall be generated */
- LIBTERMINPUT_SCROLL_DOWN, /* no corresponding release event shall be generated */
- LIBTERMINPUT_SCROLL_LEFT, /* may or may not have a corresponding release event */
- LIBTERMINPUT_SCROLL_RIGHT, /* may or may not have a corresponding release event */
- LIBTERMINPUT_XBUTTON1, /* extended button 1, also known as backward */
- LIBTERMINPUT_XBUTTON2, /* extended button 2, also known as forward */
- LIBTERMINPUT_XBUTTON3, /* extended button 3, you probably don't have this button */
- LIBTERMINPUT_XBUTTON4 /* extended button 4, you probably don't have this button */
+
+ /**
+ * Primary button
+ *
+ * Left button if right-handed,
+ * right button if left-handed
+ */
+ LIBTERMINPUT_BUTTON1,
+
+ /**
+ * Middle button
+ */
+ LIBTERMINPUT_BUTTON2,
+
+ /**
+ * Secondary button
+ *
+ * Right button if right-handed,
+ * left button if left-handed
+ */
+ LIBTERMINPUT_BUTTON3,
+
+ /**
+ * Wheel scrolled up
+ *
+ * No corresponding release event shall be generated
+ */
+ LIBTERMINPUT_SCROLL_UP,
+
+ /**
+ * Wheel scrolled down
+ *
+ * No corresponding release event shall be generated
+ */
+ LIBTERMINPUT_SCROLL_DOWN,
+
+ /**
+ * Left-scroll button or wheel scrolled left
+ *
+ * May or may not have a corresponding release event
+ */
+ LIBTERMINPUT_SCROLL_LEFT,
+
+ /**
+ * Right-scroll button or wheel scrolled right
+ *
+ * May or may not have a corresponding release event
+ */
+ LIBTERMINPUT_SCROLL_RIGHT,
+
+ /**
+ * Extended button 1, also known as backward
+ */
+ LIBTERMINPUT_XBUTTON1,
+
+ /**
+ * Extended button 2, also known as farward
+ */
+ LIBTERMINPUT_XBUTTON2,
+
+ /**
+ * Extended button 3
+ *
+ * You probably don't have this button
+ */
+ LIBTERMINPUT_XBUTTON3,
+
+ /**
+ * Extended button 4
+ *
+ * You probably don't have this button
+ */
+ LIBTERMINPUT_XBUTTON4
};
+/**
+ * Input event type
+ */
enum libterminput_type {
+ /**
+ * A special value to mark that the input was either
+ * discard or not yet completed
+ */
LIBTERMINPUT_NONE,
+
+ /**
+ * Normal key press
+ */
LIBTERMINPUT_KEYPRESS,
+
+ /**
+ * Pseudo-event that marks that beginning of a bracketed paste
+ */
LIBTERMINPUT_BRACKETED_PASTE_START,
+
+ /**
+ * Pseudo-event that marks that end of a bracketed paste
+ */
LIBTERMINPUT_BRACKETED_PASTE_END,
+
+ /**
+ * Bracketed paste
+ */
LIBTERMINPUT_TEXT,
+
+ /**
+ * Mouse event
+ */
LIBTERMINPUT_MOUSEEVENT,
+
+ /**
+ * OK response for a device status query
+ */
LIBTERMINPUT_TERMINAL_IS_OK, /* response to CSI 5 n */
+
+ /**
+ * Not-OK response for a device status query
+ */
LIBTERMINPUT_TERMINAL_IS_NOT_OK, /* response to CSI 5 n */
+
+ /**
+ * Cursor position report event as a response
+ * to a cursor position query
+ */
LIBTERMINPUT_CURSOR_POSITION /* response to CSI 6 n */
};
+/**
+ * Mouse event subtype
+ */
enum libterminput_event {
+ /**
+ * Mouse button pressed
+ */
LIBTERMINPUT_PRESS,
+
+ /**
+ * Mouse button released
+ */
LIBTERMINPUT_RELEASE,
+
+ /**
+ * Mouse moved, possibly with dragging
+ */
LIBTERMINPUT_MOTION,
+
+ /**
+ * Highlight ended inside of selected region
+ */
LIBTERMINPUT_HIGHLIGHT_INSIDE,
+
+ /**
+ * Highlight ended outside of selected region
+ */
LIBTERMINPUT_HIGHLIGHT_OUTSIDE
};
+/**
+ * Keypress event
+ *
+ * Some key presses may actually be mouse events,
+ * particularly when mouse tracking is disabled.
+ * In particular, mouse scrolling may appear as
+ * repeated Up key or Down key pesses
+ */
struct libterminput_keypress {
+ /**
+ * Should be `LIBTERMINPUT_KEYPRESS`
+ */
enum libterminput_type type;
+
+ /**
+ * Which key was pressed
+ */
enum libterminput_key key;
- unsigned long long int times; /* if .times > 1, next will be the same, but will .times -= 1 */
+
+ /**
+ * This number of types the key was
+ * pressed
+ *
+ * Normally this would be 1, some mouse
+ * events generate arrow key presses that
+ * are reported, not multiple times, but
+ * as clicked multiple times
+ *
+ * For the next `.times - 1` reads (if
+ * this value is not modified by the user)
+ * will reported as the same event except
+ * that this value will be decreased by 1
+ * each time
+ */
+ unsigned long long int times;
+
+ /**
+ * OR of active modifier keys
+ */
enum libterminput_mod mods;
- char symbol[7]; /* use if .key == LIBTERMINPUT_SYMBOL */
+
+ /**
+ * The symbol generated by the pressed key
+ *
+ * Only set if `.key == LIBTERMINPUT_SYMBOL`
+ */
+ char symbol[7];
};
+/**
+ * Text from a bracketed paste
+ */
struct libterminput_text {
+ /**
+ * Should be `LIBTERMINPUT_TEXT`
+ */
enum libterminput_type type;
+
+ /**
+ * The number of bytes available in `.bytes`
+ */
size_t nbytes;
+
+ /**
+ * The section of the paste included in this
+ * event report
+ *
+ * If the text is longer than this buffer, it
+ * is split into multiple events, however they
+ * will all be between the same
+ * `LIBTERMINPUT_BRACKETED_PASTE_START` and
+ * `LIBTERMINPUT_BRACKETED_PASTE_END`, so it is
+ * possible to determine which events are actually
+ * the same paste event
+ */
char bytes[512];
};
+/**
+ * Mouse event
+ */
struct libterminput_mouseevent {
+ /**
+ * Should be `LIBTERMINPUT_MOUSEEVENT`
+ */
enum libterminput_type type;
- enum libterminput_mod mods; /* Set to 0 for LIBTERMINPUT_HIGHLIGHT_INSIDE and LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
- enum libterminput_button button; /* Set to 1 for LIBTERMINPUT_HIGHLIGHT_INSIDE and LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
+
+ /**
+ * Active modifier keys
+ *
+ * Set to 0 for `LIBTERMINPUT_HIGHLIGHT_INSIDE`
+ * and `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ enum libterminput_mod mods;
+
+ /**
+ * The mouse button used in the event
+ *
+ * Set to 1 (LIBTERMINPUT_BUTTON1) for
+ * `LIBTERMINPUT_HIGHLIGHT_INSIDE` and
+ * `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ enum libterminput_button button;
+
+ /**
+ * Mouse event sub type
+ */
enum libterminput_event event;
+
+ /**
+ * Horizontal pointer position
+ *
+ * The number of cells offset right from the left edge, plus 1
+ */
size_t x;
+
+ /**
+ * Vertical pointer position
+ *
+ * The number of cells offset down from the top edge, plus 1
+ */
size_t y;
- size_t start_x; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
- size_t start_y; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
- size_t end_x; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
- size_t end_y; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
+
+ /**
+ * Horizontal beginning of the selection region
+ *
+ * Only set for `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ size_t start_x;
+
+ /**
+ * Vertical beginning of the selection region
+ *
+ * Only set for `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ size_t start_y;
+
+ /**
+ * Horizontal end of the selection region
+ *
+ * Only set for `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ size_t end_x;
+
+ /**
+ * Vertical end of the selection region
+ *
+ * Only set for `LIBTERMINPUT_HIGHLIGHT_OUTSIDE`
+ */
+ size_t end_y;
};
+/**
+ * Cursor position response
+ */
struct libterminput_position {
+ /**
+ * Should be `LIBTERMINPUT_CURSOR_POSITION`
+ */
enum libterminput_type type;
+
+ /**
+ * Horizontal cursor position
+ *
+ * The number of cells offset right from the left edge, plus 1
+ */
size_t x;
+
+ /**
+ * Vertical cursor position
+ *
+ * The number of cells offset down from the top edge, plus 1
+ */
size_t y;
};
+/**
+ * Input event
+ */
union libterminput_input {
+ /**
+ * Input event type, used to determine which
+ * other member to read
+ *
+ * The following values have no corresponding
+ * member to read data from:
+ * `LIBTERMINPUT_NONE`,
+ * `LIBTERMINPUT_BRACKETED_PASTE_START`,
+ * `LIBTERMINPUT_BRACKETED_PASTE_END`,
+ * `LIBTERMINPUT_TERMINAL_IS_OK`,
+ * `LIBTERMINPUT_TERMINAL_IS_NOT_OK`
+ */
enum libterminput_type type;
- 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 */
+
+ /**
+ * Use if `.type == LIBTERMINPUT_KEYPRESS`
+ */
+ struct libterminput_keypress keypress;
+
+ /**
+ * Use if `.type == LIBTERMINPUT_TEXT`
+ */
+ struct libterminput_text text;
+
+ /**
+ * Use if `.type == LIBTERMINPUT_MOUSEEVENT`
+ */
+ struct libterminput_mouseevent mouseevent;
+
+ /**
+ * Use if `.type == LIBTERMINPUT_CURSOR_POSITION`
+ */
+ struct libterminput_position position;
};
/**
+ * The current input state and configurations
+ *
* This struct should be considered opaque
+ *
+ * Initialised with by setting all bytes to 0
*/
struct libterminput_state {
int inited; /* whether the input in initialised, not this struct */
@@ -193,11 +583,22 @@ struct libterminput_state {
* @param input Output parameter for input
* @param ctx State for the terminal, parts of the state may be stored in `input`
* @return 1 normally, 0 on end of input, -1 on error
+ *
+ * @throws Any reason specified for read(3)
*/
int libterminput_read(int fd, union libterminput_input *input, struct libterminput_state *ctx);
+/**
+ * Check if more input available that can be processed
+ * by `libterminput_read` without performing any additional
+ * read(3) operation
+ *
+ * @param input Input gathered by `libterminput_read`
+ * @param ctx State for the terminal
+ * @return 1 if there there is more input available, 0 otherwise
+ */
inline int
-libterminput_is_ready(union libterminput_input *input, struct libterminput_state *ctx)
+libterminput_is_ready(const union libterminput_input *input, const struct libterminput_state *ctx)
{
if (!ctx->inited || ctx->paused || ctx->mouse_tracking)
return 0;
@@ -206,7 +607,26 @@ libterminput_is_ready(union libterminput_input *input, struct libterminput_state
return ctx->stored_head > ctx->stored_tail;
}
+/**
+ * Set a behavioural flags
+ *
+ * @param ctx Argument pasted as the last parameter to `libterminput_read`
+ * @param flags The OR of the flags to set
+ * @return 0 on success, -1 on failure
+ *
+ * The current version of this function cannot fail
+ */
int libterminput_set_flags(struct libterminput_state *ctx, enum libterminput_flags flags);
+
+/**
+ * Clear a behavioural flags
+ *
+ * @param ctx Argument pasted as the last parameter to `libterminput_read`
+ * @param flags The OR of the flags to clear
+ * @return 0 on success, -1 on failure
+ *
+ * The current version of this function cannot fail
+ */
int libterminput_clear_flags(struct libterminput_state *ctx, enum libterminput_flags flags);
diff --git a/libterminput_is_ready.3 b/libterminput_is_ready.3
index 0739e11..08e6fd6 100644
--- a/libterminput_is_ready.3
+++ b/libterminput_is_ready.3
@@ -6,7 +6,7 @@ libterminput_is_ready \- Check if there is read data buffered
.nf
#include <libterminput.h>
-inline int libterminput_is_ready(union libterminput_input *input, struct libterminput_state *ctx);
+inline int libterminput_is_ready(const union libterminput_input *\fIinput\fP, const struct libterminput_state *\fIctx\fP);
.fi
.PP
Link with
diff --git a/libterminput_read.3 b/libterminput_read.3
index f7bbd91..deabd63 100644
--- a/libterminput_read.3
+++ b/libterminput_read.3
@@ -411,7 +411,7 @@ OK response for a device status query.
Not-OK response for a device status query.
.TP
.B LIBTERMINPUT_CURSOR_POSITION
-Cursor position report even as a response to a
+Cursor position report event 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