15 Commits
0.1 ... 0.2

Author SHA1 Message Date
95af430d97 Use right click as previous and enable scrolling to switch slides 2015-11-19 19:37:08 +01:00
a1dcdad14f Bail out before allocating slides if file is empty
In load() we allocated slides before checking if we actually read
anything from the FILE fp and then continue with an allocated but
“empty” space wich would lead to errors.
2015-11-18 23:26:33 +01:00
eac14478e9 fix dying on empty slidefile 2015-11-18 23:24:53 +01:00
996a4c5c6e drw.c: Avoid potential memory leak in drw_cur_create()
If drw was NULL, memory was still allocated for cur.
2015-11-18 22:50:07 +01:00
243c8cf7b6 Add Escape key to quit sent 2015-11-18 12:20:55 +01:00
cc57a28eba die if no font could be loaded 2015-11-18 00:41:38 +01:00
c3cd2edca6 Register space to advance to the next slide 2015-11-17 11:23:20 +01:00
448fe33370 shorten bulletpoints in example presentation 2015-11-17 02:26:34 +01:00
31be676486 fix dejavu font name 2015-11-17 02:07:56 +01:00
4ae761b8be support even larger screens 2015-11-17 01:39:40 +01:00
4a828c2d6c prevent flickering when changing slides
When the window background is left at WhitePixel (from initialization) and the
user has set a dark background color in config.h, the window shortly displays
the white default background when clearing after advancing to another slide.
This was very disturbing and is fixed now by setting the default window
background color to the bgcol chosen in config.h.
2015-11-17 01:04:04 +01:00
aa713a8a34 update README 2015-11-17 00:32:45 +01:00
b1cb3bbc20 fix another index overflow issue 2015-11-17 00:23:51 +01:00
84734c73e8 fix several number overflow issues 2015-11-17 00:19:39 +01:00
eb07f3dc10 update version 2015-11-17 00:18:54 +01:00
6 changed files with 51 additions and 65 deletions

View File

