- if (iswcntrl(wide_char) || iswspace(wide_char)) {
- str += char_len;
-#else /* MULTIBYTE_SUPPORT */
- int c = (unsigned char) *str;
- len--;
- if (iscntrl(c) || isspace(c)) {
- str++;
-#endif /* MULTIBYTE_SUPPORT */
- if (! prevCtrl) {
- *(*dest)++ = ' ';
- }
+ if (!str)
+ return; /* It's unclear why no padding in this case. */
+ end = str + strlen(str);
+
+ if (mbtowc(NULL, NULL, 0))
+ {} /* Reset shift state. */
+
+ squash = true; /* Trim `space' or `cntrl' from the start. */
+ while (max) {
+ if (!*str)
+ return; /* It's unclear why no padding in this case. */
+
+ srclen = mbtowc(&rune, str, end - str);
+ if (srclen == -1) {
+ /* Invalid rune, or not enough bytes to finish it. */
+ rune = L'?';
+ src = oddchar;
+ srclen = oddlen;
+ str++; /* Skip one byte. */
+ } else {
+ src = str;
+ str += srclen;
+ }
+
+ if (iswspace(rune) || iswcntrl(rune)) {
+ if (squash)
+ continue; /* Amidst a run of these. */
+ rune = L' ';
+ src = spacechar;
+ srclen = spacelen;
+ squash = true;
+ } else
+ squash = false;
+
+ w = wcwidth(rune);
+ if (w == -1) {
+ rune = L'?';
+ w = wcwidth(rune);
+ assert(w != -1);
+ src = oddchar;
+ srclen = oddlen;
+ }
+
+ if ((size_t)w > max) {
+ /* No room for rune; pad. */
+ while (max--)
+ charstring_push_back_chars(dest, spacechar, spacelen, 1);
+ return;
+ }
+
+ charstring_push_back_chars(dest, src, srclen, w);
+ max -= w;
+ }
+}
+#endif