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
|
||||
====
|
||||
|
||||
A simple plaintext presentation tool.
|
||||
sent is a simple plaintext presentation tool.
|
||||
|
||||
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
|
||||
presentation. This may limit the use, but for presentations using the [Takahashi
|
||||
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
|
||||
few minutes.
|
||||
plaintext files and png images. Every paragraph represents a slide in the
|
||||
presentation.
|
||||
|
||||
The presentation is displayed in a simple X11 window. The content of each slide
|
||||
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
|
||||
----
|
||||
|
||||
To get a little demo, just type
|
||||
|
||||
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
|
||||
-----
|
||||
|
||||
sent [-f FONTSTRING] FILE1 [FILE2 ...]
|
||||
sent FILE1 [FILE2 ...]
|
||||
|
||||
If one FILE equals `-`, stdin will be read. Use png images by prepending a `@`
|
||||
before the filename. Lines starting with `#` will be ignored. A presentation
|
||||
file could look like this:
|
||||
If one FILE equals `-`, stdin will be read. Produce image slides by prepending a
|
||||
`@` in front of the filename as a single paragraph. Lines starting with `#` will
|
||||
be ignored. A `\` at the beginning of the line escapes `@` and `#`. A
|
||||
presentation file could look like this:
|
||||
|
||||
sent
|
||||
why?
|
||||
|
||||
@nyan.png
|
||||
easy to use
|
||||
depends on Xlib, libpng
|
||||
no bloat
|
||||
how?
|
||||
|
||||
depends on
|
||||
- Xlib
|
||||
- libpng
|
||||
|
||||
sent FILENAME
|
||||
one slide per line
|
||||
one slide per 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
|
||||
\# This and the next line start with backslashes
|
||||
|
||||
\@FILE.png
|
||||
|
||||
thanks / questions?
|
||||
|
||||
future features
|
||||
---------------
|
||||
|
||||
* multiple lines per slide?
|
||||
* light colored background and table of contents
|
||||
* second window for speakers laptop (progress, time, notes?)
|
||||
* markdown?
|
||||
Development
|
||||
|
||||
sent is developed at http://tools.suckless.org/sent
|
||||
|
10
config.def.h
10
config.def.h
@ -1,11 +1,11 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
static char *fontfallbacks[] = {
|
||||
"dejavu",
|
||||
"dejavu sans",
|
||||
"roboto",
|
||||
"ubuntu",
|
||||
};
|
||||
#define NUMFONTSCALES 30
|
||||
#define NUMFONTSCALES 42
|
||||
#define FONTSZ(x) ((int)(10.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTSCALES-1] */
|
||||
|
||||
static const char *fgcol = "#000000";
|
||||
@ -20,15 +20,19 @@ static const float usableheight = 0.75;
|
||||
static Mousekey mshortcuts[] = {
|
||||
/* button function argument */
|
||||
{ Button1, advance, {.i = +1} },
|
||||
{ Button2, advance, {.i = -1} },
|
||||
{ Button3, advance, {.i = -1} },
|
||||
{ Button4, advance, {.i = -1} },
|
||||
{ Button5, advance, {.i = +1} },
|
||||
};
|
||||
|
||||
static Shortcut shortcuts[] = {
|
||||
/* keysym function argument */
|
||||
{ XK_Escape, quit, {0} },
|
||||
{ XK_q, quit, {0} },
|
||||
{ XK_Right, advance, {.i = +1} },
|
||||
{ XK_Left, advance, {.i = -1} },
|
||||
{ XK_Return, advance, {.i = +1} },
|
||||
{ XK_space, advance, {.i = +1} },
|
||||
{ XK_BackSpace, advance, {.i = -1} },
|
||||
{ XK_l, advance, {.i = +1} },
|
||||
{ XK_h, advance, {.i = -1} },
|
||||
|
@ -1,5 +1,5 @@
|
||||
# sent version
|
||||
VERSION = 0.1
|
||||
VERSION = 0.2
|
||||
|
||||
# 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 *
|
||||
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;
|
||||
cur->cursor = XCreateFontCursor(drw->dpy, shape);
|
||||
return cur;
|
||||
|
4
example
4
example
@ -29,8 +29,8 @@ $ 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
|
||||
▸ image slide: paragraph containing @FILE.png
|
||||
▸ empty slide: just use a \ as a paragraph
|
||||
|
||||
# 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)
|
||||
{
|
||||
size_t i, j;
|
||||
int i, j;
|
||||
unsigned int curw, imax;
|
||||
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--)
|
||||
if (fonts[j]->h * lfac <= xw.uh)
|
||||
break;
|
||||
LIMIT(j, 0, NUMFONTSCALES - 1);
|
||||
drw_setfontset(d, fonts[j]);
|
||||
|
||||
/* fit width */
|
||||
@ -334,7 +335,7 @@ void getfontsize(Slide *s, unsigned int *width, unsigned int *height)
|
||||
curw = drw_fontset_getwidth(d, s->lines[i]);
|
||||
if (curw >= *width)
|
||||
imax = i;
|
||||
while (j >= 0 && curw > xw.uw) {
|
||||
while (j > 0 && curw > xw.uw) {
|
||||
drw_setfontset(d, fonts[--j]);
|
||||
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 */
|
||||
while (1) {
|
||||
if ((slidecount+1) * sizeof(*slides) >= size)
|
||||
if (!(slides = realloc(slides, (size += BUFSIZ))))
|
||||
die("cannot realloc %u bytes:", size);
|
||||
|
||||
/* eat consecutive empty lines */
|
||||
while ((p = fgets(buf, sizeof(buf), fp)))
|
||||
if (strcmp(buf, "\n") != 0 && buf[0] != '#')
|
||||
@ -423,6 +420,10 @@ void load(FILE *fp)
|
||||
if (!p)
|
||||
break;
|
||||
|
||||
if ((slidecount+1) * sizeof(*slides) >= size)
|
||||
if (!(slides = realloc(slides, (size += BUFSIZ))))
|
||||
die("cannot realloc %u bytes:", size);
|
||||
|
||||
/* read one slide */
|
||||
maxlines = 0;
|
||||
memset((s = &slides[slidecount]), 0, sizeof(Slide));
|
||||
@ -571,14 +572,13 @@ void xinit()
|
||||
xw.vis = XDefaultVisual(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.event_mask = KeyPressMask | ExposureMask | StructureNotifyMask
|
||||
| ButtonMotionMask | ButtonPressMask;
|
||||
|
||||
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,
|
||||
CWBackPixel | CWBitGravity | CWEventMask, &xw.attrs);
|
||||
CWBitGravity | CWEventMask, &xw.attrs);
|
||||
|
||||
xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
|
||||
xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
|
||||
@ -588,6 +588,7 @@ void xinit()
|
||||
die("Can't create drawing context.");
|
||||
sc = drw_scm_create(d, fgcol, bgcol);
|
||||
drw_setscheme(d, sc);
|
||||
XSetWindowBackground(xw.dpy, xw.win, sc->bg.pix);
|
||||
|
||||
xloadfonts();
|
||||
|
||||
@ -615,7 +616,8 @@ void xloadfonts()
|
||||
if (MAXFONTSTRLEN < snprintf(fstrs[j], MAXFONTSTRLEN, "%s:size=%d", fontfallbacks[j], FONTSZ(i)))
|
||||
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++)
|
||||
@ -683,7 +685,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (!slides || !slides[0].lines)
|
||||
if (!slidecount)
|
||||
usage();
|
||||
|
||||
xinit();
|
||||
|
Reference in New Issue
Block a user