So, third diff to ponder as we evaluate this approach. This one also uses a u8len() function to help get the column widths correct.
(Still not dealing with combining or otherwise not 1 width glyphs.) Index: ls.c =================================================================== RCS file: /cvs/src/bin/ls/ls.c,v retrieving revision 1.43 diff -u -p -r1.43 ls.c --- ls.c 9 Oct 2015 01:37:06 -0000 1.43 +++ ls.c 23 Oct 2015 12:39:52 -0000 @@ -410,6 +410,8 @@ traverse(int argc, char *argv[], int opt fts_close(ftsp); } +extern size_t u8len(char *); + /* * Display() takes a linked list of FTSENT structures and passes the list * along with any other necessary information to the print function. P @@ -474,8 +476,8 @@ display(FTSENT *p, FTSENT *list) continue; } } - if (cur->fts_namelen > maxlen) - maxlen = cur->fts_namelen; + if (u8len(cur->fts_name) > maxlen) + maxlen = u8len(cur->fts_name); if (needstats) { sp = cur->fts_statp; if (sp->st_blocks > maxblock) Index: util.c =================================================================== RCS file: /cvs/src/bin/ls/util.c,v retrieving revision 1.16 diff -u -p -r1.16 util.c --- util.c 21 Nov 2013 15:54:45 -0000 1.16 +++ util.c 23 Oct 2015 12:39:57 -0000 @@ -46,12 +46,31 @@ #include "extern.h" int +isu8cont(unsigned char c) +{ + return ((c & (0x80 | 0x40)) == 0x80); +} +size_t +u8len(const char *s) +{ + size_t len = 0; + + for (; *s; s++) + if (!isu8cont(*s)) + len++; + return len; +} + +int putname(char *name) { int len; - for (len = 0; *name; len++, name++) - putchar((!isprint((unsigned char)*name) && f_nonprint) ? '?' : *name); + for (len = 0; *name; name++) { + if (!isu8cont(*name)) + len++; + putchar(*name); + } return len; }