add stuff
This commit is contained in:
		
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -21,3 +21,10 @@
 | 
				
			|||||||
*.i*86
 | 
					*.i*86
 | 
				
			||||||
*.x86_64
 | 
					*.x86_64
 | 
				
			||||||
*.hex
 | 
					*.hex
 | 
				
			||||||
 | 
					/sent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vim
 | 
				
			||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config.h
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
The MIT License (MIT)
 | 
					The MIT License (MIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Copyright (c) 2014 schachmat
 | 
					Copyright (c) 2014 markus.teich@stusta.mhn.de
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
of this software and associated documentation files (the "Software"), to deal
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										56
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					# sent - plain text presentation tool
 | 
				
			||||||
 | 
					# See LICENSE file for copyright and license details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include config.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SRC = sent.c
 | 
				
			||||||
 | 
					OBJ = ${SRC:.c=.o}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					all: options sent cscope
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					options:
 | 
				
			||||||
 | 
						@echo sent build options:
 | 
				
			||||||
 | 
						@echo "CFLAGS   = ${CFLAGS}"
 | 
				
			||||||
 | 
						@echo "LDFLAGS  = ${LDFLAGS}"
 | 
				
			||||||
 | 
						@echo "CC       = ${CC}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config.h:
 | 
				
			||||||
 | 
						cp config.def.h config.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.c.o:
 | 
				
			||||||
 | 
						@echo CC $<
 | 
				
			||||||
 | 
						@${CC} -c ${CFLAGS} $<
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${OBJ}: config.h config.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sent: ${OBJ}
 | 
				
			||||||
 | 
						@echo CC -o $@
 | 
				
			||||||
 | 
						@${CC} -o $@ ${OBJ} ${LDFLAGS}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cscope: ${SRC} config.h
 | 
				
			||||||
 | 
						@echo cScope
 | 
				
			||||||
 | 
						@cscope -R -b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						@echo cleaning
 | 
				
			||||||
 | 
						@rm -f sent ${OBJ} sent-${VERSION}.tar.gz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dist: clean
 | 
				
			||||||
 | 
						@echo creating dist tarball
 | 
				
			||||||
 | 
						@mkdir -p sent-${VERSION}
 | 
				
			||||||
 | 
						@cp -R LICENSE Makefile config.mk config.def.h ${SRC} sent-${VERSION}
 | 
				
			||||||
 | 
						@tar -cf sent-${VERSION}.tar sent-${VERSION}
 | 
				
			||||||
 | 
						@gzip sent-${VERSION}.tar
 | 
				
			||||||
 | 
						@rm -rf sent-${VERSION}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install: all
 | 
				
			||||||
 | 
						@echo installing executable file to ${DESTDIR}${PREFIX}/bin
 | 
				
			||||||
 | 
						@mkdir -p ${DESTDIR}${PREFIX}/bin
 | 
				
			||||||
 | 
						@cp -f sent ${DESTDIR}${PREFIX}/bin
 | 
				
			||||||
 | 
						@chmod 755 ${DESTDIR}${PREFIX}/bin/sent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uninstall:
 | 
				
			||||||
 | 
						@echo removing executable file from ${DESTDIR}${PREFIX}/bin
 | 
				
			||||||
 | 
						@rm -f ${DESTDIR}${PREFIX}/bin/sent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: all options clean dist install uninstall cscope
 | 
				
			||||||
							
								
								
									
										63
									
								
								arg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								arg.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copy me if you can.
 | 
				
			||||||
 | 
					 * by 20h
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ARG_H__
 | 
				
			||||||
 | 
					#define ARG_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern char *argv0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* use main(int argc, char *argv[]) */
 | 
				
			||||||
 | 
					#define ARGBEGIN	for (argv0 = *argv, argv++, argc--;\
 | 
				
			||||||
 | 
										argv[0] && argv[0][1]\
 | 
				
			||||||
 | 
										&& argv[0][0] == '-';\
 | 
				
			||||||
 | 
										argc--, argv++) {\
 | 
				
			||||||
 | 
									char argc_;\
 | 
				
			||||||
 | 
									char **argv_;\
 | 
				
			||||||
 | 
									int brk_;\
 | 
				
			||||||
 | 
									if (argv[0][1] == '-' && argv[0][2] == '\0') {\
 | 
				
			||||||
 | 
										argv++;\
 | 
				
			||||||
 | 
										argc--;\
 | 
				
			||||||
 | 
										break;\
 | 
				
			||||||
 | 
									}\
 | 
				
			||||||
 | 
									for (brk_ = 0, argv[0]++, argv_ = argv;\
 | 
				
			||||||
 | 
											argv[0][0] && !brk_;\
 | 
				
			||||||
 | 
											argv[0]++) {\
 | 
				
			||||||
 | 
										if (argv_ != argv)\
 | 
				
			||||||
 | 
											break;\
 | 
				
			||||||
 | 
										argc_ = argv[0][0];\
 | 
				
			||||||
 | 
										switch (argc_)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Handles obsolete -NUM syntax */
 | 
				
			||||||
 | 
					#define ARGNUM				case '0':\
 | 
				
			||||||
 | 
										case '1':\
 | 
				
			||||||
 | 
										case '2':\
 | 
				
			||||||
 | 
										case '3':\
 | 
				
			||||||
 | 
										case '4':\
 | 
				
			||||||
 | 
										case '5':\
 | 
				
			||||||
 | 
										case '6':\
 | 
				
			||||||
 | 
										case '7':\
 | 
				
			||||||
 | 
										case '8':\
 | 
				
			||||||
 | 
										case '9'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARGEND			}\
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARGC()		argc_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARGNUMF(base)	(brk_ = 1, estrtol(argv[0], (base)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EARGF(x)	((argv[0][1] == '\0' && argv[1] == NULL)?\
 | 
				
			||||||
 | 
									((x), abort(), (char *)0) :\
 | 
				
			||||||
 | 
									(brk_ = 1, (argv[0][1] != '\0')?\
 | 
				
			||||||
 | 
										(&argv[0][1]) :\
 | 
				
			||||||
 | 
										(argc--, argv++, argv[0])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ARGF()		((argv[0][1] == '\0' && argv[1] == NULL)?\
 | 
				
			||||||
 | 
									(char *)0 :\
 | 
				
			||||||
 | 
									(brk_ = 1, (argv[0][1] != '\0')?\
 | 
				
			||||||
 | 
										(&argv[0][1]) :\
 | 
				
			||||||
 | 
										(argc--, argv++, argv[0])))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										28
									
								
								config.def.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								config.def.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/* See LICENSE file for copyright and license details. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char font[] = "-*-dejavu sans condensed-bold-r-*-*-0-0-*-*-*-0-*-*";
 | 
				
			||||||
 | 
					#define NUMFONTS 30
 | 
				
			||||||
 | 
					#define FONTSZ(x) ((int)(100.0 * powf(1.1288, (x)))) /* x in [0, NUMFONTS-1] */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* how much screen estate is to be used at max for the content */
 | 
				
			||||||
 | 
					static float usablewidth = 0.75;
 | 
				
			||||||
 | 
					static float usableheight = 0.75;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Mousekey mshortcuts[] = {
 | 
				
			||||||
 | 
						/* button         function        argument */
 | 
				
			||||||
 | 
						{ Button1,        advance,        {.i = +1} },
 | 
				
			||||||
 | 
						{ Button2,        advance,        {.i = -1} },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Shortcut shortcuts[] = {
 | 
				
			||||||
 | 
						/* keysym         function        argument */
 | 
				
			||||||
 | 
						{ XK_q,           quit,           {0} },
 | 
				
			||||||
 | 
						{ XK_Right,       advance,        {.i = +1} },
 | 
				
			||||||
 | 
						{ XK_Left,        advance,        {.i = -1} },
 | 
				
			||||||
 | 
						{ XK_Return,      advance,        {.i = +1} },
 | 
				
			||||||
 | 
						{ XK_BackSpace,   advance,        {.i = -1} },
 | 
				
			||||||
 | 
						{ XK_Down,        advance,        {.i = +5} },
 | 
				
			||||||
 | 
						{ XK_Up,          advance,        {.i = -5} },
 | 
				
			||||||
 | 
						{ XK_Next,        advance,        {.i = +10} },
 | 
				
			||||||
 | 
						{ XK_Prior,       advance,        {.i = -10} },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										25
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					# sent version
 | 
				
			||||||
 | 
					VERSION = 0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Customize below to fit your system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# paths
 | 
				
			||||||
 | 
					PREFIX = /usr/local
 | 
				
			||||||
 | 
					MANPREFIX = ${PREFIX}/share/man
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					X11INC = /usr/X11R6/include
 | 
				
			||||||
 | 
					X11LIB = /usr/X11R6/lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# includes and libs
 | 
				
			||||||
 | 
					INCS = -I. -I/usr/include -I${X11INC}
 | 
				
			||||||
 | 
					LIBS = -L/usr/lib -lc -lm -L${X11LIB} -lX11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# flags
 | 
				
			||||||
 | 
					CPPFLAGS = -DVERSION=\"${VERSION}\" -D_BSD_SOURCE -D_XOPEN_SOURCE=600
 | 
				
			||||||
 | 
					CFLAGS += -g -std=c99 -pedantic -Wall ${INCS} ${CPPFLAGS}
 | 
				
			||||||
 | 
					LDFLAGS += -g ${LIBS}
 | 
				
			||||||
 | 
					#CFLAGS += -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
 | 
				
			||||||
 | 
					#LDFLAGS += ${LIBS}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# compiler and linker
 | 
				
			||||||
 | 
					CC ?= cc
 | 
				
			||||||
							
								
								
									
										468
									
								
								sent.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										468
									
								
								sent.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,468 @@
 | 
				
			|||||||
 | 
					/* See LICENSE for licence details. */
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <stdarg.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <X11/keysym.h>
 | 
				
			||||||
 | 
					#include <X11/XKBlib.h>
 | 
				
			||||||
 | 
					#include <X11/Xatom.h>
 | 
				
			||||||
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
 | 
					#include <X11/Xutil.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "arg.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *argv0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* macros */
 | 
				
			||||||
 | 
					#define LEN(a)     (sizeof(a) / sizeof(a)[0])
 | 
				
			||||||
 | 
					#define LIMIT(x, a, b)    (x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						char* text;
 | 
				
			||||||
 | 
					} Slide;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Purely graphic info */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						Display *dpy;
 | 
				
			||||||
 | 
						Window win;
 | 
				
			||||||
 | 
						Atom wmdeletewin, netwmname;
 | 
				
			||||||
 | 
						Visual *vis;
 | 
				
			||||||
 | 
						XSetWindowAttributes attrs;
 | 
				
			||||||
 | 
						int scr;
 | 
				
			||||||
 | 
						int w, h;
 | 
				
			||||||
 | 
					} XWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Drawing Context linked list*/
 | 
				
			||||||
 | 
					struct DC{
 | 
				
			||||||
 | 
						XFontStruct *font;
 | 
				
			||||||
 | 
						GC gc;
 | 
				
			||||||
 | 
						struct DC *next;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef union {
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						unsigned int ui;
 | 
				
			||||||
 | 
						float f;
 | 
				
			||||||
 | 
						const void *v;
 | 
				
			||||||
 | 
					} Arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						unsigned int b;
 | 
				
			||||||
 | 
						void (*func)(const Arg *);
 | 
				
			||||||
 | 
						const Arg arg;
 | 
				
			||||||
 | 
					} Mousekey;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						KeySym keysym;
 | 
				
			||||||
 | 
						void (*func)(const Arg *);
 | 
				
			||||||
 | 
						const Arg arg;
 | 
				
			||||||
 | 
					} Shortcut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* function definitions used in config.h */
 | 
				
			||||||
 | 
					static void advance(const Arg *);
 | 
				
			||||||
 | 
					static void quit(const Arg *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* config.h for applying patches and the configuration. */
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Bool xfontisscalable(char *name);
 | 
				
			||||||
 | 
					static XFontStruct *xloadqueryscalablefont(char *name, int size);
 | 
				
			||||||
 | 
					static struct DC *getfontsize(char *str, size_t len, int *width, int *height);
 | 
				
			||||||
 | 
					static void cleanup(struct DC *cur);
 | 
				
			||||||
 | 
					static void eprintf(const char *, ...);
 | 
				
			||||||
 | 
					static void load(FILE *fp);
 | 
				
			||||||
 | 
					static void advance(const Arg *arg);
 | 
				
			||||||
 | 
					static void quit(const Arg *arg);
 | 
				
			||||||
 | 
					static void run();
 | 
				
			||||||
 | 
					static void usage();
 | 
				
			||||||
 | 
					static void xdraw();
 | 
				
			||||||
 | 
					static void xhints();
 | 
				
			||||||
 | 
					static void xinit();
 | 
				
			||||||
 | 
					static void xloadfonts(char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bpress(XEvent *);
 | 
				
			||||||
 | 
					static void cmessage(XEvent *);
 | 
				
			||||||
 | 
					static void expose(XEvent *);
 | 
				
			||||||
 | 
					static void kpress(XEvent *);
 | 
				
			||||||
 | 
					static void resize(XEvent *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Globals */
 | 
				
			||||||
 | 
					static Slide *slides = NULL;
 | 
				
			||||||
 | 
					static int idx = 0;
 | 
				
			||||||
 | 
					static int slidecount = 0;
 | 
				
			||||||
 | 
					static XWindow xw;
 | 
				
			||||||
 | 
					static struct DC dc;
 | 
				
			||||||
 | 
					static int running = 1;
 | 
				
			||||||
 | 
					static char *opt_font = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void (*handler[LASTEvent])(XEvent *) = {
 | 
				
			||||||
 | 
						[ButtonPress] = bpress,
 | 
				
			||||||
 | 
						[ClientMessage] = cmessage,
 | 
				
			||||||
 | 
						[ConfigureNotify] = resize,
 | 
				
			||||||
 | 
						[Expose] = expose,
 | 
				
			||||||
 | 
						[KeyPress] = kpress,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bool xfontisscalable(char *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, field;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!name || name[0] != '-')
 | 
				
			||||||
 | 
							return False;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = field = 0; name[i] != '\0'; i++) {
 | 
				
			||||||
 | 
							if (name[i] == '-') {
 | 
				
			||||||
 | 
								field++;
 | 
				
			||||||
 | 
								if ((field == 7) || (field == 8) || (field == 12))
 | 
				
			||||||
 | 
									if ((name[i+1] != '0') || (name[i+2] != '-'))
 | 
				
			||||||
 | 
										return False;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return field == 14;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					XFontStruct *xloadqueryscalablefont(char *name, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, j, field;
 | 
				
			||||||
 | 
						char newname[500];
 | 
				
			||||||
 | 
						int resx, resy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!name || name[0] != '-')
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						/* calculate our screen resolution in dots per inch. 25.4mm = 1 inch */
 | 
				
			||||||
 | 
						resx = DisplayWidth(xw.dpy, xw.scr)/(DisplayWidthMM(xw.dpy, xw.scr)/25.4);
 | 
				
			||||||
 | 
						resy = DisplayHeight(xw.dpy, xw.scr)/(DisplayHeightMM(xw.dpy, xw.scr)/25.4);
 | 
				
			||||||
 | 
						/* copy the font name, changing the scalable fields as we do so */
 | 
				
			||||||
 | 
						for (i = j = field = 0; name[i] != '\0' && field <= 14; i++) {
 | 
				
			||||||
 | 
							newname[j++] = name[i];
 | 
				
			||||||
 | 
							if (name[i] == '-') {
 | 
				
			||||||
 | 
								field++;
 | 
				
			||||||
 | 
								switch (field) {
 | 
				
			||||||
 | 
									case 7:  /* pixel size */
 | 
				
			||||||
 | 
									case 12: /* average width */
 | 
				
			||||||
 | 
										/* change from "-0-" to "-*-" */
 | 
				
			||||||
 | 
										newname[j] = '*';
 | 
				
			||||||
 | 
										j++;
 | 
				
			||||||
 | 
										if (name[i+1] != '\0') i++;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case 8:  /* point size */
 | 
				
			||||||
 | 
										/* change from "-0-" to "-<size>-" */
 | 
				
			||||||
 | 
										sprintf(&newname[j], "%d", size);
 | 
				
			||||||
 | 
										while (newname[j] != '\0') j++;
 | 
				
			||||||
 | 
										if (name[i+1] != '\0') i++;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case 9:  /* x-resolution */
 | 
				
			||||||
 | 
									case 10: /* y-resolution */
 | 
				
			||||||
 | 
										/* change from an unspecified resolution to resx or resy */
 | 
				
			||||||
 | 
										sprintf(&newname[j], "%d", (field == 9) ? resx : resy);
 | 
				
			||||||
 | 
										while (newname[j] != '\0') j++;
 | 
				
			||||||
 | 
										while ((name[i+1] != '-') && (name[i+1] != '\0')) i++;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newname[j] = '\0';
 | 
				
			||||||
 | 
						return (field != 14) ? NULL : XLoadQueryFont(xw.dpy, newname);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct DC *getfontsize(char *str, size_t len, int *width, int *height)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						XCharStruct info;
 | 
				
			||||||
 | 
						int unused;
 | 
				
			||||||
 | 
						struct DC *pre = &dc;
 | 
				
			||||||
 | 
						struct DC *cur = &dc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							XTextExtents(cur->font, str, len, &unused, &unused, &unused, &info);
 | 
				
			||||||
 | 
							if (info.width > usablewidth * xw.w
 | 
				
			||||||
 | 
									|| info.ascent + info.descent > usableheight * xw.h)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							pre = cur;
 | 
				
			||||||
 | 
						} while ((cur = cur->next));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XTextExtents(pre->font, "o", 1, &unused, &unused, &unused, &info);
 | 
				
			||||||
 | 
						*height = info.ascent;
 | 
				
			||||||
 | 
						*width = XTextWidth(pre->font, str, len);
 | 
				
			||||||
 | 
						return pre;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cleanup(struct DC *cur)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						XFreeFont(xw.dpy, cur->font);
 | 
				
			||||||
 | 
						XFreeGC(xw.dpy, cur->gc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cur->next) {
 | 
				
			||||||
 | 
							cleanup(cur->next);
 | 
				
			||||||
 | 
							cur->next = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cur != &dc) {
 | 
				
			||||||
 | 
							free(cur);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XDestroyWindow(xw.dpy, xw.win);
 | 
				
			||||||
 | 
						XSync(xw.dpy, False);
 | 
				
			||||||
 | 
						XCloseDisplay(xw.dpy);
 | 
				
			||||||
 | 
						if (slides) {
 | 
				
			||||||
 | 
							free(slides);
 | 
				
			||||||
 | 
							slides = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void eprintf(const char *fmt, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						va_list ap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(ap, fmt);
 | 
				
			||||||
 | 
						vfprintf(stderr, fmt, ap);
 | 
				
			||||||
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
 | 
				
			||||||
 | 
							fputc(' ', stderr);
 | 
				
			||||||
 | 
							perror(NULL);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fputc('\n', stderr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						exit(EXIT_FAILURE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void load(FILE *fp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static size_t size = 0;
 | 
				
			||||||
 | 
						char buf[BUFSIZ], *p;
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* read each line from stdin and add it to the item list */
 | 
				
			||||||
 | 
						for (i = slidecount; fgets(buf, sizeof(buf), fp); i++) {
 | 
				
			||||||
 | 
							if ((i+1) * sizeof(*slides) >= size)
 | 
				
			||||||
 | 
								if (!(slides = realloc(slides, (size += BUFSIZ))))
 | 
				
			||||||
 | 
									eprintf("cannot realloc %u bytes:", size);
 | 
				
			||||||
 | 
							if ((p = strchr(buf, '\n')))
 | 
				
			||||||
 | 
								*p = '\0';
 | 
				
			||||||
 | 
							if (!(slides[i].text = strdup(buf)))
 | 
				
			||||||
 | 
								eprintf("cannot strdup %u bytes:", strlen(buf)+1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (slides)
 | 
				
			||||||
 | 
							slides[i].text = NULL;
 | 
				
			||||||
 | 
						slidecount = i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void advance(const Arg *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int new_idx = idx + arg->i;
 | 
				
			||||||
 | 
						LIMIT(new_idx, 0, slidecount-1);
 | 
				
			||||||
 | 
						if (new_idx != idx) {
 | 
				
			||||||
 | 
							idx = new_idx;
 | 
				
			||||||
 | 
							xdraw();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void quit(const Arg *arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						running = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void run()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						XEvent ev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Waiting for window mapping */
 | 
				
			||||||
 | 
						while (1) {
 | 
				
			||||||
 | 
							XNextEvent(xw.dpy, &ev);
 | 
				
			||||||
 | 
							if (ev.type == ConfigureNotify) {
 | 
				
			||||||
 | 
								xw.w = ev.xconfigure.width;
 | 
				
			||||||
 | 
								xw.h = ev.xconfigure.height;
 | 
				
			||||||
 | 
							} else if (ev.type == MapNotify) {
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (running) {
 | 
				
			||||||
 | 
							XNextEvent(xw.dpy, &ev);
 | 
				
			||||||
 | 
							if (handler[ev.type])
 | 
				
			||||||
 | 
								(handler[ev.type])(&ev);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usage()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						eprintf("sent " VERSION " (c) 2014 markus.teich@stusta.mhn.de\n" \
 | 
				
			||||||
 | 
						"usage: sent [-f font] FILE1 [FILE2 ...]", argv0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xdraw()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int line_len = strlen(slides[idx].text);
 | 
				
			||||||
 | 
						int height;
 | 
				
			||||||
 | 
						int width;
 | 
				
			||||||
 | 
						struct DC *dc = getfontsize(slides[idx].text, line_len, &width, &height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XClearWindow(xw.dpy, xw.win);
 | 
				
			||||||
 | 
						XDrawString(xw.dpy, xw.win, dc->gc, (xw.w - width)/2, (xw.h + height)/2,
 | 
				
			||||||
 | 
								slides[idx].text, line_len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xhints()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						XClassHint class = {.res_name = "sent", .res_class = "presenter"};
 | 
				
			||||||
 | 
						XWMHints wm = {.flags = InputHint, .input = True};
 | 
				
			||||||
 | 
						XSizeHints *sizeh = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(sizeh = XAllocSizeHints()))
 | 
				
			||||||
 | 
							eprintf("sent: Could not alloc size hints");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sizeh->flags = PSize;
 | 
				
			||||||
 | 
						sizeh->height = xw.h;
 | 
				
			||||||
 | 
						sizeh->width = xw.w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm, &class);
 | 
				
			||||||
 | 
						XFree(sizeh);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xinit()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						XTextProperty prop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(xw.dpy = XOpenDisplay(NULL)))
 | 
				
			||||||
 | 
							eprintf("Can't open display.");
 | 
				
			||||||
 | 
						xw.scr = XDefaultScreen(xw.dpy);
 | 
				
			||||||
 | 
						xw.vis = XDefaultVisual(xw.dpy, xw.scr);
 | 
				
			||||||
 | 
						xw.w = DisplayWidth(xw.dpy, xw.scr);
 | 
				
			||||||
 | 
						xw.h = 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
 | 
				
			||||||
 | 
						xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
 | 
				
			||||||
 | 
						XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xloadfonts(opt_font ? opt_font : font);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XStringListToTextProperty(&argv0, 1, &prop);
 | 
				
			||||||
 | 
						XSetWMName(xw.dpy, xw.win, &prop);
 | 
				
			||||||
 | 
						XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
 | 
				
			||||||
 | 
						XFree(prop.value);
 | 
				
			||||||
 | 
						XMapWindow(xw.dpy, xw.win);
 | 
				
			||||||
 | 
						xhints();
 | 
				
			||||||
 | 
						XSync(xw.dpy, False);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void xloadfonts(char *fontstr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int count = 0;
 | 
				
			||||||
 | 
						int i = 0;
 | 
				
			||||||
 | 
						XFontStruct *fnt;
 | 
				
			||||||
 | 
						XGCValues gcvalues;
 | 
				
			||||||
 | 
						struct DC *cur = &dc;
 | 
				
			||||||
 | 
						char **fstr = XListFonts(xw.dpy, fontstr, 42, &count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (count-- && !xfontisscalable(fstr[count]))
 | 
				
			||||||
 | 
							; /* nothing, just get first scalable font result */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (count < 0)
 | 
				
			||||||
 | 
							eprintf("sent: could not find a scalable font matching %s", fontstr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&gcvalues, 0, sizeof(gcvalues));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							if (!(fnt = xloadqueryscalablefont(fstr[count], FONTSZ(i)))) {
 | 
				
			||||||
 | 
								i++;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cur->gc = XCreateGC(xw.dpy, XRootWindow(xw.dpy, xw.scr), 0, &gcvalues);
 | 
				
			||||||
 | 
							cur->font = fnt;
 | 
				
			||||||
 | 
							XSetFont(xw.dpy, cur->gc, fnt->fid);
 | 
				
			||||||
 | 
							XSetForeground(xw.dpy, cur->gc, BlackPixel(xw.dpy, xw.scr));
 | 
				
			||||||
 | 
							cur->next = (++i < NUMFONTS) ? malloc(sizeof(struct DC)) : NULL;
 | 
				
			||||||
 | 
							cur = cur->next;
 | 
				
			||||||
 | 
						} while (cur && i < NUMFONTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cur == &dc)
 | 
				
			||||||
 | 
							eprintf("sent: could not load fonts.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XFreeFontNames(fstr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void bpress(XEvent *e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < LEN(mshortcuts); i++)
 | 
				
			||||||
 | 
							if (e->xbutton.button == mshortcuts[i].b && mshortcuts[i].func)
 | 
				
			||||||
 | 
								mshortcuts[i].func(&(mshortcuts[i].arg));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cmessage(XEvent *e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (e->xclient.data.l[0] == xw.wmdeletewin)
 | 
				
			||||||
 | 
							running = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void expose(XEvent *e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (0 == e->xexpose.count)
 | 
				
			||||||
 | 
							xdraw();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kpress(XEvent *e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						KeySym sym;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sym = XkbKeycodeToKeysym(xw.dpy, (KeyCode)e->xkey.keycode, 0, 0);
 | 
				
			||||||
 | 
						for (i = 0; i < LEN(shortcuts); i++)
 | 
				
			||||||
 | 
							if (sym == shortcuts[i].keysym && shortcuts[i].func)
 | 
				
			||||||
 | 
								shortcuts[i].func(&(shortcuts[i].arg));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void resize(XEvent *e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						xw.w = e->xconfigure.width;
 | 
				
			||||||
 | 
						xw.h = e->xconfigure.height;
 | 
				
			||||||
 | 
						xdraw();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						FILE *fp = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ARGBEGIN {
 | 
				
			||||||
 | 
						case 'f':
 | 
				
			||||||
 | 
							opt_font = EARGF(usage());
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 'v':
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							usage();
 | 
				
			||||||
 | 
						} ARGEND;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < argc; i++) {
 | 
				
			||||||
 | 
							if ((fp = strcmp(argv[i], "-") ? fopen(argv[i], "r") : stdin)) {
 | 
				
			||||||
 | 
								load(fp);
 | 
				
			||||||
 | 
								fclose(fp);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								eprintf("could not open file %s for reading:", argv[i]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!slides || !slides[0].text)
 | 
				
			||||||
 | 
							usage();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xinit();
 | 
				
			||||||
 | 
						run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cleanup(&dc);
 | 
				
			||||||
 | 
						return EXIT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user