about summary refs log tree commit diff
path: root/Src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/Src/utils.c b/Src/utils.c
index 3394b0526..aef26165d 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3520,6 +3520,49 @@ mb_niceztrdup(const char *s)
     return retstr;
 }
 
+/*
+ * Return the screen width of a multibyte string.  The input
+ * string is metafied.
+ */
+/**/
+mod_export int
+mb_width(const char *s)
+{
+    char *ums = ztrdup(s), *umptr;
+    int umlen;
+    int width = 0;
+    mbstate_t mbs;
+
+    memset(&mbs, 0, sizeof(mbs));
+    umptr = unmetafy(ums, &umlen);
+    /*
+     * Convert one wide character at a time.  We could convet
+     * the entire string using mbsrtowcs(), but that terminates on
+     * a NUL and we might have embedded NULs.
+     */
+    while (umlen > 0) {
+	wchar_t cc;
+	int ret = mbrtowc(&cc, umptr, umlen, &mbs);
+
+	if (ret <= 0) {
+	    /* Assume a single-width character. */
+	    width++;
+	    ret = 1;
+	} else {
+	    int wret = wcwidth(cc);
+	    if (wret > 0)
+		width += wret;
+	}
+
+	umlen -= ret;
+	umptr += ret;
+    }
+
+    free(ums);
+
+    return width;
+}
+
 /**/
 #endif /* ZLE_UNICODE_SUPPORT */