mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 01:48:47 +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_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
||||||
void screen_write_overwrite(struct screen_write_ctx *);
|
void screen_write_overwrite(struct screen_write_ctx *);
|
||||||
|
int screen_write_combine(struct screen_write_ctx *, u_char *);
|
||||||
|
|
||||||
/* Initialise writing with a window. */
|
/* Initialise writing with a window. */
|
||||||
void
|
void
|
||||||
@ -977,8 +978,8 @@ screen_write_cell(
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
struct grid_utf8 gu, *tmp_gu;
|
struct grid_utf8 gu;
|
||||||
u_int width, xx, i;
|
u_int width, xx;
|
||||||
struct grid_cell tmp_gc, *tmp_gcp;
|
struct grid_cell tmp_gc, *tmp_gcp;
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
|
|
||||||
@ -1003,34 +1004,15 @@ screen_write_cell(
|
|||||||
(s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
|
(s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
|
||||||
return;
|
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 (width == 0) {
|
||||||
if (s->cx == 0)
|
if (screen_write_combine(ctx, udata) == 0) {
|
||||||
return;
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
tmp_gcp = grid_view_get_cell(gd, s->cx - 1, s->cy);
|
tty_write(tty_cmd_utf8character, &ttyctx);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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;
|
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
|
* 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
|
* 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;
|
} __packed;
|
||||||
|
|
||||||
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */
|
/* 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 {
|
struct grid_utf8 {
|
||||||
u_char width;
|
u_char width;
|
||||||
u_char data[UTF8_SIZE];
|
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
|
void
|
||||||
tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx)
|
tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx)
|
||||||
{
|
{
|
||||||
u_char *ptr = ctx->ptr;
|
struct window_pane *wp = ctx->wp;
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < UTF8_SIZE; i++) {
|
/*
|
||||||
if (ptr[i] == 0xff)
|
* Cannot rely on not being a partial character, so just redraw the
|
||||||
break;
|
* whole line.
|
||||||
tty_putc(tty, ptr[i]);
|
*/
|
||||||
}
|
tty_draw_line(tty, wp->screen, ctx->ocy, wp->xoff, wp->yoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user