From: c_14 <git@c-14.de>
Date: Tue, 16 May 2017 16:13:27 +0000 (+0200)
Subject: fmt_scan: support multibyte characters in putstr decoding
X-Git-Tag: mmh-0.4~37
X-Git-Url: http://git.marmaro.de/?a=commitdiff_plain;h=95f7880a49b3eb5d1d4f5a966c291d91aeca3c41;p=mmh

fmt_scan: support multibyte characters in putstr decoding

Fixes an issue where the string output by scan with a putstr format is
truncated within a multibyte character causing terminal corruption
---

diff --git a/sbr/fmt_scan.c b/sbr/fmt_scan.c
index 2485e6cb..d0b112bf 100644
--- a/sbr/fmt_scan.c
+++ b/sbr/fmt_scan.c
@@ -188,17 +188,48 @@ cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n) {
 static void
 cpstripped(char **start, char *end, char *str)
 {
+#ifdef MULTIBYTE_SUPPORT
+	int char_len;  /* bytes in current character */
+	int nbytes;
+	wchar_t wide_char;
+#else
 	int c;
+#endif
 	char *s = str;
 
 	if (!s)
 		return;
 
 	/* skip any initial control characters or spaces */
+#ifdef MULTIBYTE_SUPPORT
+	nbytes = end - *start + 1;
+	mbtowc(NULL, NULL, 0); /* reset shift state */
+	while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+		s += char_len;
+		nbytes -= char_len;
+	}
+#else
 	while ((c = (unsigned char) *s) && (iscntrl(c) || isspace(c)))
 		s++;
+#endif
 
 	/* compact repeated control characters and spaces into a single space */
+#ifdef MULTIBYTE_SUPPORT
+	while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && *start < end) {
+		if (!iswcntrl(wide_char) && !iswspace(wide_char)) {
+			strncpy(*start, s, char_len);
+			s += char_len;
+			*start += char_len;
+			nbytes -= char_len;
+		} else {
+			while ((char_len = mbtowc(&wide_char, s, nbytes)) > 0 && (iswcntrl(wide_char) || iswspace(wide_char))) {
+				s += char_len;
+				nbytes -= char_len;
+			}
+			*(*start)++ = ' ';
+		}
+	}
+#else
 	while((c = (unsigned char) *s++) && *start < end)
 		if (!iscntrl(c) && !isspace(c))
 			*(*start)++ = c;
@@ -208,6 +239,7 @@ cpstripped(char **start, char *end, char *str)
 				s++;
 			*(*start)++ = ' ';
 		}
+#endif
 }
 
 static char *lmonth[] = {