summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-load-buffer.c7
-rw-r--r--cmd-queue.c19
-rw-r--r--tmux.h1
-rw-r--r--utf8.c44
4 files changed, 67 insertions, 4 deletions
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 9352cbe5..40bea9b7 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -133,7 +133,7 @@ void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
const char *bufname = data;
- char *pdata, *cause;
+ char *pdata, *cause, *saved;
size_t psize;
if (!closed)
@@ -154,6 +154,11 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
if (paste_set(pdata, psize, bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
+ if (~c->flags & CLIENT_UTF8) {
+ saved = cause;
+ cause = utf8_sanitize(saved);
+ free(saved);
+ }
evbuffer_add_printf(c->stderr_data, "%s", cause);
server_push_stderr(c);
free(pdata);
diff --git a/cmd-queue.c b/cmd-queue.c
index ff8c69cb..5015981c 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -69,14 +69,21 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
struct client *c = cmdq->client;
struct window *w;
va_list ap;
+ char *tmp, *msg;
va_start(ap, fmt);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
- evbuffer_add_vprintf(c->stdout_data, fmt, ap);
-
+ if (~c->flags & CLIENT_UTF8) {
+ vasprintf(&tmp, fmt, ap);
+ msg = utf8_sanitize(tmp);
+ free(tmp);
+ evbuffer_add(c->stdout_data, msg, strlen(msg));
+ free(msg);
+ } else
+ evbuffer_add_vprintf(c->stdout_data, fmt, ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
} else {
@@ -101,6 +108,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
va_list ap;
char *msg;
size_t msglen;
+ char *tmp;
va_start(ap, fmt);
msglen = xvasprintf(&msg, fmt, ap);
@@ -109,9 +117,14 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL)
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
+ if (~c->flags & CLIENT_UTF8) {
+ tmp = msg;
+ msg = utf8_sanitize(tmp);
+ free(tmp);
+ msglen = strlen(msg);
+ }
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
-
server_push_stderr(c);
c->retval = 1;
} else {
diff --git a/tmux.h b/tmux.h
index 618240b0..de19159d 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2189,6 +2189,7 @@ u_int utf8_combine(const struct utf8_data *);
int utf8_split(u_int, struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
int utf8_strvis(char *, const char *, size_t, int);
+char *utf8_sanitize(const char *);
struct utf8_data *utf8_fromcstr(const char *);
char *utf8_tocstr(struct utf8_data *);
u_int utf8_cstrwidth(const char *);
diff --git a/utf8.c b/utf8.c
index e61bf996..cb20ea6d 100644
--- a/utf8.c
+++ b/utf8.c
@@ -586,6 +586,50 @@ utf8_strvis(char *dst, const char *src, size_t len, int flag)
}
/*
+ * Sanitize a string, changing any UTF-8 characters to '_'. Caller should free
+ * the returned string. Anything not valid printable ASCII or UTF-8 is
+ * stripped.
+ */
+char *
+utf8_sanitize(const char *src)
+{
+ char *dst;
+ size_t n;
+ int more;
+ struct utf8_data utf8data;
+ u_int i;
+
+ dst = NULL;
+
+ n = 0;
+ while (*src != '\0') {
+ dst = xreallocarray(dst, n + 1, sizeof *dst);
+ if (utf8_open(&utf8data, *src)) {
+ more = 1;
+ while (*++src != '\0' && more)
+ more = utf8_append(&utf8data, *src);
+ if (!more) {
+ dst = xreallocarray(dst, n + utf8data.width,
+ sizeof *dst);
+ for (i = 0; i < utf8data.width; i++)
+ dst[n++] = '_';
+ continue;
+ }
+ src -= utf8data.have;
+ }
+ if (*src > 0x1f && *src < 0x7f)
+ dst[n] = *src;
+ src++;
+
+ n++;
+ }
+
+ dst = xreallocarray(dst, n + 1, sizeof *dst);
+ dst[n] = '\0';
+ return (dst);
+}
+
+/*
* Convert a string into a buffer of UTF-8 characters. Terminated by size == 0.
* Caller frees.
*/