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 51d39904aa2a57c24f0cf38054e704aff67c74d0..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);
@@ -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);
@@ -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
+}