add multiline support
authorMarkus Teich <markus.teich@stusta.mhn.de>
Sat, 7 Nov 2015 22:54:23 +0000 (23:54 +0100)
committerMarkus Teich <markus.teich@stusta.mhn.de>
Wed, 11 Nov 2015 22:46:24 +0000 (23:46 +0100)
config.def.h
example
sent.c

index 11221eed3a32a47c16750d3244206af126ae6284..9e4d5e71d314f7da001146c22d52c9027f5406a3 100644 (file)
@@ -11,6 +11,8 @@ static char *fontfallbacks[] = {
 static const char *fgcol = "#000000";
 static const char *bgcol = "#FFFFFF";
 
+static const float linespacing = 1.4;
+
 /* how much screen estate is to be used at max for the content */
 static const float usablewidth = 0.75;
 static const float usableheight = 0.75;
diff --git a/example b/example
index 09964e63b4dd3f703d75e3de50b3ca3ae93c3af1..19dd27eb11f4f94a4e752096c8eb763635b0f24f 100644 (file)
--- a/example
+++ b/example
@@ -1,14 +1,58 @@
 sent
-takahashi
-why?
+
+Origin:
+     Takahashi
+
+Why?
+• PPTX sucks
+• LATEX sucks
+• PDF sucks
+
+also:
+terminal presentations
+don't support images…
+
 @nyan.png
+this text will not be displayed, since the @ at the start of the first line
+makes this paragraph an image slide.
+
 easy to use
-depends on Xlib, libpng
+
+depends on
+♽ Xlib
+☢ libpng
+
 ~1000 lines of code
-how?
-sent FILENAME
-one slide per line
+
+usage:
+$ sent FILE1 [FILE2 …]
+
+▸ one slide per paragraph
+▸ lines starting with # are ignored
+▸ paragraphs starting with a @ line are png images
+▸ for an empty slide just use a \ as a paragraph
+
 # This is a comment and will not be part of the presentation
-# The next line starts with a whitespace, it will not produce an image slide
- @FILE.png
-thanks / questions?
+
+# multiple empty lines between paragraphs are also ignored
+
+
+# The following lines should produce
+# one empty slide
+
+
+
+\
+\
+
+\@this_line_actually_started_with_a_\.png
+\#This line as well
+⇒ Prepend a backslash to kill behaviour of special characters
+
+😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏
+😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟
+😠😡😢😣😥😦😧😨😩😪😫😭😮😯😰😱
+😲😳😴😵😶😷😸😹😺😻😼😽😾😿🙀☠
+
+thanks
+questions?
diff --git a/sent.c b/sent.c
index 8ef7e3395c472cbda78bb822cd2a7b753e4e5ff8..c4696be10e72285413b3a36cf899b7991d49e5bd 100644 (file)
--- a/sent.c
+++ b/sent.c
@@ -43,7 +43,8 @@ typedef struct {
 } Image;
 
 typedef struct {
-       char *text;
+       unsigned int linecount;
+       char **lines;
        Image *img;
 } Slide;
 
@@ -85,7 +86,7 @@ static int pngprepare(Image *img);
 static void pngscale(Image *img);
 static void pngdraw(Image *img);
 
-static void getfontsize(char *str, unsigned int *width, unsigned int *height);
+static void getfontsize(Slide *s, unsigned int *width, unsigned int *height);
 static void cleanup();
 static void eprintf(const char *, ...);
 static void die(const char *, ...);
@@ -149,7 +150,7 @@ Image *pngopen(char *filename)
                return NULL;
        }
        if (!(img->info_ptr = png_create_info_struct(img->png_ptr))
-               || setjmp(png_jmpbuf(img->png_ptr))) {
+           || setjmp(png_jmpbuf(img->png_ptr))) {
                pngfree(img);
                return NULL;
        }
@@ -315,28 +316,38 @@ void pngdraw(Image *img)
        img->state |= DRAWN;
 }
 
