add stuff
This commit is contained in:
		
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -21,3 +21,10 @@ | ||||
| *.i*86 | ||||
| *.x86_64 | ||||
| *.hex | ||||
| /sent | ||||
|  | ||||
| # vim | ||||
| *.swp | ||||
| *~ | ||||
|  | ||||
| config.h | ||||
|  | ||||
							
								
								
									
										4
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								LICENSE
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| 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 | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| @ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| SOFTWARE. | ||||
|  | ||||
							
								
								
									
										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