summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compat.h6
-rw-r--r--src/escape.c11
-rw-r--r--src/input.c9
-rw-r--r--src/screen.c11
-rw-r--r--src/selection.c20
-rw-r--r--src/text_run.c7
6 files changed, 38 insertions, 26 deletions
diff --git a/src/compat.h b/src/compat.h
index c0ae6fa..dc345d0 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -209,10 +209,8 @@ static inline bool term_has_prefix_ci(const char *s, const char *prefix)
for (; *prefix; prefix++, s++) {
unsigned char a = (unsigned char)*s;
unsigned char b = (unsigned char)*prefix;
- if (a >= 'A' && a <= 'Z')
- a += 'a' - 'A';
- if (b >= 'A' && b <= 'Z')
- b += 'a' - 'A';
+ a |= ((unsigned)(a - 'A') < 26) ? 0x20 : 0;
+ b |= ((unsigned)(b - 'A') < 26) ? 0x20 : 0;
if (a != b)
return false;
}
diff --git a/src/escape.c b/src/escape.c
index 1e56d77..7956017 100644
--- a/src/escape.c
+++ b/src/escape.c
@@ -76,7 +76,16 @@ static int dcs_decode_hex(const char *s, int len, char *out, int cap)
{
if (len & 1) return -1;
int n = 0;
- for (int i = 0; i < len; i += 2) {
+ int i = 0;
+ for (; i + 4 <= len; i += 4) {
+ int h0 = hex_val[(unsigned char)s[i]], l0 = hex_val[(unsigned char)s[i + 1]];
+ int h1 = hex_val[(unsigned char)s[i + 2]], l1 = hex_val[(unsigned char)s[i + 3]];
+ if ((h0 | l0 | h1 | l1) < 0 || n + 2 > cap) return -1;
+ out[n] = (char)(h0 << 4 | l0);
+ out[n + 1] = (char)(h1 << 4 | l1);
+ n += 2;
+ }
+ if (i < len) {
int hi = hex_val[(unsigned char)s[i]], lo = hex_val[(unsigned char)s[i + 1]];
if ((hi | lo) < 0 || n >= cap) return -1;
out[n++] = (char)(hi << 4 | lo);
diff --git a/src/input.c b/src/input.c
index 798ffc0..960f488 100644
--- a/src/input.c
+++ b/src/input.c
@@ -716,11 +716,10 @@ struct term_input_result term_input_encode_paste(const struct term_modes *m,
size_t body = sb_len(&sb, buf);
for (size_t i = 0; i < len;) {
if (sb.overflow) break;
- size_t start = i;
- while (i < len && (unsigned char)text[i] >= 0x20 && (unsigned char)text[i] < 0x7f)
- i++;
- if (i > start) {
- sb_bytes(&sb, text + start, i - start);
+ size_t run = term_scan_printable_span(text + i, len - i, 0x7f);
+ if (run > 0) {
+ sb_bytes(&sb, text + i, run);
+ i += run;
continue;
}
unsigned char c = (unsigned char)text[i];
diff --git a/src/screen.c b/src/screen.c
index e3f0191..99e788c 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -1024,10 +1024,13 @@ void term_free(struct term *t)
screen_free(&t->scr);
screen_free(&t->alt_scr);
screen_free(&t->spare);
- struct grow_buf *bufs[] = { &t->resize.row, &t->resize.rows, &t->resize.cells, &t->resize.line,
- &t->resize.pull, &t->resize.rest, &t->resize.lens };
- for (size_t i = 0; i < sizeof(bufs) / sizeof(bufs[0]); i++)
- free(bufs[i]->data);
+ free(t->resize.row.data);
+ free(t->resize.rows.data);
+ free(t->resize.cells.data);
+ free(t->resize.line.data);
+ free(t->resize.pull.data);
+ free(t->resize.rest.data);
+ free(t->resize.lens.data);
free(t->ascii_ends.data);
free(t->ascii_tail.data);
term_hist_free(&t->hist);
diff --git a/src/selection.c b/src/selection.c
index 4602d8f..e4a3e35 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -26,7 +26,15 @@ static char *link_at_text(const struct term *t, struct term_vector2i cell)
while (end < t->cols && cells[end].c > ' ' && cells[end].c < 127) end++;
char *text = malloc((size_t)(end - start) + 1);
if (!text) return NULL;
- for (int c = start; c < end; c++) text[c - start] = cells[c].c;
+ int c = start;
+ for (; c + 4 <= end; c += 4) {
+ uint32_t packed = (cells[c].c & 0xff) |
+ ((cells[c + 1].c & 0xff) << 8) |
+ ((cells[c + 2].c & 0xff) << 16) |
+ ((cells[c + 3].c & 0xff) << 24);
+ memcpy(text + (c - start), &packed, 4);
+ }
+ for (; c < end; c++) text[c - start] = (char)cells[c].c;
text[end - start] = 0;
size_t scheme = 8;
char *url = strstr(text, "https://");
@@ -307,9 +315,8 @@ static struct term_sel_point view_to_sel_point(const struct lines *L, int x, int
if (!view_row_line(L, y, &id, &seg))
return (struct term_sel_point){ .line_id = L->first };
const struct cell *cells = line_seg_cells(L, id, seg, NULL, NULL);
- if (cells)
- while (x > 0 && (cells[x].flags & CELL_WRAP_PAD))
- x--;
+ if (cells && x > 0 && (cells[x].flags & CELL_WRAP_PAD))
+ x--;
return (struct term_sel_point){
.line_id = id,
.cell_off = line_seg_start_off(L, id, seg) + (uint32_t)x,
@@ -385,9 +392,8 @@ static void unit_span(const struct lines *L, int x, int y, bool right_half,
}
const struct cell *row = term_screen_view_row(t, y);
- if (row)
- while (x > 0 && (row[x].flags & CELL_WRAP_PAD))
- x--;
+ if (row && x > 0 && (row[x].flags & CELL_WRAP_PAD))
+ x--;
int left = x, right = x;
int kind = row ? word_class(row[x].c) : 0;
while (left > 0 && row && word_class(row[left - 1].c) == kind)
diff --git a/src/text_run.c b/src/text_run.c
index 9df7ac0..bf0e8a9 100644
--- a/src/text_run.c
+++ b/src/text_run.c
@@ -326,11 +326,8 @@ struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *res
unsigned char c = (unsigned char)buf[i];
if (c >= 0x20 && c < 0x7f) {
int room = max_cols - cx < len - i ? max_cols - cx : len - i;
- int n = 1;
- while (n < room && n < 16 && (unsigned char)(buf[i + n] - 0x20) < 0x5f)
- n++;
- if (n == 16 && n < room)
- n += (int)scan_printable_span(buf + i + 16, (size_t)(room - 16), 0x7f);
+ int n = (int)scan_printable_span(buf + i, (size_t)room, 0x7f);
+ if (!n) n = 1;
bytes_copy_small(dst + o, buf + i, n);
i += n;
o += n;