Finish multiline support
[herbe.git] / herbe.c
diff --git a/herbe.c b/herbe.c
index 9ab2eb33b506b80dc8b961f050d1707df6022c29..c05da39b1880674116990225b9ad22476caaab23 100644 (file)
--- a/herbe.c
+++ b/herbe.c
@@ -20,11 +20,14 @@ void expire()
 
 int main(int argc, char *argv[])
 {
-       if (argc != 2) {
+       if (argc != 2)
+       {
                fprintf(stderr, "Usage: herbe message\n");
                exit(EXIT_FAILURE);
        }
 
+       char *body = argv[1];
+
        signal(SIGALRM, expire);
        alarm(duration);
 
@@ -37,45 +40,86 @@ int main(int argc, char *argv[])
        }
 
        int screen = DefaultScreen(display);
+       Visual *visual = DefaultVisual(display, screen);
+       Colormap colormap = DefaultColormap(display, screen);
 
-       int window_width = DisplayWidth(display, screen);
-       int window_height = DisplayHeight(display, screen);
+       int screen_width = DisplayWidth(display, screen);
+       int screen_height = DisplayHeight(display, screen);
 
        XftColor color;
 
-       Window root = RootWindow(display, screen);
        XSetWindowAttributes attributes;
        attributes.override_redirect = True;
-       XftColorAllocName(display, DefaultVisual(display, screen), DefaultColormap(display, screen), background_color, &color);
+       XftColorAllocName(display, visual, colormap, background_color, &color);
        attributes.background_pixel = color.pixel;
-       XftColorAllocName(display, DefaultVisual(display, screen), DefaultColormap(display, screen), border_color, &color);
+       XftColorAllocName(display, visual, colormap, border_color, &color);
        attributes.border_pixel = color.pixel;
 
-       XftFont *font = XftFontOpenName(display, screen, font_style);
+       XftFont *font = XftFontOpenName(display, screen, font_pattern);
 
-       unsigned short x = pos_x;
-       unsigned short y = pos_y;
-       int height = font->ascent - font->descent + text_padding * 2;
-       switch (corner)
+       int max_text_width = width - 2 * padding;
+       int eols_size = 5;
+       int *eols = malloc(eols_size * sizeof(int));
+       eols[0] = 0;
+       int remainder = strlen(body);
+       int num_of_lines = 1;
+
+       while (1)
        {
-               case down_right:
-                       y = window_height - height - border_size * 2 - pos_y;
-               case top_right:
-                       x = window_width - width - border_size * 2 - pos_x;
+               XGlyphInfo info;
+               info.width = 0;
+               int eol = max_text_width / font->max_advance_width;
+               while (info.width < max_text_width)
+               {
+                       eol++;
+                       XftTextExtentsUtf8(display, font, body, eol, &info);
+               }
+
+               --eol;
+
+               if (eol >= remainder)
+               {
+                       if (eols_size < num_of_lines + 1)
+                       {
+                               eols_size += 5;
+                               eols = realloc(eols, eols_size * sizeof(int));
+                       }
+                       eols[num_of_lines] = eols[num_of_lines - 1] + remainder;
+                       num_of_lines++;
                        break;
-               case down_left:
-                       y = window_height - height - border_size * 2 - pos_y;
+               }
+
+               remainder -= eol;
+               if (eols_size < num_of_lines + 1)
+               {
+                       eols_size += 5;
+                       eols = realloc(eols, eols_size * sizeof(int));
+               }
+               eols[num_of_lines] = eols[num_of_lines - 1] + eol;
+               num_of_lines++;
+       }
+
+       unsigned int x = pos_x;
+       unsigned int y = pos_y;
+       unsigned int text_height = font->ascent - font->descent;
+       unsigned int height = (num_of_lines - 2) * line_spacing + (num_of_lines - 1) * text_height + 2 * padding;
+
+       switch (corner)
+       {
+       case BOTTOM_RIGHT:
+               y = screen_height - height - border_size * 2 - pos_y;
+       case TOP_RIGHT:
+               x = screen_width - width - border_size * 2 - pos_x;
+               break;
+       case BOTTOM_LEFT:
+               y = screen_height - height - border_size * 2 - pos_y;
        }
 
-       window = XCreateWindow(
-                       display, root, x,
-                       y, width, height, border_size,
-                       DefaultDepth(display, screen), CopyFromParent,
-                       DefaultVisual(display, screen),
-                       CWOverrideRedirect | CWBackPixel | CWBorderPixel, &attributes);
+       window = XCreateWindow(display, RootWindow(display, screen), x, y, width, height, border_size, DefaultDepth(display, screen), CopyFromParent, visual,
+                                                  CWOverrideRedirect | CWBackPixel | CWBorderPixel, &attributes);
 
-       XftDraw *draw = XftDrawCreate(display, window, DefaultVisual(display, screen), DefaultColormap(display, screen));
-       XftColorAllocName(display, DefaultVisual(display, screen), DefaultColormap(display, screen), font_color, &color);
+       XftDraw *draw = XftDrawCreate(display, window, visual, colormap);
+       XftColorAllocName(display, visual, colormap, font_color, &color);
 
        XSelectInput(display, window, ExposureMask | ButtonPress);
 
@@ -90,16 +134,18 @@ int main(int argc, char *argv[])
                if (event.type == Expose)
                {
                        XClearWindow(display, window);
-                       XftDrawStringUtf8(draw, &color, font, text_padding, height - text_padding, (XftChar8 *)argv[1], strlen(argv[1]));
+                       for (int i = 1; i < num_of_lines; i++)
+                               XftDrawStringUtf8(draw, &color, font, padding, line_spacing * (i - 1) + text_height * i + padding, body + eols[i - 1], eols[i] - eols[i - 1]);
                }
                if (event.type == ButtonPress)
                        break;
        }
 
+       free(eols);
        XftDrawDestroy(draw);
-       XftColorFree(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &color);
+       XftColorFree(display, visual, colormap, &color);
        XftFontClose(display, font);
 
        XCloseDisplay(display);
-       return 0;
-}
+       return EXIT_SUCCESS;
+}
\ No newline at end of file