summaryrefslogtreecommitdiffstats
path: root/screen-write.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-10-20 17:33:33 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-10-20 17:33:33 +0000
commit62f234ce3b3fb10633f8bbb1d4159cd5c179345a (patch)
treeac8494b4eadbe71c3b7f7aabd30a725035676f20 /screen-write.c
parent387f4d42ccfb9aab1b8d5f10176dac2a3209c3fa (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 'screen-write.c')
-rw-r--r--screen-write.c94
1 files changed, 66 insertions, 28 deletions
diff --git a/screen-write.c b/screen-write.c
index 9f98153b..9ed8f93b 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -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