-void getfontsize(char *str, unsigned int *width, unsigned int *height)
+void getfontsize(Slide *s, unsigned int *width, unsigned int *height)
 {
-       size_t i;
+       size_t i, j;
+       unsigned int curw, imax;
+       float lfac = linespacing * (s->linecount - 1) + 1;
 
-       for (i = 0; i < NUMFONTSCALES; i++) {
-               drw_setfontset(d, fonts[i]);
-               *height = fonts[i]->h;
-               *width = drw_fontset_getwidth(d, str);
-               if (*width  > xw.uw || *height > xw.uh)
+       /* fit height */
+       for (j = NUMFONTSCALES - 1; j >= 0; j--)
+               if (fonts[j]->h * lfac <= xw.uh)
                        break;
+       drw_setfontset(d, fonts[j]);
+
+       /* fit width */
+       *width = 0;
+       for (i = 0; i < s->linecount; i++) {
+               curw = drw_fontset_getwidth(d, s->lines[i]);
+               if (curw >= *width)
+                       imax = i;
+               while (j >= 0 && curw > xw.uw) {
+                       drw_setfontset(d, fonts[--j]);
+                       curw = drw_fontset_getwidth(d, s->lines[i]);
+               }
+               if (imax == i)
+                       *width = curw;
        }
-       if (i > 0) {
-               drw_setfontset(d, fonts[i-1]);
-               *height = fonts[i-1]->h;
-               *width = drw_fontset_getwidth(d, str);
-       }
-       *width += d->fonts->h;
+       *height = fonts[j]->h * lfac;
+       *width += fonts[j]->h;
 }
 
 void cleanup()
 {
-       unsigned int i;
+       unsigned int i, j;
 
        for (i = 0; i < NUMFONTSCALES; i++)
                drw_fontset_free(fonts[i]);
@@ -348,8 +359,9 @@ void cleanup()
        XCloseDisplay(xw.dpy);
        if (slides) {
                for (i = 0; i < slidecount; i++) {
-                       if (slides[i].text)
-                               free(slides[i].text);
+                       for (j = 0; j < slides[i].linecount; j++)
+                               free(slides[i].lines[j]);
+                       free(slides[i].lines);
                        if (slides[i].img)
                                pngfree(slides[i].img);
                }
@@ -394,27 +406,57 @@ void eprintf(const char *fmt, ...)
 void load(FILE *fp)
 {
        static size_t size = 0;
+       size_t blen, maxlines;
        char buf[BUFSIZ], *p;
-       size_t i = slidecount;
+       Slide *s;
 
        /* read each line from fp and add it to the item list */
-       while (fgets(buf, sizeof(buf), fp)) {
-               if ((i+1) * sizeof(*slides) >= size)
+       while (1) {
+               if ((slidecount+1) * sizeof(*slides) >= size)
                        if (!(slides = realloc(slides, (size += BUFSIZ))))
                                die("cannot realloc %u bytes:", size);
-               if (*buf == '#')
-                       continue;
-               if ((p = strchr(buf, '\n')))
-                       *p = '\0';
-               if (!(slides[i].text = strdup(buf)))
-                       die("cannot strdup %u bytes:", strlen(buf)+1);
-               if (slides[i].text[0] == '@')
-                       slides[i].img = pngopen(slides[i].text + 1);
-               else
-                       slides[i].img = 0;
-               i++;
+
+               /* eat consecutive empty lines */
+               while ((p = fgets(buf, sizeof(buf), fp)))
+                       if (strcmp(buf, "\n") != 0 && buf[0] != '#')
+                               break;
+               if (!p)
+                       break;
+
+               /* read one slide */
+               maxlines = 0;
+               memset((s = &slides[slidecount]), 0, sizeof(Slide));
+               do {
+                       if (buf[0] == '#')
+                               continue;
+
+                       /* grow lines array */
+                       if (s->linecount >= maxlines) {
+                               maxlines = 2 * s->linecount + 1;
+                               if (!(s->lines = realloc(s->lines, maxlines * sizeof(s->lines[0]))))
+                                       die("cannot realloc %u bytes:", maxlines * sizeof(s->lines[0]));
+                       }
+
+                       blen = strlen(buf);
+                       if (!(s->lines[s->linecount] = strdup(buf)))
+                               die("cannot strdup:");
+                       if (s->lines[s->linecount][blen-1] == '\n')
+                               s->lines[s->linecount][blen-1] = '\0';
+
+                       /* only make image slide if first line of a slide starts with @ */
+                       if (s->linecount == 0 && s->lines[0][0] == '@') {
+                               memmove(s->lines[0], &s->lines[0][1], blen);
+                               s->img = pngopen(s->lines[0]);
+                       }
+
+                       if (s->lines[s->linecount][0] == '\\')
+                               memmove(s->lines[s->linecount], &s->lines[s->linecount][1], blen);
+                       s->linecount++;
+               } while ((p = fgets(buf, sizeof(buf), fp)) && strcmp(buf, "\n") != 0);
+               slidecount++;
+               if (!p)
+                       break;
        }
-       slidecount = i;
 }
 
 void advance(const Arg *arg)
@@ -427,9 +469,9 @@ void advance(const Arg *arg)
                idx = new_idx;
                xdraw();
                if (slidecount > idx + 1 && slides[idx + 1].img && !pngread(slides[idx + 1].img))
-                       die("could not read image %s", slides[idx + 1].text + 1);
+                       die("could not read image %s", slides[idx + 1].lines[0]);
                if (0 < idx && slides[idx - 1].img && !pngread(slides[idx - 1].img))
-                       die("could not read image %s", slides[idx - 1].text + 1);
+                       die("could not read image %s", slides[idx - 1].lines[0]);
        }
 }
 
@@ -476,20 +518,27 @@ void usage()
 
 void xdraw()
 {
-       unsigned int height, width;
+       unsigned int height, width, i;
        Image *im = slides[idx].img;
 
-       getfontsize(slides[idx].text, &width, &height);
+       getfontsize(&slides[idx], &width, &height);
        XClearWindow(xw.dpy, xw.win);
 
        if (!im) {
                drw_rect(d, 0, 0, xw.w, xw.h, 1, 1);
-               drw_text(d, (xw.w - width) / 2, (xw.h - height) / 2, width, height, slides[idx].text, 0);
+               for (i = 0; i < slides[idx].linecount; i++)
+                       drw_text(d,
+                                (xw.w - width) / 2,
+                                (xw.h - height) / 2 + i * linespacing * d->fonts->h,
+                                width,
+                                d->fonts->h,
+                                slides[idx].lines[i],
+                                0);
                drw_map(d, xw.win, 0, 0, xw.w, xw.h);
        } else if (!(im->state & LOADED) && !pngread(im)) {
-               eprintf("could not read image %s", slides[idx].text + 1);
+               eprintf("could not read image %s", slides[idx].lines[0]);
        } else if (!(im->state & SCALED) && !pngprepare(im)) {
-               eprintf("could not prepare image %s for drawing", slides[idx].text + 1);
+               eprintf("could not prepare image %s for drawing", slides[idx].lines[0]);
        } else if (!(im->state & DRAWN)) {
                pngdraw(im);
        }
@@ -634,7 +683,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       if (!slides || !slides[0].text)
+       if (!slides || !slides[0].lines)
                usage();
 
        xinit();