]> git.lizzy.rs Git - center.git/blob - center.c
Fix empty lines
[center.git] / center.c
1 #define _POSIX_C_SOURCE 200809L
2 #define _XOPEN_SOURCE
3 #include <stdio.h>
4 #include <wchar.h>
5 #include <stdlib.h>
6 #include <termios.h>
7 #include <unistd.h>
8 #include <sys/ioctl.h>
9 #include <locale.h>
10
11 #define ERR(str) { perror(str); err = EXIT_FAILURE; goto end; }
12
13 int main()
14 {
15         if (setlocale(LC_ALL, "") == NULL) {
16                 perror("setlocale");
17                 exit(EXIT_FAILURE);
18         }
19
20         char *buf = NULL;
21         size_t siz = 0;
22         ssize_t len;
23         int err = EXIT_SUCCESS;
24
25         while ((len = getline(&buf, &siz, stdin)) > 0) {
26                 struct winsize ws;
27                 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) ERR("ioctl")
28
29                 int term_width = ws.ws_col;
30
31                 char *ptr = buf;
32                 char *last = ptr;
33                 int str_width = 0;
34                 mbstate_t mbs = {0};
35
36                 while (len > 0) {
37                         wchar_t wc;
38
39                         size_t adv = mbrtowc(&wc, ptr, len, &mbs);
40                         if (adv == (size_t) -1 || adv == (size_t) -2) ERR("mbrtowc")
41
42                         int width = wcwidth(wc);
43                         if (width > 0)
44                                 str_width += width;
45
46                         if (*ptr == '\n' || str_width >= term_width - 12) {
47                                 for (int i = (term_width - str_width) / 2; i > 0; i--)
48                                         putchar(' ');
49                                 fwrite(last, 1, ptr - last + 1, stdout);
50
51                                 if (*ptr != '\n')
52                                         putchar('\n');
53
54                                 last = ptr + adv;
55                                 str_width = 0;
56                         }
57
58                         ptr += adv;
59                         len -= adv;
60                 }
61         }
62
63         end:
64         if (buf)
65                 free(buf);
66
67         return err;
68 }