commit 00dfcb9257905221d15c8cdf62614113ecc07057 from: Stefan Sperling date: Mon Jun 11 20:02:49 2018 UTC handle EILSEQ in tog(1) 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 + * + * 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 + * Copyright (c) 2018 Stefan Sperling + * + * 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 +#include +#include +#include + +#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;