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 }