aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-04-10 12:12:06 +0200
committerMattias Andrée <maandree@kth.se>2021-04-10 12:12:06 +0200
commit4cffaa1b3f1a78805977db1565111b8e894d3c17 (patch)
tree96d338262f77e0f64c591381ef21a5ab15b5dcd8
parentAdd tests and make some fixes (diff)
downloadlibterminput-4cffaa1b3f1a78805977db1565111b8e894d3c17.tar.gz
libterminput-4cffaa1b3f1a78805977db1565111b8e894d3c17.tar.bz2
libterminput-4cffaa1b3f1a78805977db1565111b8e894d3c17.tar.xz
Fix bracketed paste support
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--libterminput.c94
-rw-r--r--libterminput.h7
-rw-r--r--libterminput_is_ready.36
-rw-r--r--test.c37
4 files changed, 109 insertions, 35 deletions
diff --git a/libterminput.c b/libterminput.c
index 54016fe..0b2b22d 100644
--- a/libterminput.c
+++ b/libterminput.c
@@ -656,40 +656,82 @@ read_bracketed_paste(int fd, union libterminput_input *input, struct libterminpu
* 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) { /* TODO test */
- 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;
- ctx->bracketed_paste = 0;
- input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
- return 0;
+ if (ctx->stored_head - ctx->stored_tail) {
+ ctx->paused = 0;
+ n = ctx->stored_head - ctx->stored_tail;
+ if (!strncmp(&ctx->stored[ctx->stored_tail], "\033[201~", n < 6 ? n : 6)) {
+ if (n >= 6) {
+ ctx->stored_tail += 6;
+ if (ctx->stored_tail == ctx->stored_head)
+ ctx->stored_tail = ctx->stored_head = 0;
+ ctx->bracketed_paste = 0;
+ input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
+ return 1;
+ }
+ input->text.nbytes = ctx->stored_head - ctx->stored_tail;
+ memcpy(input->text.bytes, &ctx->stored[ctx->stored_tail], input->text.nbytes);
+ r = read(fd, &input->text.bytes[input->text.nbytes], sizeof(input->text.bytes) - input->text.nbytes);
+ if (r <= 0)
+ return (int)r;
+ input->text.nbytes += (size_t)r;
+ ctx->stored_head = ctx->stored_tail = 0;
+ goto normal;
}
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;
+ memcpy(input->text.bytes, &ctx->stored[ctx->stored_tail], input->text.nbytes);
+ ctx->stored_head = ctx->stored_tail = 0;
+ goto normal;
}
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++) {
+
+normal:
+ for (n = 0; n + 5 < 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] == '~')
+ input->text.bytes[n + 3] == '0' && input->text.bytes[n + 4] == '1' && input->text.bytes[n + 5] == '~')
break;
}
- if (!n && input->text.nbytes >= 6) {
+ do {
+ if (n + 4 < input->text.nbytes) {
+ 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] == '1')
+ break;
+ n += 1;
+ }
+ if (n + 3 < input->text.nbytes) {
+ if (input->text.bytes[n + 0] == '\033' && input->text.bytes[n + 1] == '[' && input->text.bytes[n + 2] == '2' &&
+ input->text.bytes[n + 3] == '0')
+ break;
+ n += 1;
+ }
+ if (n + 2 < input->text.nbytes) {
+ if (input->text.bytes[n + 0] == '\033' && input->text.bytes[n + 1] == '[' && input->text.bytes[n + 2] == '2')
+ break;
+ n += 1;
+ }
+ if (n + 1 < input->text.nbytes) {
+ if (input->text.bytes[n + 0] == '\033' && input->text.bytes[n + 1] == '[')
+ break;
+ n += 1;
+ }
+ if (n + 0 < input->text.nbytes) {
+ if (input->text.bytes[n + 0] == '\033')
+ break;
+ n += 1;
+ }
+ } while (0);
+ if (!n) {
+ if (input->text.nbytes < 6) {
+ input->text.type = LIBTERMINPUT_NONE;
+ memcpy(ctx->stored, input->text.bytes, input->text.nbytes);
+ ctx->stored_tail = 0;
+ ctx->stored_head = input->text.nbytes;
+ ctx->paused = 1;
+ return 1;
+ }
ctx->stored_tail = 0;
ctx->stored_head = input->text.nbytes - 6;
memcpy(ctx->stored, &input->text.bytes[6], ctx->stored_head);
@@ -697,14 +739,14 @@ read_bracketed_paste(int fd, union libterminput_input *input, struct libterminpu
ctx->stored_tail = ctx->stored_head = 0;
ctx->bracketed_paste = 0;
input->type = LIBTERMINPUT_BRACKETED_PASTE_END;
- return 0;
+ return 1;
}
- /* TODO test */
ctx->stored_tail = 0;
ctx->stored_head = input->text.nbytes - n;
+ memcpy(ctx->stored, &input->text.bytes[n], ctx->stored_head);
input->text.nbytes = n;
input->text.type = LIBTERMINPUT_TEXT;
- return 0;
+ return 1;
}
diff --git a/libterminput.h b/libterminput.h
index 95eea11..6029305 100644
--- a/libterminput.h
+++ b/libterminput.h
@@ -172,12 +172,13 @@ struct libterminput_state {
int inited; /* whether the input in initialised, not this struct */
enum libterminput_mod mods;
enum libterminput_flags flags;
- size_t stored_head;
- size_t stored_tail;
char bracketed_paste;
char mouse_tracking;
char meta;
char n;
+ size_t stored_head;
+ size_t stored_tail;
+ char paused;
char npartial;
char partial[7];
char key[44];
@@ -198,7 +199,7 @@ int libterminput_read(int fd, union libterminput_input *input, struct libterminp
inline int
libterminput_is_ready(union libterminput_input *input, struct libterminput_state *ctx)
{
- if (!ctx->inited)
+ if (!ctx->inited || ctx->paused)
return 0;
if (input->type == LIBTERMINPUT_KEYPRESS && input->keypress.times > 1)
return 1;
diff --git a/libterminput_is_ready.3 b/libterminput_is_ready.3
index 293d60e..0739e11 100644
--- a/libterminput_is_ready.3
+++ b/libterminput_is_ready.3
@@ -19,7 +19,11 @@ function check if a call to the
.BR libterminput_read (3)
function will skip reading from the file
descriptor passed to it because it already
-has read data buffered.
+has read data buffered. However, if there
+is buffered data but the library knows it
+it not enough to return something they,
+it will also return that there is nothing
+buffered.
.SH RETURN VALUE
The
diff --git a/test.c b/test.c
index 76a4654..86d9bfa 100644
--- a/test.c
+++ b/test.c
@@ -128,7 +128,9 @@ main(void)
#define TYPE(STR, T)\
do {\
- TEST(write(fds[1], STR, strlen(STR)) == (ssize_t)strlen(STR));\
+ alarm(5);\
+ if ((STR) && *(const char *)(STR))\
+ TEST(write(fds[1], STR, strlen(STR)) == (ssize_t)strlen(STR));\
do {\
TEST(libterminput_read(fds[0], &input, &ctx) == 1);\
} while (input.type == LIBTERMINPUT_NONE && libterminput_is_ready(&input, &ctx));\
@@ -138,8 +140,10 @@ main(void)
#define KEYPRESS_(STR1, STR2, STR3, STR4, KEY, MODS, TIMES)\
do {\
int times__ = (TIMES);\
+ alarm(5);\
stpcpy(stpcpy(stpcpy(stpcpy(buffer, STR1), STR2), STR3), STR4);\
- TEST(write(fds[1], buffer, strlen(buffer)) == (ssize_t)strlen(buffer));\
+ if (*buffer)\
+ TEST(write(fds[1], buffer, strlen(buffer)) == (ssize_t)strlen(buffer));\
for (; times__; times__--) {\
do {\
TEST(libterminput_read(fds[0], &input, &ctx) == 1);\
@@ -229,11 +233,34 @@ main(void)
TYPE("\033[201~", LIBTERMINPUT_BRACKETED_PASTE_END);
TYPE("x", LIBTERMINPUT_KEYPRESS);
-#ifdef TODO
TYPE("\033[200~", LIBTERMINPUT_BRACKETED_PASTE_START);
- TYPE("x", LIBTERMINPUT_TEXT);
-#endif
+ TYPE("x\033[201~", LIBTERMINPUT_TEXT);
+ TEST(input.text.nbytes == strlen("x"));
+ TEST(!memcmp(input.text.bytes, "x", strlen("x")));
+ TYPE(NULL, LIBTERMINPUT_BRACKETED_PASTE_END);
+ TYPE("\033[200~x", LIBTERMINPUT_BRACKETED_PASTE_START);
+ TYPE(NULL, LIBTERMINPUT_TEXT);
+ TEST(input.text.nbytes == strlen("x"));
+ TEST(!memcmp(input.text.bytes, "x", strlen("x")));
+ TYPE("\033[201x~x\033[201~x", LIBTERMINPUT_TEXT);
+ TEST(input.text.nbytes == strlen("\033[201x~x"));
+ TEST(!memcmp(input.text.bytes, "\033[201x~x", strlen("\033[201x~x")));
+ TYPE(NULL, LIBTERMINPUT_BRACKETED_PASTE_END);
+ TYPE(NULL, LIBTERMINPUT_KEYPRESS);
+ TYPE("\033[200~", LIBTERMINPUT_BRACKETED_PASTE_START);
TYPE("\033[201~", LIBTERMINPUT_BRACKETED_PASTE_END);
+ TYPE("\033[200~", LIBTERMINPUT_BRACKETED_PASTE_START);
+ TYPE("\033[201", LIBTERMINPUT_NONE);
+ TYPE("x\033[20", LIBTERMINPUT_TEXT);
+ TEST(input.text.nbytes == strlen("\033[201x"));
+ TEST(!memcmp(input.text.bytes, "\033[201x", strlen("\033[201x")));
+ TYPE("1", LIBTERMINPUT_NONE);
+ TYPE("~", LIBTERMINPUT_BRACKETED_PASTE_END);
+ TYPE("\033[200~\033[201~", LIBTERMINPUT_BRACKETED_PASTE_START);
+ TYPE(NULL, LIBTERMINPUT_BRACKETED_PASTE_END);
+ TYPE("\033[200~\033[201", LIBTERMINPUT_BRACKETED_PASTE_START);
+ TYPE("~", LIBTERMINPUT_BRACKETED_PASTE_END);
+
TYPE("\033[200^", LIBTERMINPUT_NONE);
TYPE("\033[200$", LIBTERMINPUT_NONE);
TYPE("\033[200@", LIBTERMINPUT_NONE);