]> git.lizzy.rs Git - center.git/blobdiff - center.c
Add new target clean
[center.git] / center.c
index e6f13b67316dfc050d932454207127416007bae1..a08e9e7349ce1082fdd784ae7ae3e21a9fc6723f 100644 (file)
--- a/center.c
+++ b/center.c
@@ -1,14 +1,17 @@
 #define _POSIX_C_SOURCE 200809L
 #define _XOPEN_SOURCE
+#include <fcntl.h>
+#include <locale.h>
 #include <stdio.h>
-#include <wchar.h>
 #include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <termios.h>
 #include <unistd.h>
-#include <sys/ioctl.h>
-#include <locale.h>
+#include <wchar.h>
 
-#define ERR(str) { perror(str); err = EXIT_FAILURE; break; }
+#define ERR(str) { perror(str); err = EXIT_FAILURE; goto end; }
 
 int main()
 {
@@ -17,37 +20,60 @@ int main()
                exit(EXIT_FAILURE);
        }
 
-       char *ptr = NULL;
+       char *buf = NULL;
        size_t siz = 0;
-       ssize_t slen;
+       ssize_t len;
        int err = EXIT_SUCCESS;
 
-       while ((slen = getline(&ptr, &siz, stdin)) > 0) {
-               ptr[slen - 1] = '\0';
-       
-               size_t len = mbstowcs(NULL, ptr, 0);
-               if (len == (size_t) -1) ERR("msbtowcs")
+       int tty_fd = open("/dev/tty", O_RDWR);
+       if (tty_fd < 0) {
+               perror("open");
+               return EXIT_FAILURE;
+       }
+
+       while ((len = getline(&buf, &siz, stdin)) > 0) {
+               struct winsize ws;
+               if (ioctl(tty_fd, TIOCGWINSZ, &ws) < 0) ERR("ioctl")
+
+               int term_width = ws.ws_col;
 
-               wchar_t *wcs = calloc(len + 1, sizeof *wcs);
-               if (!wcs) ERR("calloc")
+               char *ptr = buf;
+               char *last = ptr;
+               int str_width = 0;
+               mbstate_t mbs = {0};
 
-               if (mbstowcs(wcs, ptr, len + 1) == (size_t) -1) ERR("msbtowcs")
+               while (len > 0) {
+                       wchar_t wc;
 
-               struct winsize ws;
-               if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) ERR("ioctl")
+                       size_t adv = mbrtowc(&wc, ptr, len, &mbs);
+                       if (adv == (size_t) -1 || adv == (size_t) -2) ERR("mbrtowc")
 
-               int trm_width = ws.ws_col;
-               int str_width = wcswidth(wcs, len);
+                       int width = wcwidth(wc);
+                       if (width > 0)
+                               str_width += width;
 
-               free(wcs);
+                       if (*ptr == '\n' || str_width >= term_width - 12) {
+                               for (int i = (term_width - str_width) / 2; i > 0; i--)
+                                       putchar(' ');
+                               fwrite(last, 1, ptr - last + 1, stdout);
 
-               for (int i = (trm_width - str_width) / 2; i > 0; i--)
-                       putchar(' ');
-               puts(ptr);
+                               if (*ptr != '\n')
+                                       putchar('\n');
+
+                               last = ptr + adv;
+                               str_width = 0;
+                       }
+
+                       ptr += adv;
+                       len -= adv;
+               }
        }
 
-       if (ptr)
-               free(ptr);
+       end:
+       close(tty_fd);
+
+       if (buf)
+               free(buf);
 
        return err;
 }