Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
95af430d97 | |||
a1dcdad14f | |||
eac14478e9 | |||
996a4c5c6e | |||
243c8cf7b6 | |||
cc57a28eba | |||
c3cd2edca6 | |||
448fe33370 | |||
31be676486 | |||
4ae761b8be | |||
4a828c2d6c | |||
aa713a8a34 | |||
b1cb3bbc20 | |||
84734c73e8 | |||
eb07f3dc10 |
74
README.md
74
README.md
@ -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?
|
|
||||||
|
10
config.def.h
10
config.def.h
@ -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} },
|
||||||
|
@ -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
4
drw.c
@ -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;
|
||||||
|
4
example
4
example
@ -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
22
sent.c
@ -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();
|
||||||
|
Reference in New Issue
Block a user