catpoint

Catpoint simple presenting software.
git clone git://r-36.net/catpoint
Log | Files | Refs | LICENSE

catpoint.c (3893B)


      1 /* See LICENSE file for license details. */
      2 
      3 #include <sys/mman.h>
      4 #include <sys/stat.h>
      5 #include <sys/types.h>
      6 
      7 #include <curses.h>
      8 #include <errno.h>
      9 #include <fcntl.h>
     10 #include <locale.h>
     11 #include <signal.h>
     12 #include <stdarg.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <unistd.h>
     17 
     18 void die(const char *, ...);
     19 
     20 char *currentslidep, **slidefiles; /* the slides */
     21 int nslides, currentslide, currentslidelen;
     22 
     23 volatile sig_atomic_t slidechanged = 1;
     24 
     25 void
     26 unloadcurrentslide(void)
     27 {
     28 	if (currentslidep == NULL)
     29 		return;
     30 
     31 	if (munmap(currentslidep, currentslidelen) < 0)
     32 		die("munmap: %s", slidefiles[currentslide]);
     33 }
     34 
     35 void
     36 cleanup(void)
     37 {
     38 	unloadcurrentslide();
     39 
     40 	endwin(); /* restore terminal */
     41 }
     42 
     43 /* print to stderr, call cleanup() and _exit(). */
     44 void
     45 die(const char *fmt, ...)
     46 {
     47 	va_list ap;
     48 	int saved_errno;
     49 
     50 	saved_errno = errno;
     51 	cleanup();
     52 
     53 	va_start(ap, fmt);
     54 	vfprintf(stderr, fmt, ap);
     55 	va_end(ap);
     56 
     57 	if (saved_errno)
     58 		fprintf(stderr, ": %s", strerror(saved_errno));
     59 	fflush(stderr);
     60 	write(2, "\n", 1);
     61 
     62 	_exit(1);
     63 }
     64 
     65 void
     66 quit(int sig)
     67 {
     68 	cleanup();
     69 	_exit(128 + sig);
     70 }
     71 
     72 void
     73 loadcurrentslide(char **argv, int slide)
     74 {
     75 	struct stat statbuf;
     76 	int fd;
     77 
     78 	unloadcurrentslide();
     79 
     80 	fd = open(slidefiles[slide], O_RDONLY, 0);
     81 	if (fd < 0)
     82 		die("open: %s", slidefiles[slide]);
     83 	if (fstat(fd, &statbuf) < 0)
     84 		die("fstat: %s", slidefiles[slide]);
     85 	currentslidep = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
     86 	if (currentslidep == MAP_FAILED) {
     87 		currentslidep = NULL;
     88 		die("mmap: %s", slidefiles[slide]);
     89 	}
     90 	currentslidelen = statbuf.st_size;
     91 	close(fd);
     92 }
     93 
     94 void
     95 reloadcurrentslide(int sig)
     96 {
     97 	/*
     98 	 * Keep this out of SIGHUP, in case this is used somewhere else.
     99 	 */
    100 	slidechanged = 1;
    101 
    102 	if (sig == SIGHUP) {
    103 		/* Make ncurses redisplay slide. */
    104 		if (raise(SIGWINCH) < 0)
    105 			die("raise");
    106 	}
    107 }
    108 
    109 void
    110 setsignal()
    111 {
    112 	struct sigaction sa;
    113 
    114 	memset(&sa, 0, sizeof(sa));
    115 	sigemptyset(&sa.sa_mask);
    116 	sa.sa_flags = 0;
    117 
    118 	sa.sa_handler = quit;
    119 	sigaction(SIGINT, &sa, NULL);
    120 	sigaction(SIGQUIT, &sa, NULL);
    121 	sigaction(SIGTERM, &sa, NULL);
    122 
    123 	sa.sa_handler = reloadcurrentslide;
    124 	sigaction(SIGHUP, &sa, NULL);
    125 }
    126 
    127 int
    128 main(int argc, char *argv[])
    129 {
    130 	int c;
    131 
    132 	if (argc == 1) {
    133 		errno = 0;
    134 		die("usage: %s file ...", argv[0]);
    135 	}
    136 	slidefiles = ++argv;
    137 	nslides = --argc;
    138 
    139 	setsignal();
    140 	setlocale(LC_ALL, "");
    141 
    142 	/* start */
    143 	currentslide = 0;
    144 	currentslidep = NULL;
    145 	currentslidelen = 0;
    146 
    147 	/* init curses */
    148 	initscr();
    149 	cbreak();
    150 	noecho();
    151 	nonl();
    152 	intrflush(stdscr, FALSE);
    153 	keypad(stdscr, TRUE);
    154 	curs_set(FALSE); /* hide cursor */
    155 
    156 show:
    157 	/* display slide if changed */
    158 	if (slidechanged) {
    159 		slidechanged = 0;
    160 		loadcurrentslide(slidefiles, currentslide);
    161 	}
    162 	clear();
    163 	refresh();
    164 	printw("%.*s", currentslidelen, currentslidep);
    165 
    166 again:
    167 	c = getch();
    168 	switch (c) {
    169 	/* powerpoint remote presenter shortcuts */
    170 	case 4: /* ^D, EOT */
    171 	case 27:
    172 	case KEY_F(5):
    173 	/* end presentation */
    174 	case 'q':
    175 		break;
    176 	/* next */
    177 	case ' ':
    178 	case 'l':
    179 	case 'j':
    180 	case KEY_RIGHT:
    181 	case KEY_DOWN:
    182 	case KEY_NPAGE:
    183 		if (currentslide < nslides - 1) {
    184 			slidechanged = 1;
    185 			currentslide++;
    186 			goto show;
    187 		}
    188 		goto again;
    189 	/* prev */
    190 	case 'h':
    191 	case 'k':
    192 	case KEY_LEFT:
    193 	case KEY_UP:
    194 	case KEY_PPAGE:
    195 		if (currentslide > 0) {
    196 			slidechanged = 1;
    197 			currentslide--;
    198 			goto show;
    199 		}
    200 		goto again;
    201 	/* shortcut from powerpoint. Needed for remote presenters. */
    202 	case '.':
    203 	/* first */
    204 	case 'u':
    205 	case KEY_BEG:
    206 	case KEY_HOME:
    207 		if (currentslide != 0)
    208 			slidechanged = 1;
    209 		currentslide = 0;
    210 		goto show;
    211 	/* last */
    212 	case 'i':
    213 	case KEY_END:
    214 		if (currentslide != (nslides - 1))
    215 			slidechanged = 1;
    216 		currentslide = nslides - 1;
    217 		goto show;
    218 	/* reload */
    219 	case 'r':
    220 	case 12: /* ^L, redraw */
    221 	case KEY_RESIZE: /* resize / SIGWINCH */
    222 		goto show;
    223 	default:
    224 		/* printf("key pressed = '%d'\n", c); */
    225 		goto again;
    226 	}
    227 
    228 	cleanup();
    229 
    230 	return 0;
    231 }