@ -1,70 +1,50 @@
sent sent is a simple plaintext presentation tool.
====
A simple plaintext presentation tool.
sent does not need latex, libreoffice or any other fancy file format, it uses sent does not need latex, libreoffice or any other fancy file format, it uses
plaintext files and png images. Every line represents a slide in the plaintext files and png images. Every paragraph represents a slide in the
presentation. This may limit the use, but for presentations using the [Takahashi presentation.
method](https://en.wikipedia.org/wiki/Takahashi_method) this is very nice and
allows you to write down the presentation for a quick lightning talk within a The presentation is displayed in a simple X11 window. The content of each slide
few minutes. is automatically scaled to fit the window and centered so you also don't have to
worry about alignment. Instead you can really concentrate on the content.
The presentation is displayed in a simple X11 window colored black on white for
maximum contrast even if the sun shines directly onto the projected image. The
content of each slide is automatically scaled to fit the window so you don't
have to worry about alignment. Instead you can really concentrate on the
content.
Demo Demo
----
To get a little demo, just type To get a little demo, just type
make && ./sent example make && ./sent example
You can navigate with the arrow keys and quit with `q`. If you get You can navigate with the arrow keys and quit with `q`.
sent: could not find a scalable font matching -*-dejavu sans condensed-bold-r-*-*-0-0-*-*-*-0-*-*
you should add the dejavu fonts dir (customize path to fit your distribution)
with:
xset fp+ /usr/share/fonts/dejavu
Configuration
-------------
Edit config.h to fit your needs. The font has to be in the X servers font path,
see `man xset` for how to add it.
Usage Usage
-----
sent [-f FONTSTRING] FILE1 [FILE2 ...] sent FILE1 [FILE2 ...]
If one FILE equals `-`, stdin will be read. Use png images by prepending a `@` If one FILE equals `-`, stdin will be read. Produce image slides by prepending a
before the filename. Lines starting with `#` will be ignored. A presentation `@` in front of the filename as a single paragraph. Lines starting with `#` will
file could look like this: be ignored. A `\` at the beginning of the line escapes `@` and `#`. A
presentation file could look like this:
sent sent
why?
@nyan.png @nyan.png
easy to use
depends on Xlib, libpng depends on
no bloat - Xlib
how? - libpng
sent FILENAME sent FILENAME
one slide per line one slide per paragraph
# This is a comment and will not be part of the presentation # 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 \# This and the next line start with backslashes
@FILE.png
\@FILE.png
thanks / questions? thanks / questions?
future features
---------------
* multiple lines per slide? Development
* light colored background and table of contents
* second window for speakers laptop (progress, time, notes?) sent is developed at http://tools.suckless.org/sent
* markdown?

View File

@ -1,11 +1,11 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
static char *fontfallbacks[] = { static char *fontfallbacks[] = {
"dejavu", "dejavu sans",
"roboto", "roboto",
"ubuntu", "ubuntu",
}; };
#define NUMFONTSCALES 30 #define NUMFONTSCALES 42
#define FONTSZ(x) ((int)(10.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTSCALES-1] */ #define FONTSZ(x) ((int)(10.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTSCALES-1] */
static const char *fgcol = "#000000"; static const char *fgcol = "#000000";
@ -20,15 +20,19 @@ static const float usableheight = 0.75;
static Mousekey mshortcuts[] = { static Mousekey mshortcuts[] = {
/* button function argument */ /* button function argument */
{ Button1, advance, {.i = +1} }, { Button1, advance, {.i = +1} },
{ Button2, advance, {.i = -1} }, { Button3, advance, {.i = -1} },
{ Button4, advance, {.i = -1} },
{ Button5, advance, {.i = +1} },
}; };
static Shortcut shortcuts[] = { static Shortcut shortcuts[] = {
/* keysym function argument */ /* keysym function argument */
{ XK_Escape, quit, {0} },
{ XK_q, quit, {0} }, { XK_q, quit, {0} },
{ XK_Right, advance, {.i = +1} }, { XK_Right, advance, {.i = +1} },
{ XK_Left, advance, {.i = -1} }, { XK_Left, advance, {.i = -1} },
{ XK_Return, advance, {.i = +1} }, { XK_Return, advance, {.i = +1} },
{ XK_space, advance, {.i = +1} },
{ XK_BackSpace, advance, {.i = -1} }, { XK_BackSpace, advance, {.i = -1} },
{ XK_l, advance, {.i = +1} }, { XK_l, advance, {.i = +1} },
{ XK_h, advance, {.i = -1} }, { XK_h, advance, {.i = -1} },

View File

@ -1,5 +1,5 @@
# sent version # sent version
VERSION = 0.1 VERSION = 0.2
# Customize below to fit your system # Customize below to fit your system

4
drw.c
View File

@ -396,9 +396,9 @@ drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w,
Cur * Cur *
drw_cur_create(Drw *drw, int shape) { drw_cur_create(Drw *drw, int shape) {
Cur *cur = (Cur *)calloc(1, sizeof(Cur)); Cur *cur;
if(!drw || !cur) if(!drw || !(cur = (Cur *)calloc(1, sizeof(Cur))))
return NULL; return NULL;
cur->cursor = XCreateFontCursor(drw->dpy, shape); cur->cursor = XCreateFontCursor(drw->dpy, shape);
return cur; return cur;

View File

@ -29,8 +29,8 @@ $ sent FILE1 [FILE2 …]
▸ one slide per paragraph ▸ one slide per paragraph
▸ lines starting with # are ignored ▸ lines starting with # are ignored
paragraphs starting with a @ line are png images image slide: paragraph containing @FILE.png
for an empty slide just use a \ as a paragraph ▸ empty slide: just use a \ as a paragraph
# This is a comment and will not be part of the presentation # This is a comment and will not be part of the presentation

22
sent.c
View File

@ -318,7 +318,7 @@ void pngdraw(Image *img)
void getfontsize(Slide *s, unsigned int *width, unsigned int *height) void getfontsize(Slide *s, unsigned int *width, unsigned int *height)
{ {
size_t i, j; int i, j;
unsigned int curw, imax; unsigned int curw, imax;
float lfac = linespacing * (s->linecount - 1) + 1; float lfac = linespacing * (s->linecount - 1) + 1;
@ -326,6 +326,7 @@ void getfontsize(Slide *s, unsigned int *width, unsigned int *height)
for (j = NUMFONTSCALES - 1; j >= 0; j--) for (j = NUMFONTSCALES - 1; j >= 0; j--)
if (fonts[j]->h * lfac <= xw.uh) if (fonts[j]->h * lfac <= xw.uh)
break; break;
LIMIT(j, 0, NUMFONTSCALES - 1);
drw_setfontset(d, fonts[j]); drw_setfontset(d, fonts[j]);
/* fit width */ /* fit width */
@ -334,7 +335,7 @@ void getfontsize(Slide *s, unsigned int *width, unsigned int *height)
curw = drw_fontset_getwidth(d, s->lines[i]); curw = drw_fontset_getwidth(d, s->lines[i]);
if (curw >= *width) if (curw >= *width)
imax = i; imax = i;
while (j >= 0 && curw > xw.uw) { while (j > 0 && curw > xw.uw) {
drw_setfontset(d, fonts[--j]); drw_setfontset(d, fonts[--j]);
curw = drw_fontset_getwidth(d, s->lines[i]); curw = drw_fontset_getwidth(d, s->lines[i]);
} }
@ -412,10 +413,6 @@ void load(FILE *fp)
/* read each line from fp and add it to the item list */ /* read each line from fp and add it to the item list */
while (1) { while (1) {
if ((slidecount+1) * sizeof(*slides) >= size)
if (!(slides = realloc(slides, (size += BUFSIZ))))
die("cannot realloc %u bytes:", size);
/* eat consecutive empty lines */ /* eat consecutive empty lines */
while ((p = fgets(buf, sizeof(buf), fp))) while ((p = fgets(buf, sizeof(buf), fp)))
if (strcmp(buf, "\n") != 0 && buf[0] != '#') if (strcmp(buf, "\n") != 0 && buf[0] != '#')
@ -423,6 +420,10 @@ void load(FILE *fp)
if (!p) if (!p)
break; break;
if ((slidecount+1) * sizeof(*slides) >= size)
if (!(slides = realloc(slides, (size += BUFSIZ))))
die("cannot realloc %u bytes:", size);
/* read one slide */ /* read one slide */
maxlines = 0; maxlines = 0;
memset((s = &slides[slidecount]), 0, sizeof(Slide)); memset((s = &slides[slidecount]), 0, sizeof(Slide));
@ -571,14 +572,13 @@ void xinit()
xw.vis = XDefaultVisual(xw.dpy, xw.scr); xw.vis = XDefaultVisual(xw.dpy, xw.scr);
resize(DisplayWidth(xw.dpy, xw.scr), DisplayHeight(xw.dpy, xw.scr)); resize(DisplayWidth(xw.dpy, xw.scr), DisplayHeight(xw.dpy, xw.scr));
xw.attrs.background_pixel = WhitePixel(xw.dpy, xw.scr);
xw.attrs.bit_gravity = CenterGravity; xw.attrs.bit_gravity = CenterGravity;
xw.attrs.event_mask = KeyPressMask | ExposureMask | StructureNotifyMask xw.attrs.event_mask = KeyPressMask | ExposureMask | StructureNotifyMask
| ButtonMotionMask | ButtonPressMask; | ButtonMotionMask | ButtonPressMask;
xw.win = XCreateWindow(xw.dpy, XRootWindow(xw.dpy, xw.scr), 0, 0, xw.win = XCreateWindow(xw.dpy, XRootWindow(xw.dpy, xw.scr), 0, 0,
xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis, xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput, xw.vis,
CWBackPixel | CWBitGravity | CWEventMask, &xw.attrs); CWBitGravity | CWEventMask, &xw.attrs);
xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False); xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False); xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
@ -588,6 +588,7 @@ void xinit()
die("Can't create drawing context."); die("Can't create drawing context.");
sc = drw_scm_create(d, fgcol, bgcol); sc = drw_scm_create(d, fgcol, bgcol);
drw_setscheme(d, sc); drw_setscheme(d, sc);
XSetWindowBackground(xw.dpy, xw.win, sc->bg.pix);
xloadfonts(); xloadfonts();
@ -615,7 +616,8 @@ void xloadfonts()
if (MAXFONTSTRLEN < snprintf(fstrs[j], MAXFONTSTRLEN, "%s:size=%d", fontfallbacks[j], FONTSZ(i))) if (MAXFONTSTRLEN < snprintf(fstrs[j], MAXFONTSTRLEN, "%s:size=%d", fontfallbacks[j], FONTSZ(i)))
die("font string too long"); die("font string too long");
} }
fonts[i] = drw_fontset_create(d, (const char**)fstrs, LEN(fstrs)); if (!(fonts[i] = drw_fontset_create(d, (const char**)fstrs, LEN(fstrs))))
die("unable to load any font for size %d", FONTSZ(i));
} }
for (j = 0; j < LEN(fontfallbacks); j++) for (j = 0; j < LEN(fontfallbacks); j++)
@ -683,7 +685,7 @@ int main(int argc, char *argv[])
} }
} }
if (!slides || !slides[0].lines) if (!slidecount)
usage(); usage();
xinit(); xinit();