1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
int
libterminput_read_bracketed_paste__(int fd, union libterminput_input *input, struct libterminput_state *ctx)
{
ssize_t r;
size_t n;
size_t i;
/* 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. */
/* Check for bracketed paste end marker to output LIBTERMINPUT_BRACKETED_PASTE_END
* and stop, and read more if we don't have it; the marker will be at the
* beginning as the function will stop when it encounteres it and output the
* text pasted before it */
if (ctx->stored_head - ctx->stored_tail) {
/* If we have input buffered, unpause and handle it */
ctx->paused = 0;
n = ctx->stored_head - ctx->stored_tail;
if (!strncmp(&ctx->stored[ctx->stored_tail], "\033[201~", n < 6U ? n : 6U)) {
/* If starting with bracketed paste end marker, output LIBTERMINPUT_BRACKETED_PASTE_END, */
if (n >= 6U) {
ctx->stored_tail += 6U;
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;
}
/* otherwise, but if the buffered input is a truncating of the marker,
* move over the data from the stored input buffer to the input buffer
* and store continue reading input */
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;
} else {
/* If the buffered input does not begin with the bracketed paste end marker,
* or a truncation of it, move over the data from the stored input buffer
* to the input buffer */
input->text.nbytes = ctx->stored_head - ctx->stored_tail;
memcpy(input->text.bytes, &ctx->stored[ctx->stored_tail], input->text.nbytes);
ctx->stored_head = ctx->stored_tail = 0;
}
} else {
/* If we don't have any input buffered, read some */
r = read(fd, input->text.bytes, sizeof(input->text.bytes));
if (r <= 0)
return (int)r;
input->text.nbytes = (size_t)r;
}
/* Count the number of bytes available before a bracketed paste end
* marker, or a truncation of it at the end of the input buffer */
for (n = 0; n + 5U < input->text.nbytes; n++) {
if (!strncmp(&input->text.bytes[n], "\033[201~", 6U))
break;
}
for (i = 5U; i--;) {
if (n + i < input->text.nbytes) {
if (!strncmp(&input->text.bytes[n], "\033[201~", i + 1U))
break;
n += 1;
}
}
/* Of there was pasted input, output it */
if (n) {
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 1;
}
/* If the input is solely a truncation of the bracketed paste
* end marker, output that we do not have any complete input */
if (input->text.nbytes < 6U) {
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;
}
/* If the input starts with a bracketed paste end marker,
* output it and store the rest of the input buffer for
* later processing */
ctx->stored_tail = 0;
ctx->stored_head = input->text.nbytes - 6U;
memcpy(ctx->stored, &input->text.bytes[6], ctx->stored_head);
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;
}
|