Counting characters, not bytes
A separator drawn with multibyte border symbols cannot use strlen to determine its printed character count. Its byte count need not equal its wide-character count, so draw_sep uses the nonstandard mbsrlen instead. section 14.3
A wide character has type wchar_t and represents a character of an extended character set. The C header wchar.h provides wchar_t and conversion utilities. Converting a multibyte string can require an mbstate_t parsing state; mbsrtowcs converts it to wide characters. section 14.3
38 wchar_t* mbsrdup(char const*s, mbstate_t const*restrict state) {
39 size_t mblen = mbsrlen(s, state);
40 if (mblen == -1) return 0;
41 mbstate_t st = state ? *state : *MBSTATE;
42 wchar_t* S = malloc(sizeof(wchar_t[mblen+1]));
43 /* We know that s converts well, so no error check */
44 if (S) mbsrtowcs(S, &s, mblen+1, &st);
45 return S;
46 }
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":2}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":12}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":14}],[{\"line\":0,\"ch\":22},{\"line\":0,\"ch\":32}],[{\"line\":0,\"ch\":36},{\"line\":0,\"ch\":45}],[{\"line\":3,\"ch\":7},{\"line\":3,\"ch\":16}],[{\"line\":0,\"ch\":27},{\"line\":0,\"ch\":32}],[{\"line\":0,\"ch\":52},{\"line\":0,\"ch\":60}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":2}],[{\"line\":1,\"ch\":7},{\"line\":1,\"ch\":13}],[{\"line\":1,\"ch\":14},{\"line\":1,\"ch\":19}],[{\"line\":2,\"ch\":11},{\"line\":2,\"ch\":16}],[{\"line\":4,\"ch\":42},{\"line\":4,\"ch\":47}],[{\"line\":6,\"ch\":31},{\"line\":6,\"ch\":36}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":2}],[{\"line\":2,\"ch\":7},{\"line\":2,\"ch\":9}],[{\"line\":6,\"ch\":7},{\"line\":6,\"ch\":9}],[{\"line\":1,\"ch\":14},{\"line\":1,\"ch\":19}],[{\"line\":2,\"ch\":11},{\"line\":2,\"ch\":16}],[{\"line\":4,\"ch\":42},{\"line\":4,\"ch\":47}],[{\"line\":6,\"ch\":31},{\"line\":6,\"ch\":36}],[{\"line\":2,\"ch\":24},{\"line\":2,\"ch\":30}],[{\"line\":7,\"ch\":7},{\"line\":7,\"ch\":13}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":2}],[{\"line\":0,\"ch\":36},{\"line\":0,\"ch\":45}],[{\"line\":3,\"ch\":7},{\"line\":3,\"ch\":16}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":2}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":12}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":14}],[{\"line\":4,\"ch\":20},{\"line\":4,\"ch\":26}],[{\"line\":4,\"ch\":27},{\"line\":4,\"ch\":33}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":12}],[{\"line\":4,\"ch\":7},{\"line\":4,\"ch\":14}],[{\"line\":1,\"ch\":14},{\"line\":1,\"ch\":19}],[{\"line\":2,\"ch\":11},{\"line\":2,\"ch\":16}],[{\"line\":4,\"ch\":42},{\"line\":4,\"ch\":47}],[{\"line\":6,\"ch\":31},{\"line\":6,\"ch\":36}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":2}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":2}],[{\"line\":2,\"ch\":7},{\"line\":2,\"ch\":9}],[{\"line\":6,\"ch\":7},{\"line\":6,\"ch\":9}],[{\"line\":6,\"ch\":14},{\"line\":6,\"ch\":23}],[{\"line\":1,\"ch\":14},{\"line\":1,\"ch\":19}],[{\"line\":2,\"ch\":11},{\"line\":2,\"ch\":16}],[{\"line\":4,\"ch\":42},{\"line\":4,\"ch\":47}],[{\"line\":6,\"ch\":31},{\"line\":6,\"ch\":36}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":2}],[{\"line\":2,\"ch\":24},{\"line\":2,\"ch\":30}],[{\"line\":7,\"ch\":7},{\"line\":7,\"ch\":13}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":2}]]"}
!@%STYLE%@!
The mbsrdup implementation counts converted characters, allocates space for those wchar_t elements plus a terminator, then calls mbsrtowcs. section 14.3
TAKEAWAY: Do not assume that each char array element is one character. Nor should every wchar_t value be assumed to be a Unicode code point: the example explicitly checks for that implementation property. section 14.3

