@@ 5,9 5,6 @@
#include <event.h>
#include <cursor.h>
-int checkonly;
-char *file, *contents;
-
typedef struct Slide {
char *cmd;
char *arg;
@@ 16,11 13,60 @@ typedef struct Slide {
char *lines[];
} Slide;
+enum {
+ MenuNext = 0,
+ MenuPrev,
+ MenuExit,
+ MenuN
+};
+
+char *menuitems[] = {
+ [MenuNext] = "Next Slide",
+ [MenuPrev] = "Prev Slide",
+ [MenuExit] = "Exit",
+ nil
+};
+Menu menu = {
+ .item = menuitems
+};
+
+int checkonly, lightmode, nslides, cslide, xm, ym;
+char *file, *contents, *offset, *tfname, *hfname;
+Image *bg,*fg,*tmp;
+Font *tfont, *hfont;
+Slide **slides;
+
+Point
+SPt(int x, int y)
+{
+ return addpt(Pt(x, y), screen->r.min);
+}
+
+Rectangle
+SRect(int x0, int y0, int x1, int y1)
+{
+ return rectaddpt(Rect(x0, y0, x1, y1), screen->r.min);
+}
+
+Point
+imagecenter(Image* img)
+{
+ return divpt(addpt(img->r.min, img->r.max), 2);
+}
+
+double
+imageradius(Image* img)
+{
+ Point dims;
+ dims = divpt(subpt(img->r.max, img->r.min), 2);
+ return 1.4 + sqrt(dims.x*dims.x + dims.y*dims.y);
+}
+
char *
nextline(char **p, int *linum)
{
char *line;
- while(1){
+ for(;;){
(*linum)++;
line = *p;
while(**p != '\n' && **p != '\0') (*p)++;
@@ 40,7 86,7 @@ nextslide(char **p, int *linum)
int nlines, blines, i, slinum;
Slide *s;
- while(1){
+ for(;;){
if((cmd = nextline(p, linum)) == nil)
return nil;
if(cmd[0] != '%')
@@ 140,9 186,11 @@ checkfile(void)
p = c2;
while((s = nextslide(&p, &linum)) != nil){
- if(strcmp(s->cmd, "") == 0)
+ nslides++;
+ if(strcmp(s->cmd, "") == 0){
+ nslides--;
continue;
- else if(strcmp(s->cmd, "bullet") == 0)
+ }else if(strcmp(s->cmd, "bullet") == 0)
continue;
else if(strcmp(s->cmd, "blank") == 0)
continue;
@@ 164,22 212,110 @@ checkfile(void)
}
void
+render(void)
+{
+ int i, voff, height, width;
+ Point p, center, prog0, prog1, smin, smax;
+ const Slide *s;
+
+ if(cslide < 0)
+ cslide = 0;
+ else if(cslide >= nslides)
+ cslide = nslides -1;
+
+ s = slides[cslide];
+
+ center = imagecenter(screen);
+ smin = screen->r.min;
+ smax = screen->r.max;
+
+ draw(screen, screen->r, bg, nil, SPt(0, 0));
+
+ prog0 = Pt(smin.x, smax.y);
+ prog1 = Pt(smin.x + cslide + (smax.x - smin.x) / (nslides - 1) * cslide, smax.y);
+ if(cslide != 0)
+ line(screen, prog0, prog1, Endsquare, Enddisc, 5, fg, Pt(0,0));
+
+ if(strcmp(s->cmd, "text") == 0){
+ voff = ym;
+ if(s->arg != nil){
+ string(screen, SPt(xm, ym), fg, Pt(0, 0), hfont, s->arg);
+ voff += hfont->height;
+ }else
+ voff = xm;
+ for(i = 0; i < s->nlines; i++){
+ string(screen, SPt(xm + 10, voff), fg, Pt(0, 0), tfont, s->lines[i]);
+ voff += tfont->height;
+ }
+ }else if(strcmp(s->cmd, "title") == 0){
+ height = hfont->height + tfont->height * s->nlines;
+ voff = center.y - (height / 2);
+
+ p = string(screen, smax, fg, Pt(0,0), hfont, s->arg);
+ width = p.x - smax.x;
+ string(screen, Pt(center.x - (width / 2), voff), fg, Pt(0,0), hfont, s->arg);
+
+ voff += hfont->height;
+
+ for(i = 0; i < s->nlines; i++){
+ p = string(screen, smax, fg, Pt(0,0), tfont, s->lines[i]);
+ width = p.x - smax.x;
+ string(screen, Pt(center.x - (width / 2), voff), fg, Pt(0,0), tfont, s->lines[i]);
+ voff += tfont->height;
+ }
+
+ }
+}
+
+void
+eresized(int new)
+{
+ if(new && getwindow(display, Refnone) < 0)
+ fprint(2,"can't reattach to window\n");
+ render();
+}
+
+void
usage(void)
{
- fprint(2,"usage: %s [ -c ] filename\n", argv0);
+ fprint(2,"usage: %s [ -cl ] [ -x xmargin ] [ -y ymargin ] [ -f textfont ] [ -h headerfont ] filename\n", argv0);
exits("usage");
}
void
main(int argc, char *argv[])
{
- int fd;
+ int etype, fd, i, linum;
+ char slabel[32];
+ Event e;
+ Mouse m, lastm;
Dir *d;
+ xm = 50;
+ ym = 10;
+
+ tfname = "/n/ttf/lucida.ttf.32/font";
+ hfname = "/n/ttf/lucida.ttf.80/font";
+
ARGBEGIN{
case 'c':
checkonly = 1;
break;
+ case 'l':
+ lightmode = 1;
+ break;
+ case 'f':
+ tfname = EARGF(usage());
+ break;
+ case 'h':
+ hfname = EARGF(usage());
+ break;
+ case 'x':
+ xm = atoi(EARGF(usage()));
+ break;
+ case 'y':
+ ym = atoi(EARGF(usage()));
+ break;
default:
usage();
}ARGEND
@@ 200,6 336,10 @@ main(int argc, char *argv[])
// cursed but makes the handling nicer above
contents[d->length] = '\n';
contents[d->length + 1] = '\0';
+ offset = contents;
+
+ snprintf(slabel, sizeof(slabel), "%s %s", argv0, d->name);
+
free(d);
close(fd);
@@ 207,4 347,75 @@ main(int argc, char *argv[])
if(checkonly)
exits(nil);
+
+ slides = malloc(nslides*sizeof(Slide*));
+ for(i = 0; i < nslides; i++){
+ slides[i] = nextslide(&offset, &linum);
+ if(*slides[i]->cmd == '\0')
+ i--;
+ }
+
+ if(initdraw(nil, nil, slabel) < 0)
+ sysfatal("initdraw: %r");
+
+ bg = allocimage(display, Rect(0,0, 1,1), RGB16, 1, DBlack);
+ if(bg == nil)
+ sysfatal("couldn't allocimage!");
+
+ fg = allocimage(display, Rect(0,0, 1,1), RGB16, 1, DWhite);
+ if(fg == nil)
+ sysfatal("couldn't allocimage!");
+ if(lightmode){
+ tmp = fg;
+ fg = bg;
+ bg = tmp;
+ }
+
+ if(strncmp(tfname, "/n/ttf", 6) == 0 || strncmp(tfname, "/n/ttf", 6) == 0){
+ if(fork() == 0)
+ execl("/bin/truetypefs", "truetypefs", nil);
+ else
+ sleep(200);
+ }
+
+ tfont = openfont(display, tfname);
+ if(tfont == nil)
+ sysfatal("couldn't open font '%s'", tfname);
+ hfont = openfont(display, hfname);
+ if(hfont == nil)
+ sysfatal("couldn't open font '%s'", hfname);
+
+
+ einit(Emouse);
+
+ for(;;){
+ render();
+ etype = event(&e);
+
+ if(etype == Emouse){
+ m = e.mouse;
+ if(m.buttons & 1 && !(lastm.buttons & 1))
+ cslide--;
+ if(m.buttons & 4 && !(lastm.buttons & 4))
+ cslide++;
+
+ menu.lasthit = -1;
+ if(m.buttons & 2)
+ emenuhit(2, &m, &menu);
+
+ switch(menu.lasthit){
+ case MenuNext:
+ cslide++;
+ break;
+ case MenuPrev:
+ cslide--;
+ break;
+ case MenuExit:
+ exits(nil);
+ break;
+ }
+
+ lastm = m;
+ }
+ }
}