cols.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       cols.c (2087B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <sys/ioctl.h>
            3 
            4 #include <limits.h>
            5 #include <stdint.h>
            6 #include <stdio.h>
            7 #include <stdlib.h>
            8 #include <string.h>
            9 #include <unistd.h>
           10 
           11 #include "text.h"
           12 #include "util.h"
           13 
           14 static void
           15 usage(void)
           16 {
           17         eprintf("usage: %s [-c num] [file ...]\n", argv0);
           18 }
           19 
           20 int
           21 main(int argc, char *argv[])
           22 {
           23         FILE *fp;
           24         struct winsize w;
           25         struct linebuf b = EMPTY_LINEBUF;
           26         size_t chars = 65, maxlen = 0, i, j, k, len, cols, rows;
           27         int cflag = 0, ret = 0;
           28         char *p;
           29 
           30         ARGBEGIN {
           31         case 'c':
           32                 cflag = 1;
           33                 chars = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX));
           34                 break;
           35         default:
           36                 usage();
           37         } ARGEND
           38 
           39         if (!cflag) {
           40                 if ((p = getenv("COLUMNS")))
           41                         chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
           42                 else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0)
           43                         chars = w.ws_col;
           44         }
           45 
           46         if (!argc) {
           47                 getlines(stdin, &b);
           48         } else {
           49                 for (; *argv; argc--, argv++) {
           50                         if (!strcmp(*argv, "-")) {
           51                                 *argv = "<stdin>";
           52                                 fp = stdin;
           53                         } else if (!(fp = fopen(*argv, "r"))) {
           54                                 weprintf("fopen %s:", *argv);
           55                                 ret = 1;
           56                                 continue;
           57                         }
           58                         getlines(fp, &b);
           59                         if (fp != stdin && fshut(fp, *argv))
           60                                 ret = 1;
           61                 }
           62         }
           63 
           64         for (i = 0; i < b.nlines; i++) {
           65                 for (j = 0, len = 0; j < b.lines[i].len; j++) {
           66                         if (UTF8_POINT(b.lines[i].data[j]))
           67                                 len++;
           68                 }
           69                 if (len && b.lines[i].data[b.lines[i].len - 1] == '\n') {
           70                         b.lines[i].data[--(b.lines[i].len)] = '\0';
           71                         len--;
           72                 }
           73                 if (len > maxlen)
           74                         maxlen = len;
           75         }
           76 
           77         for (cols = 1; (cols + 1) * maxlen + cols <= chars; cols++);
           78         rows = b.nlines / cols + (b.nlines % cols > 0);
           79 
           80         for (i = 0; i < rows; i++) {
           81                 for (j = 0; j < cols && i + j * rows < b.nlines; j++) {
           82                         for (k = 0, len = 0; k < b.lines[i + j * rows].len; k++) {
           83                                 if (UTF8_POINT(b.lines[i + j * rows].data[k]))
           84                                         len++;
           85                         }
           86                         fwrite(b.lines[i + j * rows].data, 1,
           87                                b.lines[i + j * rows].len, stdout);
           88                         if (j < cols - 1)
           89                                 for (k = len; k < maxlen + 1; k++)
           90                                         putchar(' ');
           91                 }
           92                 putchar('\n');
           93         }
           94 
           95         ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
           96 
           97         return ret;
           98 }