add color change if argv[1] is a color in #RRGGBB format
[herbe.git] / herbe.c
diff --git a/herbe.c b/herbe.c
index 05b21b1bee3b25fcb96369f58724838d739512d5..be2411fb11b8a01c4fb22fa5bcc236f7b03136e9 100644 (file)
--- a/herbe.c
+++ b/herbe.c
@@ -1,5 +1,6 @@
 #include <X11/Xlib.h>
 #include <X11/Xft/Xft.h>
+#include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
@@ -29,6 +30,47 @@ static void die(const char *format, ...)
        exit(EXIT_FAIL);
 }
 
+char *read_stdin_walloc(void)
+{
+       char *buff = NULL;
+       size_t size = 0;
+       FILE *memstream = open_memstream(&buff, &size);
+
+       if (!memstream)
+               die("open_memstream failed");
+
+       char *temp = malloc(4096);
+       if (!temp)
+               die("malloc failed");
+
+       size_t len;
+       while ((len = fread(temp, 1, 4096, stdin)) > 0)
+               fwrite(temp, 1, len, memstream);
+
+       free(temp);
+       fclose(memstream);
+
+       return buff;
+}
+
+char *invert_color(const char *color)
+{
+       char c;
+       static char inverted[8];
+
+       strcpy(inverted, color);
+       for (int i = 1; i < 7; i++)
+       {
+               c = color[i];
+                       inverted[i] = (c < 'a') ?
+                       "0123456789ABCDEF"[15 - (c - '0' - (c > '9' ? 7 : 0))] :
+                       "0123456789abcdef"[15 - (c - 'a')];
+       }
+
+       inverted[7] = '\0';
+       return inverted;
+}
+
 int get_max_len(char *string, XftFont *font, int max_text_width)
 {
        int eol = strlen(string);
@@ -56,7 +98,7 @@ int get_max_len(char *string, XftFont *font, int max_text_width)
                        return ++i;
                }
 
-       if (info.width < max_text_width)
+       if (info.width <= max_text_width)
                return eol;
 
        int temp = eol;
@@ -81,14 +123,70 @@ void expire(int sig)
 
 int main(int argc, char *argv[])
 {
-       if (argc == 1)
+       int nargc = 0, rstatus;
+       regex_t regex;
+       regmatch_t match;
+       char **nargv = NULL;
+       char *body = NULL, *bptr;
+       const char *pattern = "#[a-fA-F0-9]{6}";
+
+       if (!isatty(STDIN_FILENO))
+       {
+               body = read_stdin_walloc();
+               bptr = body;
+
+               while (*bptr)
+               {
+                       if (*bptr == '\n' && *(bptr + 1)) nargc++;
+                       bptr++;
+               }
+
+               nargc++;
+               bptr = body;
+
+               nargv = malloc((argc + nargc) * sizeof(char *));
+               if (!nargv)
+                       die("malloc failed");
+
+               memcpy(nargv, argv, argc * sizeof(char *));
+
+               int c = argc;
+               nargv[c] = body;
+               c++;
+
+               while (*bptr)
+               {
+                       if (c == nargc + argc) break;
+                       if (*bptr == '\n' && *(bptr + 1))
+                       {
+                               nargv[c] = bptr+1;
+                               *bptr = '\0';
+                               c++;
+                       }
+                       bptr++;
+               }
+
+               argc += nargc;
+               argv = nargv;
+       }
+       else if (argc == 1)
        {
                sem_unlink("/herbe");
-               die("Usage: %s body", argv[0]);
+               die("usage: %s [body]", argv[0]);
        }
 
        struct sigaction act_expire, act_ignore;
 
+       if ((rstatus = regcomp(&regex, pattern, REG_EXTENDED)))
+               die("%s: regex compilation failed", argv[0]);
+
+       if (!(rstatus = regexec(&regex, argv[1], 1, &match, 0)))
+       {
+               background_color = argv[1];
+               font_color = invert_color(argv[1]);
+               border_color = font_color;
+       }
+
        act_expire.sa_handler = expire;
        act_expire.sa_flags = SA_RESTART;
        sigemptyset(&act_expire.sa_mask);
@@ -133,13 +231,13 @@ int main(int argc, char *argv[])
 
        for (int i = 1; i < argc; i++)
        {
-               for (unsigned int eol = get_max_len(argv[i], font, max_text_width); eol <= strlen(argv[i]) && eol; argv[i] += eol, num_of_lines++, eol = get_max_len(argv[i], font, max_text_width))
+               for (unsigned int eol = get_max_len(argv[i], font, max_text_width); eol; argv[i] += eol, num_of_lines++, eol = get_max_len(argv[i], font, max_text_width))
                {
                        if (lines_size <= num_of_lines)
                        {
                                lines = realloc(lines, (lines_size += 5) * sizeof(char *));
                                if (!lines)
-                                       die("malloc failed");
+                                       die("realloc failed");
                        }
 
                        lines[num_of_lines] = malloc((eol + 1) * sizeof(char));
@@ -210,11 +308,16 @@ int main(int argc, char *argv[])
        for (int i = 0; i < num_of_lines; i++)
                free(lines[i]);
 
+       if (nargv)
+               free(nargv);
+       if (body)
+               free(body);
        free(lines);
+       regfree(&regex);
        XftDrawDestroy(draw);
        XftColorFree(display, visual, colormap, &color);
        XftFontClose(display, font);
        XCloseDisplay(display);
 
        return exit_code;
-}
\ No newline at end of file
+}