summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2009-10-20 17:33:34 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2009-10-20 17:33:34 +0000
commitd89b749326b0670ac53e05f47aa31d57775fcafa (patch)
tree9cf5d1cc8cc90259d71b0a3428953022adb590e5 /usr.bin
parent7ca7f75f02ff9e27a8d6213d9a633327c5586e4c (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')
-rw-r--r--usr.bin/tmux/screen-write.c96
-rw-r--r--usr.bin/tmux/tmux.h4
-rw-r--r--usr.bin/tmux/tty.c15
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