aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-06 17:53:09 +0200
committerMattias Andrée <maandree@kth.se>2021-04-06 17:55:01 +0200
commit8f09401e3d7d238355391e4abf3746987c95c492 (patch)
tree5b53b0ceee4610ebc89f9fb878208edcc0cf57f1
parentAdd more key codes (diff)
downloadlibterminput-8f09401e3d7d238355391e4abf3746987c95c492.tar.gz
libterminput-8f09401e3d7d238355391e4abf3746987c95c492.tar.bz2
libterminput-8f09401e3d7d238355391e4abf3746987c95c492.tar.xz
Add support for bracketed paste
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--TODO2
-rw-r--r--interactive-test.c8
-rw-r--r--libterminput.c82
-rw-r--r--libterminput.h20
4 files changed, 102 insertions, 10 deletions
diff --git a/TODO b/TODO
index 2ed08cc..bd68fab 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
+Add test
Add README
Add man page
Add mouse input
-Add bracked paste
diff --git a/interactive-test.c b/interactive-test.c
index cc41231..d393a96 100644
--- a/interactive-test.c
+++ b/interactive-test.c
@@ -86,6 +86,14 @@ main(void)
printf("\t%s: %s\n", "meta", (input.keypress.mods & LIBTERMINPUT_META) ? "yes" : "no");
printf("\t%s: %s\n", "ctrl", (input.keypress.mods & LIBTERMINPUT_CTRL) ? "yes" : "no");
printf("\t%s: %s (%llu)\n", "will repeat", input.keypress.times > 1 ? "yes" : "no", input.keypress.times);
+ } else if (input.type == LIBTERMINPUT_BRACKETED_PASTE_START) {
+ printf("bracketed paste start\n");
+ } else if (input.type == LIBTERMINPUT_BRACKETED_PASTE_END) {
+ printf("bracketed paste end\n");
+ } else if (input.type == LIBTERMINPUT_TEXT) {
+ printf("text:\n");
+ printf("\tlength: %zu\n", input.text.nbytes);
+ printf("\tdata: %.512s\n", input.text.bytes);
} else {
printf("other\n");
}
diff --git a/libterminput.c b/libterminput.c
index d721abd..62f4ca8 100644
--- a/libterminput.c
+++ b/libterminput.c
@@ -21,9 +21,10 @@ read_input(int fd, struct input *input, struct libterminput_state *ctx)
int r;
/* Get next byte from input */
- if (ctx->have_stored) {
- ctx->have_stored = 0;
- c = (unsigned char)ctx->stored;
+ if (ctx->stored_head != ctx->stored_tail) {
+ c = ((unsigned char *)ctx->stored)[ctx->stored_tail++];
+ if (ctx->stored_tail == ctx->stored_head)
+ ctx->stored_tail = ctx->stored_head = 0;
} else {
r = read(fd, &c, 1);
if (r <= 0)
@@ -39,8 +40,7 @@ read_input(int fd, struct input *input, struct libterminput_state *ctx)
ctx->n = 0;
ctx->npartial = 0;
ctx->mods = 0;
- ctx->have_stored = 1;
- ctx->stored = (char)c;
+ ctx->stored[ctx->stored_head++] = c;
strcpy(input->symbol, ctx->partial);
return 1;
} else {
@@ -185,6 +185,14 @@ parse_sequence(union libterminput_input *input, struct libterminput_state *ctx)
case 32: input->keypress.key = LIBTERMINPUT_F6; break;
case 33: input->keypress.key = LIBTERMINPUT_F7; break;
case 34: input->keypress.key = LIBTERMINPUT_F8; break;
+ case 200:
+ ctx->bracketed_paste = 1;
+ input->type = LIBTERMINPUT_BRACKETED_PASTE_START;
+ return;
+ case 201:
+ ctx->bracketed_paste = 0;
+ input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
+ return;
default:
input->type = LIBTERMINPUT_NONE;
return;
@@ -251,6 +259,67 @@ parse_sequence(union libterminput_input *input, struct libterminput_state *ctx)
}
+static int
+read_bracketed_paste(int fd, union libterminput_input *input, struct libterminput_state *ctx)
+{
+ ssize_t r;
+ size_t n;
+
+ /* Unfortunately there is no standard for how to handle pasted ESC's,
+ * not even ESC [201~ or ESC ESC. Terminates seem to just paste ESC as
+ * is, so we cannot do anything about them, however, a good terminal
+ * would stop the paste at the ~ in ESC [201~, send ~ as normal, and
+ * then continue the brackated paste mode. */
+
+ if (ctx->stored_head - ctx->stored_tail) {
+ for (n = ctx->stored_tail; n + 6 < ctx->stored_head; n++) {
+ if (ctx->stored[n + 0] == '\033' && ctx->stored[n + 1] == '[' && ctx->stored[n + 2] == '2' &&
+ ctx->stored[n + 3] == '0' && ctx->stored[n + 4] == '0' && ctx->stored[n + 5] == '~')
+ break;
+ }
+ if (n == ctx->stored_tail && ctx->stored_head - ctx->stored_tail >= 6) {
+ ctx->stored_tail += 6;
+ if (ctx->stored_tail == ctx->stored_head)
+ ctx->stored_tail = ctx->stored_head = 0;
+ input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
+ return 0;
+ }
+ input->text.nbytes = ctx->stored_head - ctx->stored_tail;
+ input->text.type = LIBTERMINPUT_TEXT;
+ memcpy(input->text.bytes, &ctx->stored[ctx->stored_tail], n - ctx->stored_tail);
+ ctx->stored_tail = n;
+ if (ctx->stored_tail == ctx->stored_head)
+ ctx->stored_tail = ctx->stored_head = 0;
+ return 0;
+ }
+
+ r = read(fd, input->text.bytes, sizeof(input->text.bytes));
+ if (r <= 0)
+ return (int)r;
+
+ input->text.nbytes = (size_t)r;
+ for (n = 0; n + 6 < input->text.nbytes; n++) {
+ if (input->text.bytes[n + 0] == '\033' && input->text.bytes[n + 1] == '[' && input->text.bytes[n + 2] == '2' &&
+ input->text.bytes[n + 3] == '0' && input->text.bytes[n + 4] == '0' && input->text.bytes[n + 5] == '~')
+ break;
+ }
+ if (!n && input->text.nbytes >= 6) {
+ ctx->stored_tail = 0;
+ ctx->stored_head = input->text.nbytes - 6;
+ memcpy(ctx->stored, &input->text.bytes[6], ctx->stored_head);
+ if (ctx->stored_tail == ctx->stored_head)
+ ctx->stored_tail = ctx->stored_head = 0;
+ input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
+ return 0;
+ }
+ ctx->stored_tail = 0;
+ ctx->stored_head = input->text.nbytes - n;
+ input->text.nbytes = n;
+ input->text.type = LIBTERMINPUT_TEXT;
+ return 0;
+}
+
+
int
libterminput_read(int fd, union libterminput_input *input, struct libterminput_state *ctx)
{
@@ -267,6 +336,9 @@ libterminput_read(int fd, union libterminput_input *input, struct libterminput_s
return 1;
}
+ if (ctx->bracketed_paste)
+ return read_bracketed_paste(fd, input, ctx);
+
r = read_input(fd, &ret, ctx);
if (r <= 0)
return r;
diff --git a/libterminput.h b/libterminput.h
index 4e33d09..d2f505f 100644
--- a/libterminput.h
+++ b/libterminput.h
@@ -60,7 +60,10 @@ enum libterminput_key {
enum libterminput_type {
LIBTERMINPUT_NONE,
- LIBTERMINPUT_KEYPRESS
+ LIBTERMINPUT_KEYPRESS,
+ LIBTERMINPUT_BRACKETED_PASTE_START,
+ LIBTERMINPUT_BRACKETED_PASTE_END,
+ LIBTERMINPUT_TEXT
};
struct libterminput_keypress {
@@ -71,9 +74,16 @@ struct libterminput_keypress {
char symbol[7]; /* use if .key == LIBTERMINPUT_SYMBOL */
};
+struct libterminput_text {
+ enum libterminput_type type;
+ size_t nbytes;
+ char bytes[512];
+};
+
union libterminput_input {
enum libterminput_type type;
- struct libterminput_keypress keypress;
+ struct libterminput_keypress keypress; /* use if .type == LIBTERMINPUT_KEYPRESS */
+ struct libterminput_text text; /* use if .type == LIBTERMINPUT_TEXT */
};
@@ -83,13 +93,15 @@ union libterminput_input {
struct libterminput_state {
int inited; /* whether the input in initialised, not this struct */
enum libterminput_mod mods;
+ size_t stored_head;
+ size_t stored_tail;
+ char bracketed_paste;
char meta;
char n;
- char have_stored;
char npartial;
- char stored;
char partial[7];
char key[44];
+ char stored[512];
};