Commit Diff


commit - 72f85f8c3ae4b36f7f5c13835be4cfcca33ce82d
commit + 00dfcb9257905221d15c8cdf62614113ecc07057
blob - /dev/null
blob + 2c3703e2bf1b24f41f58d6c3538d46f170f75e76 (mode 644)
--- /dev/null
+++ include/got_utf8.h
@@ -0,0 +1,17 @@
+/*
+ * 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
@@ -0,0 +1,67 @@
+/*
+ * 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
@@ -1,9 +1,10 @@
 .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
@@ -39,6 +39,7 @@
 #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))
@@ -97,20 +98,33 @@ usage_log(void)
 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;