Stefan Sperling writes: > On Mon, Oct 26, 2015 at 03:58:58PM -0600, Anthony J. Bentley wrote: > > "Ted Unangst" writes: > > > it only gets deeper and thicker... > > > > Indeed. > > > > Here's a shorter implementation. Like colorls(1), it uses wide > > characters (only within the putname() function) but is slightly cleaned > > up and simplified. > > Is it really shorter if you follow the libc code paths this is calling?
No, it's not. But that's not inherent to wchar_t, only to the Citrus stuff that infests our libc. As Citrus gets cleaned up, this works better instantly. And if we instead come up with better functions for doing this kind of thing: > The utilities in Ted's diff would eventually be split off into a library. There are a number of directions a hypothetical UTF-8 library could go. mbwidth(), for example, would fit quite cleanly in the code below--and this code style is *very* common, because these are the standard functions for this stuff, so such an API would get a lot of use. New version of the patch--Ted pointed out max column widths were derived from byte lengths instead of character widths. Index: extern.h =================================================================== RCS file: /cvs/src/bin/ls/extern.h,v retrieving revision 1.9 diff -u -p -r1.9 extern.h --- extern.h 2 Jun 2003 23:32:08 -0000 1.9 +++ extern.h 27 Oct 2015 00:07:54 -0000 @@ -51,4 +51,5 @@ void printacol(DISPLAY *); void printlong(DISPLAY *); void printscol(DISPLAY *); void printstream(DISPLAY *); +size_t strwidth(char *); void usage(void); 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 27 Oct 2015 00:07:54 -0000 @@ -48,6 +48,7 @@ #include <string.h> #include <unistd.h> #include <limits.h> +#include <locale.h> #include <util.h> #include "ls.h" @@ -103,6 +104,8 @@ ls_main(int argc, char *argv[]) int kflag = 0, width = 0; char *p; + setlocale(LC_CTYPE, ""); + /* Terminal defaults to -Cq, non-terminal defaults to -1. */ if (isatty(STDOUT_FILENO)) { if ((p = getenv("COLUMNS")) != NULL) @@ -474,8 +477,8 @@ display(FTSENT *p, FTSENT *list) continue; } } - if (cur->fts_namelen > maxlen) - maxlen = cur->fts_namelen; + if (strwidth(cur->fts_name) > maxlen) + maxlen = strwidth(cur->fts_name); if (needstats) { sp = cur->fts_statp; if (sp->st_blocks > maxblock) Index: print.c =================================================================== RCS file: /cvs/src/bin/ls/print.c,v retrieving revision 1.34 diff -u -p -r1.34 print.c --- print.c 15 Mar 2015 00:41:27 -0000 1.34 +++ print.c 27 Oct 2015 00:07:54 -0000 @@ -310,7 +310,8 @@ printstream(DISPLAY *dp) continue; if (col > 0) { (void)putchar(','), col++; - if (col + 1 + extwidth + p->fts_namelen >= termwidth) + if (col + 1 + extwidth + strwidth(p->fts_name) >= + termwidth) (void)putchar('\n'), col = 0; else (void)putchar(' '), col++; 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 27 Oct 2015 00:07:54 -0000 @@ -41,10 +41,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <wchar.h> +#include <wctype.h> #include "ls.h" #include "extern.h" +#ifdef SMALL int putname(char *name) { @@ -54,6 +57,62 @@ putname(char *name) putchar((!isprint((unsigned char)*name) && f_nonprint) ? '?' : *name); return len; } + +size_t +strwidth(char *s) +{ + return strlen(s); +} +#else +int +putname(char *name) +{ + int width, n; + wchar_t wc; + + width = 0; + while ((n = mbtowc(&wc, name, MB_LEN_MAX)) != 0) { + if (n == -1) { + width++; + name++; + putchar('?'); + } else if (iswprint(wc)) { + width += wcwidth(wc); + name += n; + printf("%lc", wc); + } else { + width++; + name += n; + putchar('?'); + } + } + + return width; +} + +size_t +strwidth(char *s) +{ + int width, n; + wchar_t wc; + + width = 0; + while ((n = mbtowc(&wc, s, MB_LEN_MAX)) != 0) { + if (n == -1) { + width++; + s++; + } else if (iswprint(wc)) { + width += wcwidth(wc); + s += n; + } else { + width++; + s += n; + } + } + + return width; +} +#endif void usage(void)