summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--grid-utf8.c96
-rw-r--r--grid.c16
-rw-r--r--screen-write.c66
-rw-r--r--tmux.12
-rw-r--r--tmux.h16
-rw-r--r--tty.c14
-rw-r--r--window-copy.c15
8 files changed, 157 insertions, 70 deletions
diff --git a/Makefile b/Makefile
index 0f6f2707..b0caca92 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@ SRCS= attributes.c cfg.c client.c clock.c \
cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \
cmd-up-pane.c cmd-display-message.c cmd-display-panes.c \
cmd-pipe-pane.c cmd.c \
- colour.c environ.c grid-view.c grid.c input-keys.c \
+ colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \
imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \
layout-set.c layout.c log.c job.c \
mode-key.c names.c options-cmd.c options.c paste.c procname.c \
diff --git a/grid-utf8.c b/grid-utf8.c
new file mode 100644
index 00000000..5e5cad74
--- /dev/null
+++ b/grid-utf8.c
@@ -0,0 +1,96 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+
+#include "tmux.h"
+
+/*
+ * Grid UTF-8 utility functions.
+ */
+
+/* Calculate UTF-8 grid cell size. Data is terminated by 0xff. */
+size_t
+grid_utf8_size(const struct grid_utf8 *gu)
+{
+ size_t size;
+
+ for (size = 0; size < sizeof gu->data; size++) {
+ if (gu->data[size] == 0xff)
+ break;
+ }
+ return (size);
+}
+
+/* Copy UTF-8 out into a buffer. */
+size_t
+grid_utf8_copy(const struct grid_utf8 *gu, char *buf, size_t len)
+{
+ size_t size;
+
+ size = grid_utf8_size(gu);
+ if (size > len)
+ fatalx("UTF-8 copy overflow");
+ memcpy(buf, gu->data, size);
+ return (size);
+}
+
+/* Set UTF-8 grid data from input UTF-8. */
+void
+grid_utf8_set(struct grid_utf8 *gu, const struct utf8_data *utf8data)
+{
+ if (utf8data->size == 0)
+ fatalx("UTF-8 data empty");
+ if (utf8data->size > sizeof gu->data)
+ fatalx("UTF-8 data too long");
+ memcpy(gu->data, utf8data->data, utf8data->size);
+ if (utf8data->size != sizeof gu->data)
+ gu->data[utf8data->size] = 0xff;
+ gu->width = utf8data->width;
+}
+
+/* Append UTF-8 character onto the cell data (for combined characters). */
+int
+grid_utf8_append(struct grid_utf8 *gu, const struct utf8_data *utf8data)
+{
+ size_t old_size;
+
+ old_size = grid_utf8_size(gu);
+ if (old_size + utf8data->size > sizeof gu->data)
+ return (-1);
+ memcpy(gu->data + old_size, utf8data->data, utf8data->size);
+ if (old_size + utf8data->size != sizeof gu->data)
+ gu->data[old_size + utf8data->size] = 0xff;
+ return (0);
+}
+
+/* Compare two UTF-8 cells. */
+int
+grid_utf8_compare(const struct grid_utf8 *gu1, const struct grid_utf8 *gu2)
+{
+ size_t size;
+
+ size = grid_utf8_size(gu1);
+ if (size != grid_utf8_size(gu2))
+ return (0);
+ if (memcmp(gu1->data, gu2->data, size) != 0)
+ return (0);
+ return (1);
+}
diff --git a/grid.c b/grid.c
index 1041528d..a49c06bd 100644
--- a/grid.c
+++ b/grid.c
@@ -502,8 +502,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
const struct grid_cell *gc;
const struct grid_utf8 *gu;
char *buf;
- size_t len, off;
- u_int xx, i;
+ size_t len, off, size;
+ u_int xx;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
@@ -517,17 +517,15 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
continue;
if (gc->flags & GRID_FLAG_UTF8) {
- while (len < off + UTF8_SIZE + 1) {
+ gu = grid_peek_utf8(gd, xx, py);
+
+ size = grid_utf8_size(gu);
+ while (len < off + size + 1) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
- gu = grid_peek_utf8(gd, xx, py);
- for (i = 0; i < UTF8_SIZE; i++) {
- if (gu->data[i] == 0xff)
- break;
- buf[off++] = gu->data[i];
- }
+ off += grid_utf8_copy(gu, buf + off, len - off);
} else {
while (len < off + 2) {
buf = xrealloc(buf, 2, len);
diff --git a/screen-write.c b/screen-write.c
index 81231c2e..8afffa4b 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -354,7 +354,7 @@ screen_write_copy(struct screen_write_ctx *ctx,
const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct utf8_data utf8data;
- u_int xx, yy, cx, cy, ax, bx, i;
+ u_int xx, yy, cx, cy, ax, bx;
cx = s->cx;
cy = s->cy;
@@ -381,18 +381,15 @@ screen_write_copy(struct screen_write_ctx *ctx,
gc = &grid_default_cell;
else
gc = &gl->celldata[xx];
- if (gc->flags & GRID_FLAG_UTF8) {
- gu = &gl->utf8data[xx];
- memcpy(utf8data.data,
- gu->data, sizeof utf8data.data);
- utf8data.width = gu->width;
- utf8data.size = 0;
- for (i = 0; i < UTF8_SIZE; i++) {
- if (gu->data[i] == 0xff)
- break;
- utf8data.size++;
- }
+ if (!(gc->flags & GRID_FLAG_UTF8)) {
+ screen_write_cell(ctx, gc, NULL);
+ continue;
}
+ /* Reinject the UTF-8 sequence. */
+ gu = &gl->utf8data[xx];
+ utf8data.size = grid_utf8_copy(
+ gu, utf8data.data, sizeof utf8data.data);
+ utf8data.width = gu->width;
screen_write_cell(ctx, gc, &utf8data);
}
if (px + nx == gd->sx && px + nx > gl->cellsize)
@@ -1037,13 +1034,7 @@ screen_write_cell(struct screen_write_ctx *ctx,
grid_view_set_cell(gd, s->cx, s->cy, gc);
if (gc->flags & GRID_FLAG_UTF8) {
/* Construct UTF-8 and write it. */
- gu.width = utf8data->width;
- memset(gu.data, 0xff, sizeof gu.data);
- if (utf8data->size == 0)
- fatalx("UTF-8 data empty");
- if (utf8data->size > sizeof gu.data)
- fatalx("UTF-8 data overflow");
- memcpy(gu.data, utf8data->data, utf8data->size);
+ grid_utf8_set(&gu, utf8data);
grid_view_set_utf8(gd, s->cx, s->cy, &gu);
}
@@ -1080,7 +1071,7 @@ screen_write_combine(
struct grid *gd = s->grid;
struct grid_cell *gc;
struct grid_utf8 *gu, tmp_gu;
- u_int i, old_size;
+ u_int i;
/* Can't combine if at 0. */
if (s->cx == 0)
@@ -1093,35 +1084,30 @@ screen_write_combine(
/* 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.data[0] = gc->data;
+ tmp_gu.data[1] = 0xff;
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 and its size. */
+ /* Append the current cell. */
gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
- 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 + utf8data->size > UTF8_SIZE) {
- for (i = 0; i < gu->width && i != UTF8_SIZE; i++)
- gu->data[i] = '_';
- if (i != UTF8_SIZE)
- gu->data[i] = 0xff;
- gu->width = i;
- return (0);
+ if (grid_utf8_append(gu, utf8data) != 0) {
+ /* Failed: scrap this character and replace with underscores. */
+ if (gu->width == 1) {
+ gc->data = '_';
+ gc->flags &= ~GRID_FLAG_UTF8;
+ } else {
+ for (i = 0; i < gu->width && i != sizeof gu->data; i++)
+ gu->data[i] = '_';
+ if (i != sizeof gu->data)
+ gu->data[i] = 0xff;
+ gu->width = i;
+ }
}
- /* Otherwise save the character. */
- memcpy(gu->data + old_size, utf8data->data, utf8data->size);
- if (old_size + utf8data->size != UTF8_SIZE)
- gu->data[old_size + utf8data->size] = 0xff;
return (0);
}
diff --git a/tmux.1 b/tmux.1
index 2fb559e3..2b356db1 100644
--- a/tmux.1
+++ b/tmux.1
@@ -454,7 +454,7 @@ with
.D1 (alias: Ic rename )
Rename the session to
.Ar new-name .
-.It Xo Ic show-messages
+.It Xo Ic show-messages
.Op Fl t Ar target-client
.Xc
.D1 (alias: Ic showmsgs )
diff --git a/tmux.h b/tmux.h
index c03b21d9..517fe9d4 100644
--- a/tmux.h
+++ b/tmux.h
@@ -74,6 +74,12 @@ extern char **environ;
#define PRINT_LENGTH 512 /* printed error/message size */
#define ENVIRON_LENGTH 1024 /* environment variable length */
+/*
+ * UTF-8 data size. This must be big enough to hold combined characters as well
+ * as single.
+ */
+#define UTF8_SIZE 9
+
/* Fatal errors. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
#define fatalx(msg) log_fatalx("%s: %s", __func__, msg);
@@ -525,13 +531,12 @@ struct mode_key_table {
#define MODE_MOUSE 0x10
/*
- * A single UTF-8 character.
+ * A single UTF-8 character.
*
* The data member in this must be UTF8_SIZE to allow screen_write_copy to
* reinject stored UTF-8 data back into screen_write_cell after combining (ugh
* XXX XXX).
*/
-#define UTF8_SIZE 9
struct utf8_data {
u_char data[UTF8_SIZE];
@@ -1675,6 +1680,13 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int);
void grid_duplicate_lines(
struct grid *, u_int, struct grid *, u_int, u_int);
+/* grid-utf8.c */
+size_t grid_utf8_size(const struct grid_utf8 *);
+size_t grid_utf8_copy(const struct grid_utf8 *, char *, size_t);
+void grid_utf8_set(struct grid_utf8 *, const struct utf8_data *);
+int grid_utf8_append(struct grid_utf8 *, const struct utf8_data *);
+int grid_utf8_compare(const struct grid_utf8 *, const struct grid_utf8 *);
+
/* grid-view.c */
const struct grid_cell *grid_view_peek_cell(struct grid *, u_int, u_int);
struct grid_cell *grid_view_get_cell(struct grid *, u_int, u_int);
diff --git a/tty.c b/tty.c
index 8855a657..a3aeda5d 100644
--- a/tty.c
+++ b/tty.c
@@ -365,16 +365,12 @@ tty_putc(struct tty *tty, u_char ch)
void
tty_pututf8(struct tty *tty, const struct grid_utf8 *gu)
{
- u_int i;
-
- for (i = 0; i < UTF8_SIZE; i++) {
- if (gu->data[i] == 0xff)
- break;
- bufferevent_write(tty->event, &gu->data[i], 1);
- if (tty->log_fd != -1)
- write(tty->log_fd, &gu->data[i], 1);
- }
+ size_t size;
+ size = grid_utf8_size(gu);
+ bufferevent_write(tty->event, gu->data, size);
+ if (tty->log_fd != -1)
+ write(tty->log_fd, gu->data, size);
tty->cx += gu->width;
}
diff --git a/window-copy.c b/window-copy.c
index 499ead33..25f73634 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -486,6 +486,7 @@ window_copy_search_compare(
{
const struct grid_cell *gc, *sgc;
const struct grid_utf8 *gu, *sgu;
+ size_t size;
gc = grid_peek_cell(gd, px, py);
sgc = grid_peek_cell(sgd, spx, 0);
@@ -496,7 +497,7 @@ window_copy_search_compare(
if (gc->flags & GRID_FLAG_UTF8) {
gu = grid_peek_utf8(gd, px, py);
sgu = grid_peek_utf8(sgd, spx, 0);
- if (memcmp(gu->data, sgu->data, UTF8_SIZE) == 0)
+ if (grid_utf8_compare(gu, sgu))
return (1);
} else {
if (gc->data == sgc->data)
@@ -895,7 +896,8 @@ window_copy_copy_line(struct window_pane *wp,
const struct grid_cell *gc;
const struct grid_utf8 *gu;
struct grid_line *gl;
- u_int i, j, xx, wrapped = 0;
+ u_int i, xx, wrapped = 0;
+ size_t size;
if (sx > ex)
return;
@@ -928,12 +930,9 @@ window_copy_copy_line(struct window_pane *wp,
(*buf)[(*off)++] = gc->data;
} else {
gu = grid_peek_utf8(gd, i, sy);
- *buf = xrealloc(*buf, 1, (*off) + UTF8_SIZE);
- for (j = 0; j < UTF8_SIZE; j++) {
- if (gu->data[j] == 0xff)
- break;
- (*buf)[(*off)++] = gu->data[j];
- }
+ size = grid_utf8_size(gu);
+ *buf = xrealloc(*buf, 1, (*off) + size);
+ *off += grid_utf8_copy(gu, *buf + *off, size);
}
}
}