version 1.23, 2021/03/11 06:41:04 |
version 1.24, 2021/08/22 15:33:14 |
|
|
width_after); |
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. */ |
/* Draw multiple characters. */ |
static void |
static void |
format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch, |
format_draw_many(struct screen_write_ctx *ctx, struct style *sy, char ch, |
|
|
format_width(const char *expanded) |
format_width(const char *expanded) |
{ |
{ |
const char *cp, *end; |
const char *cp, *end; |
u_int n, width = 0; |
u_int n, leading_width, width = 0; |
struct utf8_data ud; |
struct utf8_data ud; |
enum utf8_state more; |
enum utf8_state more; |
|
|
cp = expanded; |
cp = expanded; |
while (*cp != '\0') { |
while (*cp != '\0') { |
if (*cp == '#') { |
if (*cp == '#') { |
for (n = 1; cp[n] == '#'; n++) |
end = format_leading_hashes(cp, &n, &leading_width); |
/* nothing */; |
width += leading_width; |
if (cp[n] != '[') { |
cp = end; |
width += n; |
if (*cp == '#') { |
cp += n; |
end = format_skip(cp + 2, "]"); |
continue; |
if (end == NULL) |
|
return (0); |
|
cp = end + 1; |
} |
} |
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; |
|
} |
|
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) { |
} else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { |
while (*++cp != '\0' && more == UTF8_MORE) |
while (*++cp != '\0' && more == UTF8_MORE) |
more = utf8_append(&ud, *cp); |
more = utf8_append(&ud, *cp); |
|
|
{ |
{ |
char *copy, *out; |
char *copy, *out; |
const char *cp = expanded, *end; |
const char *cp = expanded, *end; |
u_int even, n, width = 0; |
u_int n, width = 0, leading_width; |
struct utf8_data ud; |
struct utf8_data ud; |
enum utf8_state more; |
enum utf8_state more; |
|
|
|
|
if (width >= limit) |
if (width >= limit) |
break; |
break; |
if (*cp == '#') { |
if (*cp == '#') { |
for (end = cp + 1; *end == '#'; end++) |
end = format_leading_hashes(cp, &n, &leading_width); |
/* nothing */; |
if (leading_width > limit - width) |
n = end - cp; |
leading_width = limit - width; |
if (*end != '[') { |
if (leading_width != 0) { |
if (n > limit - width) |
if (n == 1) |
n = limit - width; |
*out++ = '#'; |
memcpy(out, cp, n); |
else { |
out += n; |
memset(out, '#', 2 * leading_width); |
width += n; |
out += 2 * leading_width; |
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++; |
|
} |
} |
|
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; |
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) { |
} else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { |
while (*++cp != '\0' && more == UTF8_MORE) |
while (*++cp != '\0' && more == UTF8_MORE) |
more = utf8_append(&ud, *cp); |
more = utf8_append(&ud, *cp); |
|
|
{ |
{ |
char *copy, *out; |
char *copy, *out; |
const char *cp = expanded, *end; |
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; |
struct utf8_data ud; |
enum utf8_state more; |
enum utf8_state more; |
|
|
|
|
out = copy = xcalloc(1, strlen(expanded) + 1); |
out = copy = xcalloc(1, strlen(expanded) + 1); |
while (*cp != '\0') { |
while (*cp != '\0') { |
if (*cp == '#') { |
if (*cp == '#') { |
for (end = cp + 1; *end == '#'; end++) |
end = format_leading_hashes(cp, &n, &leading_width); |
/* 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; |
|
if (width <= skip) { |
if (width <= skip) { |
if (skip - width >= n) |
if (skip - width >= leading_width) |
n = 0; |
copy_width = 0; |
else |
else |
n -= (skip - width); |
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; |
|
} |
} |
} |
if (n != 0) { |
width += leading_width; |
/* |
cp = end; |
* Copy the full amount because it hasn't been |
if (*cp == '#') { |
* escaped yet. |
end = format_skip(cp + 2, "]"); |
*/ |
if (end == NULL) |
memcpy(out, cp, old_n); |
break; |
out += old_n; |
memcpy(out, cp, end + 1 - cp); |
|
out += (end + 1 - cp); |
|
cp = end + 1; |
} |
} |
cp += old_n; |
|
width += (old_n / 2) - even; |
|
|
|
if (even) { |
|
if (width > skip) |
|
*out++ = '['; |
|
width++; |
|
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) { |
} else if ((more = utf8_open(&ud, *cp)) == UTF8_MORE) { |
while (*++cp != '\0' && more == UTF8_MORE) |
while (*++cp != '\0' && more == UTF8_MORE) |
more = utf8_append(&ud, *cp); |
more = utf8_append(&ud, *cp); |