commit - 72f85f8c3ae4b36f7f5c13835be4cfcca33ce82d
commit + 00dfcb9257905221d15c8cdf62614113ecc07057
blob - /dev/null
blob + 2c3703e2bf1b24f41f58d6c3538d46f170f75e76 (mode 644)
--- /dev/null
+++ include/got_utf8.h
+/*
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ *
+ * 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 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.
+ */
+
+const struct got_error *got_mbsavis(char**, int *, const char *);
blob - /dev/null
blob + d1db624475bcd094aaa75a1bdf61679678a7d2b1 (mode 644)
--- /dev/null
+++ lib/utf8.c
+/*
+ * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
+ *
+ * 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 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 <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "got_error.h"
+#include "got_utf8.h"
+
+const struct got_error *
+got_mbsavis(char** outp, int *widthp, const char *mbs)
+{
+ const char *src; /* Iterate mbs. */
+ char *dst; /* Iterate *outp. */
+ wchar_t wc;
+ int total_width; /* Display width of the whole string. */
+ int width; /* Display width of a single Unicode char. */
+ int len; /* Length in bytes of UTF-8 encoded string. */
+
+ len = strlen(mbs);
+ if ((*outp = malloc(len + 1)) == NULL)
+ return got_error_from_errno();
+
+ if (MB_CUR_MAX == 1) {
+ memcpy(*outp, mbs, len + 1);
+ *widthp = len;
+ return NULL;
+ }
+
+ src = mbs;
+ dst = *outp;
+ total_width = 0;
+ while (*src != '\0') {
+ if ((len = mbtowc(&wc, src, MB_CUR_MAX)) == -1) {
+ total_width++;
+ *dst++ = '?';
+ src++;
+ } else if ((width = wcwidth(wc)) == -1) {
+ total_width++;
+ *dst++ = '?';
+ src += len;
+ } else {
+ total_width += width;
+ while (len-- > 0)
+ *dst++ = *src++;
+ }
+ }
+ *dst = '\0';
+ *widthp = total_width;
+ return NULL;
+}
blob - 730e0f01dfd4ad3f3cda3fed246a8f6f65bf1b3b
blob + ec1cc5e73a5eed519f5e979d6c007695a92def6b
--- tog/Makefile
+++ tog/Makefile
.PATH:${.CURDIR}/../lib
PROG= tog
-SRCS= tog.c delta.c diff.c diffreg.c error.c fileindex.c object.c \
- opentemp.c path.c pack.c privsep.c reference.c repository.c \
- sha1.c worktree.c zbuf.c object_idset.c commit_graph.c
+SRCS= tog.c commit_graph.c delta.c diff.c diffreg.c error.c \
+ fileindex.c object.c object_idset.c opentemp.c path.c \
+ pack.c privsep.c reference.c repository.c sha1.c worktree.c \
+ utf8.c zbuf.c
CPPFLAGS = -I${.CURDIR}/../include -I${.CURDIR}/../lib
LDADD = -lpanel -lncursesw -lutil -lz
blob - 9bf2f9c79faacaeba0a3fd9bda9c541d785217c9
blob + 111605aa74fbad3f7f76de8cb2f3c8f656763ca2
--- tog/tog.c
+++ tog/tog.c
#include "got_diff.h"
#include "got_opentemp.h"
#include "got_commit_graph.h"
+#include "got_utf8.h"
#ifndef MIN
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
static const struct got_error *
mbs2ws(wchar_t **ws, size_t *wlen, const char *s)
{
+ char *vis = NULL;
const struct got_error *err = NULL;
*ws = NULL;
*wlen = mbstowcs(NULL, s, 0);
- if (*wlen == (size_t)-1)
- return got_error_from_errno();
+ if (*wlen == (size_t)-1) {
+ int vislen;
+ if (errno != EILSEQ)
+ return got_error_from_errno();
+
+ /* byte string invalid in current encoding; try to "fix" it */
+ err = got_mbsavis(&vis, &vislen, s);
+ if (err)
+ return err;
+ *wlen = mbstowcs(NULL, vis, 0);
+ if (*wlen == (size_t)-1)
+ return got_error_from_errno(); /* give up */
+ }
*ws = calloc(*wlen + 1, sizeof(*ws));
if (*ws == NULL)
return got_error_from_errno();
- if (mbstowcs(*ws, s, *wlen) != *wlen)
+ if (mbstowcs(*ws, vis ? vis : s, *wlen) != *wlen)
err = got_error_from_errno();
+ free(vis);
if (err) {
free(*ws);
*ws = NULL;