Introduction
Introduction Statistics Contact Development Disclaimer Help
add multiline support - sent - simple plaintext presentation tool
git clone git://git.suckless.org/sent
Log
Files
Refs
README
LICENSE
---
commit 22a0a7f25596c28588bac5bf9e12cd8c534684d4
parent d7eac23083be2278327e94255a182a221a0df273
Author: Markus Teich <[email protected]>
Date: Sat, 7 Nov 2015 23:54:23 +0100
add multiline support
Diffstat:
M config.def.h | 2 ++
M example | 62 ++++++++++++++++++++++++++---…
M sent.c | 133 +++++++++++++++++++++--------…
3 files changed, 146 insertions(+), 51 deletions(-)
---
diff --git a/config.def.h b/config.def.h
@@ -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
@@ -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
@@ -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 * …
+ die("cannot realloc %u bytes:", maxlin…
+ }
+
+ 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 star…
+ 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->l…
+ s->linecount++;
+ } while ((p = fgets(buf, sizeof(buf), fp)) && strcmp(buf, "\n"…
+ 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(sl…
- die("could not read image %s", slides[idx + 1].text + …
+ die("could not read image %s", slides[idx + 1].lines[0…
if (0 < idx && slides[idx - 1].img && !pngread(slides[idx - 1]…
- die("could not read image %s", slides[idx - 1].text + …
+ 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, he…
+ for (i = 0; i < slides[idx].linecount; i++)
+ drw_text(d,
+ (xw.w - width) / 2,
+ (xw.h - height) / 2 + i * linespacing * d->fo…
+ 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].…
+ eprintf("could not prepare image %s for drawing", slides[idx].…
} 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();
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.