mirror of
https://github.com/tmux/tmux.git
synced 2024-12-12 17:38:48 +00:00
Add a UTF-8 aware string length function and make UTF-8 in
status-left/status-right work properly. At the moment any top-bit-set characters are assumed to be UTF-8: a status-utf8 option to configure this will come shortly.
This commit is contained in:
parent
41d985ace3
commit
7d45e29683
114
screen-write.c
114
screen-write.c
@ -52,20 +52,126 @@ screen_write_putc(
|
||||
screen_write_cell(ctx, gc, NULL);
|
||||
}
|
||||
|
||||
/* Calculate string length. */
|
||||
size_t printflike1
|
||||
screen_write_strlen(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *msg;
|
||||
u_char *ptr, utf8buf[4];
|
||||
size_t left, size = 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
ptr = msg;
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr > 0x7f) { /* Assume this is UTF-8. */
|
||||
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||
|
||||
left = strlen(ptr);
|
||||
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||
memcpy(utf8buf, ptr, 2);
|
||||
ptr += 2;
|
||||
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||
memcpy(utf8buf, ptr, 3);
|
||||
ptr += 3;
|
||||
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||
memcpy(utf8buf, ptr, 4);
|
||||
ptr += 4;
|
||||
} else {
|
||||
*utf8buf = *ptr;
|
||||
ptr++;
|
||||
}
|
||||
size += utf8_width(utf8buf);
|
||||
} else {
|
||||
size++;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
return (size);
|
||||
}
|
||||
|
||||
/* Write string. */
|
||||
void printflike3
|
||||
screen_write_puts(
|
||||
struct screen_write_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *msg, *ptr;
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
screen_write_vnputs(ctx, -1, gc, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
for (ptr = msg; *ptr != '\0'; ptr++)
|
||||
screen_write_putc(ctx, gc, (u_char) *ptr);
|
||||
/* Write string with length limit (-1 for unlimited). */
|
||||
void printflike4
|
||||
screen_write_nputs(struct screen_write_ctx *ctx,
|
||||
ssize_t maxlen, struct grid_cell *gc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
screen_write_vnputs(ctx, maxlen, gc, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
screen_write_vnputs(struct screen_write_ctx *ctx,
|
||||
ssize_t maxlen, struct grid_cell *gc, const char *fmt, va_list ap)
|
||||
{
|
||||
char *msg;
|
||||
u_char *ptr, utf8buf[4];
|
||||
size_t left, size = 0;
|
||||
int width;
|
||||
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
|
||||
ptr = msg;
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr > 0x7f) { /* Assume this is UTF-8. */
|
||||
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||
|
||||
left = strlen(ptr);
|
||||
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||
memcpy(utf8buf, ptr, 2);
|
||||
ptr += 2;
|
||||
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||
memcpy(utf8buf, ptr, 3);
|
||||
ptr += 3;
|
||||
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||
memcpy(utf8buf, ptr, 4);
|
||||
ptr += 4;
|
||||
} else {
|
||||
*utf8buf = *ptr;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
width = utf8_width(utf8buf);
|
||||
if (maxlen > 0 && size + width > (size_t) maxlen) {
|
||||
while (size < (size_t) maxlen) {
|
||||
screen_write_putc(ctx, gc, ' ');
|
||||
size++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
size += width;
|
||||
|
||||
gc->flags |= GRID_FLAG_UTF8;
|
||||
screen_write_cell(ctx, gc, utf8buf);
|
||||
gc->flags &= ~GRID_FLAG_UTF8;
|
||||
|
||||
} else {
|
||||
if (maxlen > 0 && size > (size_t) maxlen)
|
||||
break;
|
||||
|
||||
size++;
|
||||
screen_write_putc(ctx, gc, *ptr);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
xfree(msg);
|
||||
}
|
||||
|
19
status.c
19
status.c
@ -47,8 +47,8 @@ status_redraw(struct client *c)
|
||||
struct window_pane *wp;
|
||||
struct screen *sc = NULL, old_status;
|
||||
char *left, *right, *text, *ptr;
|
||||
size_t llen, rlen, offset, xx, yy, sy;
|
||||
size_t size, start, width;
|
||||
size_t llen, llen2, rlen, rlen2, offset;
|
||||
size_t xx, yy, sy, size, start, width;
|
||||
struct grid_cell stdgc, gc;
|
||||
int larrow, rarrow;
|
||||
|
||||
@ -78,15 +78,16 @@ status_redraw(struct client *c)
|
||||
left = status_replace(s, options_get_string(
|
||||
&s->options, "status-left"), c->status_timer.tv_sec);
|
||||
llen = options_get_number(&s->options, "status-left-length");
|
||||
if (strlen(left) < llen)
|
||||
llen = strlen(left);
|
||||
left[llen] = '\0';
|
||||
llen2 = screen_write_strlen("%s", left);
|
||||
if (llen2 < llen)
|
||||
llen = llen2;
|
||||
|
||||
right = status_replace(s, options_get_string(
|
||||
&s->options, "status-right"), c->status_timer.tv_sec);
|
||||
rlen = options_get_number(&s->options, "status-right-length");
|
||||
if (strlen(right) < rlen)
|
||||
rlen = strlen(right);
|
||||
rlen2 = screen_write_strlen("%s", right);
|
||||
if (rlen2 < rlen)
|
||||
rlen = rlen2;
|
||||
right[rlen] = '\0';
|
||||
|
||||
/*
|
||||
@ -163,7 +164,7 @@ draw:
|
||||
screen_write_start(&ctx, NULL, &c->status);
|
||||
if (llen != 0) {
|
||||
screen_write_cursormove(&ctx, 0, yy);
|
||||
screen_write_puts(&ctx, &stdgc, "%s ", left);
|
||||
screen_write_nputs(&ctx, llen + 1, &stdgc, "%s ", left);
|
||||
if (larrow)
|
||||
screen_write_putc(&ctx, &stdgc, ' ');
|
||||
} else {
|
||||
@ -220,7 +221,7 @@ draw:
|
||||
/* Draw the last item. */
|
||||
if (rlen != 0) {
|
||||
screen_write_cursormove(&ctx, c->tty.sx - rlen - 1, yy);
|
||||
screen_write_puts(&ctx, &stdgc, " %s", right);
|
||||
screen_write_nputs(&ctx, rlen + 1, &stdgc, " %s", right);
|
||||
}
|
||||
|
||||
/* Draw the arrows. */
|
||||
|
9
tmux.h
9
tmux.h
@ -1347,8 +1347,13 @@ void grid_view_delete_cells(struct grid *, u_int, u_int, u_int);
|
||||
void screen_write_start(
|
||||
struct screen_write_ctx *, struct window_pane *, struct screen *);
|
||||
void screen_write_stop(struct screen_write_ctx *);
|
||||
void printflike3 screen_write_puts(
|
||||
struct screen_write_ctx *, struct grid_cell *, const char *, ...);
|
||||
size_t printflike1 screen_write_strlen(const char *, ...);
|
||||
void printflike3 screen_write_puts(struct screen_write_ctx *,
|
||||
struct grid_cell *, const char *, ...);
|
||||
void printflike4 screen_write_nputs(struct screen_write_ctx *,
|
||||
ssize_t, struct grid_cell *, const char *, ...);
|
||||
void screen_write_vnputs(struct screen_write_ctx *,
|
||||
ssize_t, struct grid_cell *, const char *, va_list);
|
||||
void screen_write_putc(
|
||||
struct screen_write_ctx *, struct grid_cell *, u_char);
|
||||
void screen_write_copy(struct screen_write_ctx *,
|
||||
|
Loading…
Reference in New Issue
Block a user