diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-10-20 17:33:34 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-10-20 17:33:34 +0000 |
commit | d89b749326b0670ac53e05f47aa31d57775fcafa (patch) | |
tree | 9cf5d1cc8cc90259d71b0a3428953022adb590e5 /usr.bin/tmux | |
parent | 7ca7f75f02ff9e27a8d6213d9a633327c5586e4c (diff) |
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.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r-- | usr.bin/tmux/screen-write.c | 96 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 4 | ||||
-rw-r--r-- | usr.bin/tmux/tty.c | 15 |
3 files changed, 76 insertions, 39 deletions
diff --git a/usr.bin/tmux/screen-write.c b/usr.bin/tmux/screen-write.c index 57a4012d6c3..1aaa1ba5fc4 100644 --- a/usr.bin/tmux/screen-write.c +++ b/usr.bin/tmux/screen-write.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-write.c,v 1.34 2009/10/20 16:32:23 nicm Exp $ */ +/* $OpenBSD: screen-write.c,v 1.35 2009/10/20 17:33:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 110db121310..42883a584a8 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.141 2009/10/20 14:22:57 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.142 2009/10/20 17:33:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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]; diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index d2d1490adb6..bba5c95b281 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.52 2009/10/20 16:32:23 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.53 2009/10/20 17:33:33 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 |