Merge branch 'maint'
[gitweb.git] / utf8.c
diff --git a/utf8.c b/utf8.c
index 0b30b54847127ec1e4af04b72ed5c6bd9ffef733..7f648574a550432e3160fcef178f894faf0bdd54 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -323,7 +323,7 @@ static size_t display_mode_esc_sequence_len(const char *s)
  * If indent is negative, assume that already -indent columns have been
  * consumed (and no extra indent is necessary for the first line).
  */
-int strbuf_add_wrapped_text(struct strbuf *buf,
+void strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent1, int indent2, int width)
 {
        int indent, w, assume_utf8 = 1;
@@ -332,7 +332,7 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
 
        if (width <= 0) {
                strbuf_add_indented_text(buf, text, indent1, indent2);
-               return 1;
+               return;
        }
 
 retry:
@@ -356,14 +356,14 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
                        if (w <= width || !space) {
                                const char *start = bol;
                                if (!c && text == start)
-                                       return w;
+                                       return;
                                if (space)
                                        start = space;
                                else
                                        strbuf_addchars(buf, ' ', indent);
                                strbuf_add(buf, start, text - start);
                                if (!c)
-                                       return w;
+                                       return;
                                space = text;
                                if (c == '\t')
                                        w |= 0x07;
@@ -405,13 +405,12 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
        }
 }
 
-int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
                             int indent, int indent2, int width)
 {
        char *tmp = xstrndup(data, len);
-       int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
+       strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
        free(tmp);
-       return r;
 }
 
 int is_encoding_utf8(const char *name)
@@ -430,6 +429,27 @@ int same_encoding(const char *src, const char *dst)
        return !strcasecmp(src, dst);
 }
 
+/*
+ * Wrapper for fprintf and returns the total number of columns required
+ * for the printed string, assuming that the string is utf8.
+ */
+int utf8_fprintf(FILE *stream, const char *format, ...)
+{
+       struct strbuf buf = STRBUF_INIT;
+       va_list arg;
+       int columns;
+
+       va_start(arg, format);
+       strbuf_vaddf(&buf, format, arg);
+       va_end(arg);
+
+       columns = fputs(buf.buf, stream);
+       if (0 <= columns) /* keep the error from the I/O */
+               columns = utf8_strwidth(buf.buf);
+       strbuf_release(&buf);
+       return columns;
+}
+
 /*
  * Given a buffer and its encoding, return it re-encoded
  * with iconv.  If the conversion fails, returns NULL.
@@ -487,9 +507,25 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e
 
        if (!in_encoding)
                return NULL;
+
        conv = iconv_open(out_encoding, in_encoding);
-       if (conv == (iconv_t) -1)
-               return NULL;
+       if (conv == (iconv_t) -1) {
+               /*
+                * Some platforms do not have the variously spelled variants of
+                * UTF-8, so let's fall back to trying the most official
+                * spelling. We do so only as a fallback in case the platform
+                * does understand the user's spelling, but not our official
+                * one.
+                */
+               if (is_encoding_utf8(in_encoding))
+                       in_encoding = "UTF-8";
+               if (is_encoding_utf8(out_encoding))
+                       out_encoding = "UTF-8";
+               conv = iconv_open(out_encoding, in_encoding);
+               if (conv == (iconv_t) -1)
+                       return NULL;
+       }
+
        out = reencode_string_iconv(in, strlen(in), conv);
        iconv_close(conv);
        return out;