mirror of
https://github.com/tmux/tmux.git
synced 2024-12-12 17:38:48 +00:00
UTF-8 combined character fixes.
Thai can have treble combinations (1 x width=1 then 2 x width=0) so bump the UTF-8 cell data size to 9 and alter the code to allow this. Also break off the combining code into a separate function, handle any further combining beyond the buffer size by replacing the character with _s, and when redrawing the UTF-8 character don't assume the first part has just been printed, redraw the entire line.
This commit is contained in:
parent
387f4d42cc
commit
62f234ce3b
@ -24,6 +24,7 @@
|
||||
|
||||
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
||||
void screen_write_overwrite(struct screen_write_ctx *);
|
||||
int screen_write_combine(struct screen_write_ctx *, u_char *);
|
||||
|
||||
/* Initialise writing with a window. */
|
||||
void
|
||||
@ -977,8 +978,8 @@ screen_write_cell(
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct tty_ctx ttyctx;
|
||||
struct grid_utf8 gu, *tmp_gu;
|
||||
u_int width, xx, i;
|
||||
struct grid_utf8 gu;
|
||||
u_int width, xx;
|
||||
struct grid_cell tmp_gc, *tmp_gcp;
|
||||
int insert = 0;
|
||||
|
||||
@ -1003,34 +1004,15 @@ screen_write_cell(
|
||||
(s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
|
||||
return;
|
||||
|
||||
/* If the width is zero, combine onto the previous character. */
|
||||
/*
|
||||
* If the width is zero, combine onto the previous character, if
|
||||
* there is space.
|
||||
*/
|
||||
if (width == 0) {
|
||||
if (s->cx == 0)
|
||||
return;
|
||||
tmp_gcp = grid_view_get_cell(gd, s->cx - 1, s->cy);
|
||||
if (!(tmp_gcp->flags & GRID_FLAG_UTF8)) {
|
||||
tmp_gcp->flags |= GRID_FLAG_UTF8;
|
||||
memset(&gu.data, 0xff, sizeof gu.data);
|
||||
*gu.data = tmp_gcp->data;
|
||||
gu.width = 1;
|
||||
grid_view_set_utf8(gd, s->cx - 1, s->cy, &gu);
|
||||
if (screen_write_combine(ctx, udata) == 0) {
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
tty_write(tty_cmd_utf8character, &ttyctx);
|
||||
}
|
||||
tmp_gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
|
||||
|
||||
for (i = 0; i < UTF8_SIZE; i++) {
|
||||
if (tmp_gu->data[i] == 0xff)
|
||||
break;
|
||||
}
|
||||
memcpy(tmp_gu->data + i, udata, UTF8_SIZE - i);
|
||||
|
||||
/*
|
||||
* Assume the previous character has just been input.
|
||||
* XXX There is no guarantee this is true, need to redraw
|
||||
* entire line.
|
||||
*/
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
ttyctx.ptr = udata;
|
||||
tty_write(tty_cmd_utf8character, &ttyctx);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1101,6 +1083,62 @@ screen_write_cell(
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine a UTF-8 zero-width character onto the previous. */
|
||||
int
|
||||
screen_write_combine(struct screen_write_ctx *ctx, u_char *udata)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_cell *gc;
|
||||
struct grid_utf8 *gu, tmp_gu;
|
||||
u_int i, old_size, new_size;
|
||||
|
||||
/* Can't combine if at 0. */
|
||||
if (s->cx == 0)
|
||||
return (-1);
|
||||
|
||||
/* Retrieve the previous cell and convert to UTF-8 if not already. */
|
||||
gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
|
||||
if (!(gc->flags & GRID_FLAG_UTF8)) {
|
||||
memset(&tmp_gu.data, 0xff, sizeof tmp_gu.data);
|
||||
*tmp_gu.data = gc->data;
|
||||
tmp_gu.width = 1;
|
||||
|
||||
grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu);
|
||||
gc->flags |= GRID_FLAG_UTF8;
|
||||
}
|
||||
|
||||
/* Get the previous cell's UTF-8 data. */
|
||||
gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
|
||||
|
||||
/* Find the new size. */
|
||||
for (new_size = 0; new_size < UTF8_SIZE; new_size++) {
|
||||
if (udata[new_size] == 0xff)
|
||||
break;
|
||||
}
|
||||
|
||||
/* And the old size. */
|
||||
for (old_size = 0; old_size < UTF8_SIZE; old_size++) {
|
||||
if (gu->data[old_size] == 0xff)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If there isn't space, scrap this character. */
|
||||
if (old_size + new_size > UTF8_SIZE) {
|
||||
for (i = 0; i < gu->width && i != UTF8_SIZE; i++)
|
||||
gu->data[i] = '_';
|
||||
if (i != UTF8_SIZE)
|
||||
gu->data[i] = 0xff;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Otherwise save the character. */
|
||||
memcpy(gu->data + old_size, udata, new_size);
|
||||
if (old_size + new_size != UTF8_SIZE)
|
||||
gu->data[old_size + new_size] = 0xff;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* UTF-8 wide characters are a bit of an annoyance. They take up more than one
|
||||
* cell on the screen, so following cells must not be drawn by marking them as
|
||||
|
2
tmux.h
2
tmux.h
@ -516,7 +516,7 @@ struct grid_cell {
|
||||
} __packed;
|
||||
|
||||
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */
|
||||
#define UTF8_SIZE 8
|
||||
#define UTF8_SIZE 9
|
||||
struct grid_utf8 {
|
||||
u_char width;
|
||||
u_char data[UTF8_SIZE];
|
||||
|
13
tty.c
13
tty.c
@ -874,14 +874,13 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
u_char *ptr = ctx->ptr;
|
||||
size_t i;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
|
||||
for (i = 0; i < UTF8_SIZE; i++) {
|
||||
if (ptr[i] == 0xff)
|
||||
break;
|
||||
tty_putc(tty, ptr[i]);
|
||||
}
|
||||
/*
|
||||
* Cannot rely on not being a partial character, so just redraw the
|
||||
* whole line.
|
||||
*/
|
||||
tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff);
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user