]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
column: ignore non-printable chars
authorKarel Zak <kzak@redhat.com>
Wed, 13 Jan 2016 09:08:39 +0000 (10:08 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 13 Jan 2016 09:08:39 +0000 (10:08 +0100)
echo -e '\033[33mb\033[mXFoo\n\033[33mbar\033[mXFoo' | column -s X -t

old version:

b   Foo
bar   Foo

fixed version:

b    Foo
bar  Foo

References: https://github.com/karelzak/util-linux/issues/252
Signed-off-by: Karel Zak <kzak@redhat.com>
text-utils/column.c

index 4411d2d262611f5973cd26d22e312a6e528e32ac..b8d31c989a451085f74c52467ee65bbcc21826b6 100644 (file)
 #include "ttyutils.h"
 
 #ifdef HAVE_WIDECHAR
-#define wcs_width(s) wcswidth(s,wcslen(s))
 static wchar_t *mbs_to_wcs(const char *);
 #else
-#define wcs_width(s) strlen(s)
 #define mbs_to_wcs(s) xstrdup(s)
 static char *mtsafe_strtok(char *, const char *, char **);
 #define wcstok mtsafe_strtok
@@ -84,6 +82,33 @@ typedef struct _tbl {
        int cols, *len;
 } TBL;
 
+
+#ifdef HAVE_WIDECHAR
+/* Don't use wcswidth(), we need to ignore non-printable chars. */
+static int width(const wchar_t *str)
+{
+       int x, width = 0;
+
+       for (; *str != '\0'; str++) {
+               x = wcwidth(*str);
+               if (x > 0)
+                       width += x;
+       }
+       return width;
+}
+#else
+static int width(const char *str)
+{
+       int width = 0;
+
+       for (; *str != '\0'; str++) {
+               if (isprint(*str))
+                       width++;
+       }
+       return width;
+}
+#endif
+
 static void __attribute__((__noreturn__)) usage(int rc)
 {
        FILE *out = rc == EXIT_FAILURE ? stderr : stdout;
@@ -223,7 +248,7 @@ static void c_columnate(int maxlength, long termwidth, wchar_t **list, int entri
        endcol = maxlength;
        for (chcnt = col = 0, lp = list;; ++lp) {
                fputws(*lp, stdout);
-               chcnt += wcs_width(*lp);
+               chcnt += width(*lp);
                if (!--entries)
                        break;
                if (++col == numcols) {
@@ -248,7 +273,7 @@ static void r_columnate(int maxlength, long termwidth, wchar_t **list, int entri
 
        maxlength = (maxlength + TAB) & ~(TAB - 1);
        numcols = termwidth / maxlength;
-       if (!numcols) 
+       if (!numcols)
                numcols = 1;
        numrows = entries / numcols;
        if (entries % numcols)
@@ -258,7 +283,7 @@ static void r_columnate(int maxlength, long termwidth, wchar_t **list, int entri
                endcol = maxlength;
                for (base = row, chcnt = col = 0; col < numcols; ++col) {
                        fputws(list[base], stdout);
-                       chcnt += wcs_width(list[base]);
+                       chcnt += width(list[base]);
                        if ((base += numrows) >= entries)
                                break;
                        while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) {
@@ -339,7 +364,7 @@ static void maketbl(wchar_t **list, int entries, wchar_t *separator, int greedy,
                t->len = xcalloc(coloff, sizeof(int));
                for (t->cols = coloff; --coloff >= 0;) {
                        t->list[coloff] = cols[coloff];
-                       t->len[coloff] = wcs_width(cols[coloff]);
+                       t->len[coloff] = width(cols[coloff]);
                        if (t->len[coloff] > lens[coloff])
                                lens[coloff] = t->len[coloff];
                }
@@ -348,7 +373,11 @@ static void maketbl(wchar_t **list, int entries, wchar_t *separator, int greedy,
        for (t = tbl, cnt = 0; cnt < entries; ++cnt, ++t) {
                for (coloff = 0; coloff < t->cols - 1; ++coloff) {
                        fputws(t->list[coloff], stdout);
+#ifdef HAVE_WIDECHAR
                        wprintf(L"%*s", lens[coloff] - t->len[coloff], "");
+#else
+                       printf("%*s", (int) lens[coloff] - t->len[coloff], "");
+#endif
                        fputws(colsep, stdout);
                }
                if (coloff < t->cols) {
@@ -400,7 +429,7 @@ static int input(FILE *fp, int *maxlength, wchar_t ***list, int *entries)
                lineno++;
                if (!feof(fp) && p)
                        *p = '\0';
-               len = wcs_width(buf);   /* len = p - buf; */
+               len = width(buf);       /* len = p - buf; */
                if (*maxlength < len)
                        *maxlength = len;
                if (local_entries == maxentry) {