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 }