diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2021-08-22 15:33:15 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2021-08-22 15:33:15 +0000 |
commit | b2ff18622a5ed25ab7153d877c676b8069a193fc (patch) | |
tree | f719ee8ecf35e8e4060b8945f37602c497c30ba0 /usr.bin | |
parent | 35370d24a359f4e6e95a36b7345e6a115be37601 (diff) |
Fix handling of leading #s when working out width.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/tmux/format-draw.c | 199 |
1 files changed, 83 insertions, 116 deletions
diff --git a/usr.bin/tmux/format-draw.c b/usr.bin/tmux/format-draw.c index b921fc91a24..057ad792b55 100644 --- a/usr.bin/tmux/format-draw.c +++ b/usr.bin/tmux/format-draw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: format-draw.c,v 1.23 2021/03/11 06:41:04 nicm Exp $ */ +/* $OpenBSD: format-draw.c,v 1.24 2021/08/22 15:33:14 nicm Exp $ */ /* * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> @@ -632,6 +632,36 @@ format_draw_absolute_centre(struct screen_write_ctx *octx, u_int available, width_after); } +/* Get width and count of any leading #s. */ +static const char * +format_leading_hashes(const char *cp, u_int *n, u_int *width) +{ + for (*n = 0; cp[*n] == '#'; (*n)++) + /* nothing */; + if (*n == 0) { + *width = 0; + return (cp); + } + if (cp[*n] != '[') { + if ((*n % 2) == 0) + *width = (*n / 2); + else + *width = (*n / 2) + 1; + return (cp + *n); + } + *width = (*n / 2); + if ((*n % 2) == 0) { + /* + * An even number of #s means that all #s are escaped, so not a + * style. The caller should not skip this. Return pointing to + * the [. + */ + return (cp + *n); + } + /* This is a style, so return pointing to the #. */ + return (cp + *n - 1); +} + /* Draw multiple characters. */ static void format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch, @@ -1002,37 +1032,22 @@ u_int format_width(const char *expanded) { const char *cp, *end; - u_int n, width = 0; + u_int n, leading_width, width = 0; struct utf8_data ud; enum utf8_state more; cp = expanded; while (*cp != '\0') { if (*cp == '#') { - for (n = 1; cp[n] == '#'; n++) - /* nothing */; - if (cp[n] != '[') { - width += n; - cp += n; - continue; - } - width += (n / 2); /* one for each ## */ - - if ((n % 2) == 0) { - /* - * An even number of #s means that all #s are - * escaped, so not a style. - */ - width++; /* one for the [ */ - cp += (n + 1); - continue; + end = format_leading_hashes(cp, &n, &leading_width); + width += leading_width; + cp = end; + if (*cp == '#') { + end = format_skip(cp + 2, "]"); + if (end == NULL) + return (0); + cp = end + 1; } - cp += (n - 1); /* point to the [ */ - - end = format_skip(cp + 2, "]"); - if (end == NULL) - return (0); - cp = end + 1; } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { while (*++cp != '\0' && more == UTF8_MORE) more = utf8_append(&ud, *cp); @@ -1059,7 +1074,7 @@ format_trim_left(const char *expanded, u_int limit) { char *copy, *out; const char *cp = expanded, *end; - u_int even, n, width = 0; + u_int n, width = 0, leading_width; struct utf8_data ud; enum utf8_state more; @@ -1068,44 +1083,27 @@ format_trim_left(const char *expanded, u_int limit) if (width >= limit) break; if (*cp == '#') { - for (end = cp + 1; *end == '#'; end++) - /* nothing */; - n = end - cp; - if (*end != '[') { - if (n > limit - width) - n = limit - width; - memcpy(out, cp, n); - out += n; - width += n; - cp = end; - continue; - } - even = ((n % 2) == 0); - - n /= 2; - if (n > limit - width) - n = limit - width; - width += n; - n *= 2; - memcpy(out, cp, n); - out += n; - - if (even) { - if (width + 1 <= limit) { - *out++ = '['; - width++; + end = format_leading_hashes(cp, &n, &leading_width); + if (leading_width > limit - width) + leading_width = limit - width; + if (leading_width != 0) { + if (n == 1) + *out++ = '#'; + else { + memset(out, '#', 2 * leading_width); + out += 2 * leading_width; } + width += leading_width; + } + cp = end; + if (*cp == '#') { + end = format_skip(cp + 2, "]"); + if (end == NULL) + break; + memcpy(out, cp, end + 1 - cp); + out += (end + 1 - cp); cp = end + 1; - continue; } - cp = end - 1; - - end = format_skip(cp + 2, "]"); - if (end == NULL) - break; - memcpy(out, cp, end + 1 - cp); - out += (end + 1 - cp); - cp = end + 1; } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { while (*++cp != '\0' && more == UTF8_MORE) more = utf8_append(&ud, *cp); @@ -1137,7 +1135,8 @@ format_trim_right(const char *expanded, u_int limit) { char *copy, *out; const char *cp = expanded, *end; - u_int width = 0, total_width, skip, old_n, even, n; + u_int width = 0, total_width, skip, n; + u_int leading_width, copy_width; struct utf8_data ud; enum utf8_state more; @@ -1149,64 +1148,32 @@ format_trim_right(const char *expanded, u_int limit) out = copy = xcalloc(1, strlen(expanded) + 1); while (*cp != '\0') { if (*cp == '#') { - for (end = cp + 1; *end == '#'; end++) - /* nothing */; - old_n = n = end - cp; - if (*end != '[') { - if (width <= skip) { - if (skip - width >= n) - n = 0; - else - n -= (skip - width); - } - if (n != 0) { - memcpy(out, cp, n); - out += n; - } - - /* - * The width always increases by the full - * amount even if we can't copy anything yet. - */ - width += old_n; - cp = end; - continue; - } - even = ((n % 2) == 0); - - n /= 2; + end = format_leading_hashes(cp, &n, &leading_width); if (width <= skip) { - if (skip - width >= n) - n = 0; + if (skip - width >= leading_width) + copy_width = 0; else - n -= (skip - width); - } - if (n != 0) { - /* - * Copy the full amount because it hasn't been - * escaped yet. - */ - memcpy(out, cp, old_n); - out += old_n; - } - cp += old_n; - width += (old_n / 2) - even; - - if (even) { - if (width > skip) - *out++ = '['; - width++; - continue; + copy_width -= (skip - width); + } else + copy_width = leading_width; + if (copy_width != 0) { + if (n == 1) + *out++ = '#'; + else { + memset(out, '#', 2 * copy_width); + out += 2 * copy_width; + } } - cp = end - 1; - - end = format_skip(cp + 2, "]"); - if (end == NULL) { - break; + width += leading_width; + cp = end; + if (*cp == '#') { + end = format_skip(cp + 2, "]"); + if (end == NULL) + break; + memcpy(out, cp, end + 1 - cp); + out += (end + 1 - cp); + cp = end + 1; } - memcpy(out, cp, end + 1 - cp); - out += (end + 1 - cp); - cp = end + 1; } else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { while (*++cp != '\0' && more == UTF8_MORE) more = utf8_append(&ud, *cp); |