summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-08-28 17:21:32 -0400
committerJune McEnroe <june@causal.agency>2019-08-28 17:21:32 -0400
commitac0a0e19b9005bcbad696f836830ffa99a14cab9 (patch)
tree44384a3341ea78967ec4f303938ee5c4bd26e76c
parentUse rand(3) in beef (diff)
downloadsrc-ac0a0e19b9005bcbad696f836830ffa99a14cab9.tar.gz
src-ac0a0e19b9005bcbad696f836830ffa99a14cab9.zip
Remove brot and gfxx
-rw-r--r--bin/.gitignore2
-rw-r--r--bin/Makefile26
-rw-r--r--bin/README2
-rw-r--r--bin/bin.76
-rw-r--r--bin/brot.c151
-rw-r--r--bin/gfx-cocoa.m162
-rw-r--r--bin/gfx-fb.c87
-rw-r--r--bin/gfx-x11.c135
-rw-r--r--bin/gfx.h24
-rw-r--r--bin/gfxx.c470
-rw-r--r--bin/man1/brot.163
-rw-r--r--bin/man1/gfxx.1138
12 files changed, 3 insertions, 1263 deletions
diff --git a/bin/.gitignore b/bin/.gitignore
index 5013166a..d30ffdac 100644
--- a/bin/.gitignore
+++ b/bin/.gitignore
@@ -4,12 +4,10 @@ aes
 beef
 bit
 bri
-brot
 config.mk
 dtch
 fbatt
 fbclock
-gfxx
 glitch
 hi
 hnel
diff --git a/bin/Makefile b/bin/Makefile
index bf096907..de4fda51 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,21 +1,14 @@
-GFX = cocoa
-LIBRESSL_PREFIX = /usr/local
-
 PREFIX = ~/.local
 MANDIR = ${PREFIX}/share/man
 
 CFLAGS += -Wall -Wextra -Wpedantic
 LDLIBS = -lm -lutil -lz
 
+LIBRESSL_PREFIX = /usr/local
 CFLAGS_tls = ${CFLAGS} -I${LIBRESSL_PREFIX}/include
 LDFLAGS_tls = ${LDFLAGS} -L${LIBRESSL_PREFIX}/lib
 LDLIBS_tls = ${LDLIBS} -ltls
 
-GFX_OBJ = gfx-${GFX}.o
-LDLIBS_cocoa = ${LDLIBS} -framework Cocoa
-LDLIBS_fb = ${LDLIBS}
-LDLIBS_x11 = ${LDLIBS} -lX11
-
 -include config.mk
 
 BINS_ANY += aes
@@ -45,9 +38,6 @@ LINKS_ANY += pbpaste
 
 BINS_BSD += wat
 
-BINS_GFX += brot
-BINS_GFX += gfxx
-
 BINS_LINUX += bri
 BINS_LINUX += fbatt
 BINS_LINUX += fbclock
@@ -55,7 +45,7 @@ BINS_LINUX += psfed
 
 BINS_TLS += relay
 
-BINS = ${BINS_ANY} ${BINS_BSD} ${BINS_GFX} ${BINS_LINUX} ${BINS_TLS}
+BINS = ${BINS_ANY} ${BINS_BSD} ${BINS_LINUX} ${BINS_TLS}
 MANS = ${BINS:%=man1/%.1}
 LINKS = ${LINKS_ANY}
 
@@ -65,8 +55,6 @@ any: meta ${BINS_ANY} ${LINKS_ANY}
 
 bsd: meta ${BINS_BSD}
 
-gfx: meta ${BINS_GFX}
-
 linux: meta ${BINS_LINUX}
 
 tls: meta ${BINS_TLS}
@@ -75,12 +63,6 @@ meta: tags .gitignore
 
 # Binaries
 
-brot: brot.o ${GFX_OBJ}
-	${CC} ${LDFLAGS} $@.o ${GFX_OBJ} ${LDLIBS_${GFX}} -o $@
-
-gfxx: gfxx.o ${GFX_OBJ}
-	${CC} ${LDFLAGS} $@.o ${GFX_OBJ} ${LDLIBS_${GFX}} -o $@
-
 hi: hi.c
 	${CC} ${CFLAGS} ${LDFLAGS} hi.c ${LDLIBS} -o $@
 	./hi -c
@@ -93,11 +75,9 @@ relay: relay.c
 
 # Headers
 
-brot.o gfxx.o gfx-cocoa.o gfx-fb.o gfx-x11.o: gfx.h
-
 fbatt.o fbclock.o: scheme.h
 
-gfxx.o psf2png.o scheme.o: png.h
+psf2png.o scheme.o: png.h
 
 scheme.h: scheme
 	./scheme -c > scheme.h
diff --git a/bin/README b/bin/README
index 104fc9b5..5b398bff 100644
--- a/bin/README
+++ b/bin/README
@@ -11,11 +11,9 @@ DESCRIPTION
      beef(1)     Befunge-93 interpreter
      bit(1)      calculator
      bri(1)      backlight brightness control
-     brot(1)     Mandelbrot renderer
      dtch(1)     detached sessions
      fbatt(1)    framebuffer battery indicator
      fbclock(1)  framebuffer clock
-     gfxx(1)     graphics data explorer
      glitch(1)   PNG glitcher
      hi(1)       syntax highlighter
      hnel(1)     PTY input remapper
diff --git a/bin/bin.7 b/bin/bin.7
index 95db49b3..c1f53ab8 100644
--- a/bin/bin.7
+++ b/bin/bin.7
@@ -28,9 +28,6 @@ calculator
 .It Xr bri 1
 backlight brightness control
 .
-.It Xr brot 1
-Mandelbrot renderer
-.
 .It Xr dtch 1
 detached sessions
 .
@@ -40,9 +37,6 @@ framebuffer battery indicator
 .It Xr fbclock 1
 framebuffer clock
 .
-.It Xr gfxx 1
-graphics data explorer
-.
 .It Xr glitch 1
 PNG glitcher
 .
diff --git a/bin/brot.c b/bin/brot.c
deleted file mode 100644
index 69f11e59..00000000
--- a/bin/brot.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <complex.h>
-#include <err.h>
-#include <math.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sysexits.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "gfx.h"
-
-static uint32_t rgb(uint8_t r, uint8_t g, uint8_t b) {
-	return (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b;
-}
-static uint32_t gray(uint8_t n) {
-	return rgb(n, n, n);
-}
-
-static double absSq(double complex z) {
-	return creal(z) * creal(z) + cimag(z) * cimag(z);
-}
-
-static uint32_t depth = 50;
-
-static uint32_t mandelbrot(double complex c) {
-	double complex z = 0;
-	for (uint32_t i = 0; i < depth; ++i) {
-		if (absSq(z) > 4.0) return i;
-		z = z * z + c;
-	}
-	return 0;
-}
-
-static double complex translate = -0.75;
-static double complex transform = 2.5;
-
-static uint32_t samples = 1;
-
-static void sample(uint32_t *buf, size_t width, size_t height) {
-	double yRatio = (height > width) ? (double)height / (double)width : 1.0;
-	double xRatio = (width > height) ? (double)width / (double)height : 1.0;
-
-	memset(buf, 0, 4 * width * height);
-	size_t superWidth = width * samples;
-	size_t superHeight = height * samples;
-	for (size_t y = 0; y < superHeight; ++y) {
-		for (size_t x = 0; x < superWidth; ++x) {
-			double zx = (((double)x + 0.5) / (double)superWidth - 0.5) * xRatio;
-			double zy = (((double)y + 0.5) / (double)superHeight - 0.5) * yRatio;
-			uint32_t n = mandelbrot((zx + zy * I) * transform + translate);
-			buf[(y / samples) * width + (x / samples)] += n;
-		}
-	}
-}
-
-static void color(uint32_t *buf, size_t width, size_t height) {
-	for (size_t i = 0; i < width * height; ++i) {
-		buf[i] = gray(255 * buf[i] / samples / samples / depth);
-	}
-}
-
-static double frameTime;
-void draw(uint32_t *buf, size_t width, size_t height) {
-	clock_t t0 = clock();
-	sample(buf, width, height);
-	color(buf, width, height);
-	frameTime = (double)(clock() - t0) / (double)CLOCKS_PER_SEC;
-}
-
-static double translateStep = 1.0 / 128.0;
-static double rotateStep = 1.0 / 128.0;
-static double scaleStep = 1.0 / 32.0;
-
-bool input(char in) {
-	const double PI = acos(-1.0);
-	switch (in) {
-		break; case 'q': return false;
-		break; case '.': depth++;
-		break; case ',': if (depth > 1) depth--;
-		break; case 'l': translate += translateStep * transform;
-		break; case 'h': translate -= translateStep * transform;
-		break; case 'j': translate += translateStep * I * transform;
-		break; case 'k': translate -= translateStep * I * transform;
-		break; case 'u': transform *= cexp(rotateStep * PI * I);
-		break; case 'i': transform /= cexp(rotateStep * PI * I);
-		break; case '+': transform *= 1.0 - scaleStep;
-		break; case '-': transform /= 1.0 - scaleStep;
-		break; case '0': translate = -0.75; transform = 2.5;
-		break; case ']': samples++;
-		break; case '[': if (samples > 1) samples--;
-	}
-	return true;
-}
-
-const char *status(void) {
-	static char buf[256];
-	snprintf(
-		buf, sizeof(buf),
-		"brot -s %u -i %u -t %g%+gi -f %g%+gi # %.6f",
-		samples, depth,
-		creal(translate), cimag(translate),
-		creal(transform), cimag(transform),
-		frameTime
-	);
-	return buf;
-}
-
-static double complex parseComplex(const char *str) {
-	double real = 0.0, imag = 0.0;
-	real = strtod(str, (char **)&str);
-	if (str[0] == 'i') {
-		imag = real;
-		real = 0.0;
-	} else if (str[0]) {
-		imag = strtod(str, NULL);
-	}
-	return real + imag * I;
-}
-
-int init(int argc, char *argv[]) {
-	int opt;
-	while (0 < (opt = getopt(argc, argv, "f:i:s:t:"))) {
-		switch (opt) {
-			break; case 'f': transform = parseComplex(optarg);
-			break; case 'i': depth = strtoul(optarg, NULL, 0);
-			break; case 's': samples = strtoul(optarg, NULL, 0);
-			break; case 't': translate = parseComplex(optarg);
-			break; default: return EX_USAGE;
-		}
-	}
-	return EX_OK;
-}
diff --git a/bin/gfx-cocoa.m b/bin/gfx-cocoa.m
deleted file mode 100644
index 8fbbad37..00000000
--- a/bin/gfx-cocoa.m
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#import <Cocoa/Cocoa.h>
-#import <err.h>
-#import <stdbool.h>
-#import <stdint.h>
-#import <stdlib.h>
-#import <sysexits.h>
-
-#import "gfx.h"
-
-@interface BufferView : NSView {
-	size_t bufSize;
-	uint32_t *buf;
-	CGColorSpaceRef colorSpace;
-	CGDataProviderRef dataProvider;
-}
-@end
-
-@implementation BufferView
-- (instancetype) initWithFrame: (NSRect) frameRect {
-	colorSpace = CGColorSpaceCreateDeviceRGB();
-	return [super initWithFrame: frameRect];
-}
-
-- (void) setWindowTitle {
-	[[self window] setTitle: [NSString stringWithUTF8String: status()]];
-}
-
-- (void) draw {
-	draw(buf, [self frame].size.width, [self frame].size.height);
-	[self setNeedsDisplay: YES];
-}
-
-- (void) setFrameSize: (NSSize) newSize {
-	[super setFrameSize: newSize];
-	size_t newBufSize = 4 * newSize.width * newSize.height;
-	if (newBufSize > bufSize) {
-		bufSize = newBufSize;
-		buf = malloc(bufSize);
-		if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize);
-		CGDataProviderRelease(dataProvider);
-		dataProvider = CGDataProviderCreateWithData(NULL, buf, bufSize, NULL);
-	}
-	[self draw];
-}
-
-- (void) drawRect: (NSRect) dirtyRect {
-	(void)dirtyRect;
-	NSSize size = [self frame].size;
-	CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext];
-	CGImageRef image = CGImageCreate(
-		size.width, size.height,
-		8, 32, 4 * size.width,
-		colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
-		dataProvider,
-		NULL, false, kCGRenderingIntentDefault
-	);
-	CGContextDrawImage(ctx, [self frame], image);
-	CGImageRelease(image);
-}
-
-- (BOOL) acceptsFirstResponder {
-	return YES;
-}
-
-- (void) keyDown: (NSEvent *) event {
-	char in;
-	BOOL converted = [
-		[event characters]
-		getBytes: &in
-		maxLength: 1
-		usedLength: NULL
-		encoding: NSASCIIStringEncoding
-		options: 0
-		range: NSMakeRange(0, 1)
-		remainingRange: NULL
-	];
-	if (converted) {
-		if (!input(in)) {
-			[NSApp terminate: self];
-		}
-		[self draw];
-		[self setWindowTitle];
-	}
-}
-@end
-
-@interface Delegate : NSObject <NSApplicationDelegate>
-@end
-
-@implementation Delegate
-- (BOOL) applicationShouldTerminateAfterLastWindowClosed:
-	(NSApplication *) sender {
-	(void)sender;
-	return YES;
-}
-@end
-
-int main(int argc, char *argv[]) {
-	int error = init(argc, argv);
-	if (error) return error;
-
-	[NSApplication sharedApplication];
-	[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular];
-	[NSApp setDelegate: [Delegate new]];
-
-	NSString *name = [[NSProcessInfo processInfo] processName];
-	NSMenu *menu = [NSMenu new];
-	[
-		menu
-		addItemWithTitle: @"Close Window"
-		action: @selector(performClose:)
-		keyEquivalent: @"w"
-	];
-	[menu addItem: [NSMenuItem separatorItem]];
-	[
-		menu
-		addItemWithTitle: [@"Quit " stringByAppendingString: name]
-		action: @selector(terminate:)
-		keyEquivalent: @"q"
-	];
-	NSMenuItem *menuItem = [NSMenuItem new];
-	[menuItem setSubmenu: menu];
-	[NSApp setMainMenu: [NSMenu new]];
-	[[NSApp mainMenu] addItem: menuItem];
-
-	NSUInteger style = NSWindowStyleMaskTitled
-		| NSWindowStyleMaskClosable
-		| NSWindowStyleMaskMiniaturizable
-		| NSWindowStyleMaskResizable;
-	NSWindow *window = [
-		[NSWindow alloc]
-		initWithContentRect: NSMakeRect(0, 0, 800, 600)
-		styleMask: style
-		backing: NSBackingStoreBuffered
-		defer: YES
-	];
-	[window center];
-
-	BufferView *view = [[BufferView alloc] initWithFrame: [window frame]];
-	[window setContentView: view];
-	[view setWindowTitle];
-
-	[window makeKeyAndOrderFront: nil];
-	[NSApp activateIgnoringOtherApps: YES];
-	[NSApp run];
-}
diff --git a/bin/gfx-fb.c b/bin/gfx-fb.c
deleted file mode 100644
index 0c4ddbf2..00000000
--- a/bin/gfx-fb.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <err.h>
-#include <fcntl.h>
-#include <linux/fb.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sysexits.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "gfx.h"
-
-static struct termios saveTerm;
-static void restoreTerm(void) {
-	tcsetattr(STDERR_FILENO, TCSADRAIN, &saveTerm);
-}
-
-int main(int argc, char *argv[]) {
-	int error;
-
-	error = init(argc, argv);
-	if (error) return error;
-
-	const char *path = getenv("FRAMEBUFFER");
-	if (!path) path = "/dev/fb0";
-
-	int fb = open(path, O_RDWR);
-	if (fb < 0) err(EX_OSFILE, "%s", path);
-
-	struct fb_var_screeninfo info;
-	error = ioctl(fb, FBIOGET_VSCREENINFO, &info);
-	if (error) err(EX_IOERR, "%s", path);
-
-	size_t size = 4 * info.xres * info.yres;
-	uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
-	if (buf == MAP_FAILED) err(EX_IOERR, "%s", path);
-
-	error = tcgetattr(STDERR_FILENO, &saveTerm);
-	if (error) err(EX_IOERR, "tcgetattr");
-	atexit(restoreTerm);
-
-	struct termios term = saveTerm;
-	term.c_lflag &= ~(ICANON | ECHO);
-	error = tcsetattr(STDERR_FILENO, TCSADRAIN, &term);
-	if (error) err(EX_IOERR, "tcsetattr");
-
-	uint32_t saveBg = buf[0];
-
-	uint32_t back[info.xres * info.yres];
-	for (;;) {
-		draw(back, info.xres, info.yres);
-		memcpy(buf, back, size);
-
-		char in;
-		ssize_t len = read(STDERR_FILENO, &in, 1);
-		if (len < 0) err(EX_IOERR, "read");
-		if (!len) return EX_DATAERR;
-
-		if (!input(in)) {
-			for (uint32_t i = 0; i < info.xres * info.yres; ++i) {
-				buf[i] = saveBg;
-			}
-			fprintf(stderr, "%s\n", status());
-			return EX_OK;
-		}
-	}
-}
diff --git a/bin/gfx-x11.c b/bin/gfx-x11.c
deleted file mode 100644
index 8a35364d..00000000
--- a/bin/gfx-x11.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <X11/Xlib.h>
-#include <err.h>
-#include <sysexits.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "gfx.h"
-
-static size_t width = 800;
-static size_t height = 600;
-
-static Display *display;
-static Window window;
-static Atom WM_DELETE_WINDOW;
-static GC windowGc;
-static XImage *image;
-
-static size_t bufSize;
-static uint32_t *buf;
-
-static size_t pixmapWidth;
-static size_t pixmapHeight;
-static Pixmap pixmap;
-
-static void createWindow(void) {
-	display = XOpenDisplay(NULL);
-	if (!display) errx(EX_UNAVAILABLE, "XOpenDisplay: %s", XDisplayName(NULL));
-
-	Window root = DefaultRootWindow(display);
-	window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, 0);
-
-	WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", false);
-	XSetWMProtocols(display, window, &WM_DELETE_WINDOW, 1);
-
-	windowGc = XCreateGC(display, window, 0, NULL);
-
-	image = XCreateImage(display, NULL, 24, ZPixmap, 0, NULL, width, height, 32, 0);
-}
-
-static void resizePixmap(void) {
-	size_t newSize = 4 * width * height;
-	if (newSize > bufSize) {
-		bufSize = newSize;
-		free(buf);
-		buf = malloc(bufSize);
-		if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize);
-	}
-
-	image->data = (char *)buf;
-	image->width = width;
-	image->height = height;
-	image->bytes_per_line = 4 * width;
-
-	if (width > pixmapWidth || height > pixmapHeight) {
-		pixmapWidth = width;
-		pixmapHeight = height;
-		if (pixmap) XFreePixmap(display, pixmap);
-		pixmap = XCreatePixmap(display, window, pixmapWidth, pixmapHeight, 24);
-	}
-}
-
-static void drawWindow(void) {
-	draw(buf, width, height);
-	XPutImage(display, pixmap, windowGc, image, 0, 0, 0, 0, width, height);
-	XCopyArea(display, pixmap, window, windowGc, 0, 0, width, height, 0, 0);
-}
-
-int main(int argc, char *argv[]) {
-	int error = init(argc, argv);
-	if (error) return error;
-
-	createWindow();
-	resizePixmap();
-	drawWindow();
-
-	XStoreName(display, window, status());
-	XMapWindow(display, window);
-
-	XEvent event;
-	XSelectInput(display, window, ExposureMask | StructureNotifyMask | KeyPressMask);
-	for (;;) {
-		XNextEvent(display, &event);
-
-		switch (event.type) {
-			case KeyPress: {
-				XKeyEvent key = event.xkey;
-				KeySym sym = XLookupKeysym(&key, key.state & ShiftMask);
-				if (sym > 0x80) break;
-				if (!input(sym)) return EX_OK;
-				drawWindow();
-				XStoreName(display, window, status());
-			} break;
-
-			case ConfigureNotify: {
-				XConfigureEvent configure = event.xconfigure;
-				width = configure.width;
-				height = configure.height;
-				resizePixmap();
-				drawWindow();
-			} break;
-
-			case Expose: {
-				XExposeEvent expose = event.xexpose;
-				XCopyArea(
-					display, pixmap, window, windowGc,
-					expose.x, expose.y,
-					expose.width, expose.height,
-					expose.x, expose.y
-				);
-			} break;
-
-			case ClientMessage: {
-				XClientMessageEvent client = event.xclient;
-				if ((Atom)client.data.l[0] == WM_DELETE_WINDOW) return EX_OK;
-			} break;
-		}
-	}
-}
diff --git a/bin/gfx.h b/bin/gfx.h
deleted file mode 100644
index 2372c0f3..00000000
--- a/bin/gfx.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-extern int init(int argc, char *argv[]);
-extern const char *status(void);
-extern void draw(uint32_t *buf, size_t width, size_t height);
-extern bool input(char in);
diff --git a/bin/gfxx.c b/bin/gfxx.c
deleted file mode 100644
index 0e2a2f2a..00000000
--- a/bin/gfxx.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/* Copyright (C) 2018  June McEnroe <june@causal.agency>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <err.h>
-#include <fcntl.h>
-#include <math.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-#include "gfx.h"
-#include "png.h"
-
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MASK(b) ((1 << (b)) - 1)
-
-static uint32_t rgb(uint8_t r, uint8_t g, uint8_t b) {
-	return (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b;
-}
-static uint32_t gray(uint8_t n) {
-	return rgb(n, n, n);
-}
-
-static enum {
-	ColorIndexed,
-	ColorGrayscale,
-	ColorRGB,
-	ColorCount,
-} space = ColorRGB;
-static const char *ColorStr[ColorCount] = { "indexed", "grayscale", "rgb" };
-static uint32_t palette[256];
-
-static enum {
-	EndianLittle,
-	EndianBig,
-} byteOrder, bitOrder;
-
-enum { Pad, R, G, B };
-static uint8_t bits[4] = { 8, 8, 8, 8 };
-
-static uint8_t bitsColor(void) {
-	return bits[R] + bits[G] + bits[B];
-}
-static uint8_t bitsTotal(void) {
-	return bits[Pad] + bitsColor();
-}
-
-static size_t offset;
-static size_t width = 16;
-static bool flip;
-static bool mirror;
-static size_t scale = 1;
-
-static const char *prefix = "gfxx";
-
-static size_t size;
-static uint8_t *data;
-
-int init(int argc, char *argv[]) {
-	const char *pal = NULL;
-	const char *path = NULL;
-
-	int opt;
-	while (0 < (opt = getopt(argc, argv, "c:p:b:e:E:n:fmw:z:o:"))) {
-		switch (opt) {
-			break; case 'c':
-				switch (optarg[0]) {
-					break; case 'i': space = ColorIndexed;
-					break; case 'g': space = ColorGrayscale;
-					break; case 'r': space = ColorRGB;
-					break; default: return EX_USAGE;
-				}
-			break; case 'p': pal = optarg;
-			break; case 'e':
-				switch (optarg[0]) {
-					break; case 'l': byteOrder = EndianLittle;
-					break; case 'b': byteOrder = EndianBig;
-					break; default: return EX_USAGE;
-				}
-			break; case 'E':
-				switch (optarg[0]) {
-					break; case 'l': bitOrder = EndianLittle;
-					break; case 'b': bitOrder = EndianBig;
-					break; default: return EX_USAGE;
-				}
-			break; case 'b': {
-				if (strlen(optarg) < 4) return EX_USAGE;
-				for (int i = 0; i < 4; ++i) {
-					bits[i] = optarg[i] - '0';
-				}
-			}
-			break; case 'n': offset = strtoul(optarg, NULL, 0);
-			break; case 'f': flip ^= true;
-			break; case 'm': mirror ^= true;
-			break; case 'w': width = strtoul(optarg, NULL, 0);
-			break; case 'z': scale = strtoul(optarg, NULL, 0);
-			break; case 'o': prefix = optarg;
-			break; default: return EX_USAGE;
-		}
-	}
-	if (argc > optind) path = argv[optind];
-	if (!width || !scale) return EX_USAGE;
-
-	if (pal) {
-		FILE *file = fopen(pal, "r");
-		if (!file) err(EX_NOINPUT, "%s", pal);
-		fread(palette, 4, 256, file);
-		if (ferror(file)) err(EX_IOERR, "%s", pal);
-		fclose(file);
-	} else {
-		for (int i = 0; i < 256; ++i) {
-			double h = i / 256.0 * 6.0;
-			double x = 1.0 - fabs(fmod(h, 2.0) - 1.0);
-			double r = 255.0, g = 255.0, b = 255.0;
-			if      (h <= 1.0) { g *= x; b = 0.0; }
-			else if (h <= 2.0) { r *= x; b = 0.0; }
-			else if (h <= 3.0) { r = 0.0; b *= x; }
-			else if (h <= 4.0) { r = 0.0; g *= x; }
-			else if (h <= 5.0) { r *= x; g = 0.0; }
-			else if (h <= 6.0) { g = 0.0; b *= x; }
-			palette[i] = (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b;
-		}
-	}
-
-	if (path) {
-		int fd = open(path, O_RDONLY);
-		if (fd < 0) err(EX_NOINPUT, "%s", path);
-
-		struct stat stat;
-		int error = fstat(fd, &stat);
-		if (error) err(EX_IOERR, "%s", path);
-		size = stat.st_size;
-
-		data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-		if (data == MAP_FAILED) err(EX_IOERR, "%s", path);
-
-	} else {
-		size = 1024 * 1024;
-		data = malloc(size);
-		if (!data) err(EX_OSERR, "malloc(%zu)", size);
-
-		size = fread(data, 1, size, stdin);
-		if (ferror(stdin)) err(EX_IOERR, "(stdin)");
-	}
-
-	return EX_OK;
-}
-
-static char options[128];
-static void formatOptions(void) {
-	snprintf(
-		options, sizeof(options),
-		"gfxx -c %s -e%c -E%c -b %hhu%hhu%hhu%hhu -n 0x%zX %s%s-w %zu -z %zu",
-		ColorStr[space],
-		"lb"[byteOrder],
-		"lb"[bitOrder],
-		bits[Pad], bits[R], bits[G], bits[B],
-		offset,
-		flip ? "-f " : "",
-		mirror ? "-m " : "",
-		width,
-		scale
-	);
-}
-
-const char *status(void) {
-	formatOptions();
-	return options;
-}
-
-struct Iter {
-	uint32_t *buf;
-	size_t bufWidth;
-	size_t bufHeight;
-	size_t left;
-	size_t x;
-	size_t y;
-};
-
-static struct Iter iter(uint32_t *buf, size_t bufWidth, size_t bufHeight) {
-	struct Iter it = { .buf = buf, .bufWidth = bufWidth, .bufHeight = bufHeight };
-	if (mirror) it.x = width - 1;
-	if (flip) it.y = bufHeight / scale - 1;
-	return it;
-}
-
-static bool nextX(struct Iter *it) {
-	if (mirror) {
-		if (it->x == it->left) return false;
-		it->x--;
-	} else {
-		it->x++;
-		if (it->x == it->left + width) return false;
-	}
-	return true;
-}
-
-static bool nextY(struct Iter *it) {
-	if (flip) {
-		if (it->y == 0) {
-			it->left += width;
-			it->y = it->bufHeight / scale;
-		}
-		it->y--;
-	} else {
-		it->y++;
-		if (it->y == it->bufHeight / scale) {
-			it->left += width;
-			it->y = 0;
-		}
-	}
-	it->x = it->left;
-	if (mirror) it->x += width - 1;
-	return (it->left < it->bufWidth / scale);
-}
-
-static bool next(struct Iter *it) {
-	return nextX(it) || nextY(it);
-}
-
-static void put(const struct Iter *it, uint32_t pixel) {
-	size_t scaledX = it->x * scale;
-	size_t scaledY = it->y * scale;
-	for (size_t fillY = scaledY; fillY < scaledY + scale; ++fillY) {
-		if (fillY >= it->bufHeight) break;
-		for (size_t fillX = scaledX; fillX < scaledX + scale; ++fillX) {
-			if (fillX >= it->bufWidth) break;
-			it->buf[fillY * it->bufWidth + fillX] = pixel;
-		}
-	}
-}
-
-static uint8_t interp(uint8_t b, uint32_t n) {
-	if (b == 8) return n;
-	if (b == 0) return 0;
-	return n * MASK(8) / MASK(b);
-}
-
-static uint32_t interpolate(uint32_t orig) {
-	uint32_t r, g, b;
-	if (bitOrder == EndianLittle) {
-		b = orig & MASK(bits[B]);
-		g = (orig >>= bits[B]) & MASK(bits[G]);
-		r = (orig >>= bits[G]) & MASK(bits[R]);
-	} else {
-		r = orig & MASK(bits[R]);
-		g = (orig >>= bits[R]) & MASK(bits[G]);
-		b = (orig >>= bits[G]) & MASK(bits[B]);
-	}
-	return rgb(interp(bits[R], r), interp(bits[G], g), interp(bits[B], b));
-}
-
-static void drawBits(struct Iter *it) {
-	for (size_t i = offset; i < size; ++i) {
-		for (uint8_t b = 0; b < 8; b += bitsTotal()) {
-			uint8_t n;
-			if (byteOrder == EndianBig) {
-				n = data[i] >> (8 - bitsTotal() - b) & MASK(bitsTotal());
-			} else {
-				n = data[i] >> b & MASK(bitsTotal());
-			}
-
-			if (space == ColorIndexed) {
-				put(it, palette[n]);
-			} else if (space == ColorGrayscale) {
-				put(it, gray(interp(bitsColor(), n & MASK(bitsColor()))));
-			} else if (space == ColorRGB) {
-				put(it, interpolate(n));
-			}
-
-			if (!next(it)) return;
-		}
-	}
-}
-
-static void drawBytes(struct Iter *it) {
-	uint8_t bytes = (bitsTotal() + 7) / 8;
-	for (size_t i = offset; i + bytes <= size; i += bytes) {
-		uint32_t n = 0;
-		for (size_t b = 0; b < bytes; ++b) {
-			n <<= 8;
-			n |= (byteOrder == EndianBig) ? data[i + b] : data[i + bytes - b - 1];
-		}
-
-		if (space == ColorIndexed) {
-			put(it, palette[n & 0xFF]);
-		} else if (space == ColorGrayscale) {
-			put(it, gray(interp(bitsColor(), n & MASK(bitsColor()))));
-		} else if (space == ColorRGB) {
-			put(it, interpolate(n));
-		}
-
-		if (!next(it)) return;
-	}
-}
-
-static struct {
-	unsigned counter;
-	char path[FILENAME_MAX];
-	FILE *file;
-} out;
-static void outOpen(const char *ext) {
-	snprintf(out.path, sizeof(out.path), "%s%04u.%s", prefix, ++out.counter, ext);
-	out.file = fopen(out.path, "wx");
-	if (out.file) {
-		printf("%s\n", out.path);
-	} else {
-		warn("%s", out.path);
-	}
-}
-
-static void pngDump(uint32_t *src, size_t srcWidth, size_t srcHeight) {
-	int error;
-
-	size_t stride = 1 + 3 * srcWidth;
-	uint8_t data[stride * srcHeight];
-	for (size_t y = 0; y < srcHeight; ++y) {
-		data[y * stride] = 0;
-		for (size_t x = 0; x < srcWidth; ++x) {
-			uint8_t *p = &data[y * stride + 1 + 3 * x];
-			p[0] = src[y * srcWidth + x] >> 16;
-			p[1] = src[y * srcWidth + x] >> 8;
-			p[2] = src[y * srcWidth + x];
-		}
-	}
-
-	outOpen("png");
-	if (!out.file) return;
-
-	const char Software[] = "Software";
-	formatOptions();
-	uint8_t sbit[3] = { MAX(bits[R], 1), MAX(bits[G], 1), MAX(bits[B], 1) };
-
-	pngHead(out.file, srcWidth, srcHeight, 8, PNGTruecolor);
-
-	pngChunk(out.file, "tEXt", sizeof(Software) + strlen(options));
-	pngWrite(out.file, (uint8_t *)Software, sizeof(Software));
-	pngWrite(out.file, (uint8_t *)options, strlen(options));
-	pngInt32(out.file, ~pngCRC);
-
-	pngChunk(out.file, "sBIT", sizeof(sbit));
-	pngWrite(out.file, sbit, sizeof(sbit));
-	pngInt32(out.file, ~pngCRC);
-
-	pngData(out.file, data, sizeof(data));
-	pngTail(out.file);
-
-	error = fclose(out.file);
-	if (error) err(EX_IOERR, "%s", out.path);
-}
-
-static enum {
-	DumpNone,
-	DumpOne,
-	DumpAll,
-} dump;
-
-void draw(uint32_t *buf, size_t bufWidth, size_t bufHeight) {
-	memset(buf, 0, 4 * bufWidth * bufHeight);
-	struct Iter it = iter(buf, bufWidth, bufHeight);
-	if (bitsTotal() >= 8) {
-		drawBytes(&it);
-	} else {
-		drawBits(&it);
-	}
-	if (dump) pngDump(buf, bufWidth, bufHeight);
-	if (dump == DumpOne) dump = DumpNone;
-}
-
-static void palSample(void) {
-	size_t temp = scale;
-	scale = 1;
-	draw(palette, 256, 1);
-	scale = temp;
-}
-
-static void palDump(void) {
-	outOpen("dat");
-	if (!out.file) return;
-
-	fwrite(palette, 4, 256, out.file);
-	if (ferror(out.file)) err(EX_IOERR, "%s", out.path);
-
-	int error = fclose(out.file);
-	if (error) err(EX_IOERR, "%s", out.path);
-}
-
-static const uint8_t Presets[][4] = {
-	{ 0, 0, 1, 0 },
-	{ 0, 1, 1, 0 },
-	{ 1, 1, 1, 1 },
-	{ 2, 2, 2, 2 },
-	{ 0, 3, 3, 2 },
-	{ 4, 4, 4, 4 },
-	{ 1, 5, 5, 5 },
-	{ 0, 5, 6, 5 },
-	{ 0, 8, 8, 8 },
-	{ 8, 8, 8, 8 },
-};
-static const size_t PresetsLen = sizeof(Presets) / sizeof(Presets[0]);
-
-static uint8_t preset = PresetsLen - 1;
-static void setPreset(void) {
-	bits[Pad] = Presets[preset][Pad];
-	bits[R] = Presets[preset][R];
-	bits[G] = Presets[preset][G];
-	bits[B] = Presets[preset][B];
-}
-
-static void setBit(char in) {
-	static uint8_t bit = 0;
-	bits[bit++] = in - '0';
-	bit &= 3;
-}
-
-bool input(char in) {
-	size_t pixel = (bitsTotal() + 7) / 8;
-	size_t row = width * bitsTotal() / 8;
-	switch (in) {
-		break; case 'q': return false;
-		break; case 'x': dump = DumpOne;
-		break; case 'X': dump ^= DumpAll;
-		break; case 'o': formatOptions(); printf("%s\n", options);
-		break; case '[': if (!space--) space = ColorCount - 1;
-		break; case ']': if (++space == ColorCount) space = 0;
-		break; case 'p': palSample();
-		break; case 'P': palDump();
-		break; case '{': if (!preset--) preset = PresetsLen - 1; setPreset();
-		break; case '}': if (++preset == PresetsLen) preset = 0; setPreset();
-		break; case 'e': byteOrder ^= EndianBig;
-		break; case 'E': bitOrder ^= EndianBig;
-		break; case 'h': if (offset) offset--;
-		break; case 'j': offset += pixel;
-		break; case 'k': if (offset >= pixel) offset -= pixel;
-		break; case 'l': offset++;
-		break; case 'H': if (offset >= row) offset -= row;
-		break; case 'J': offset += width * row;
-		break; case 'K': if (offset >= width * row) offset -= width * row;
-		break; case 'L': offset += row;
-		break; case '.': width++;
-		break; case ',': if (width > 1) width--;
-		break; case '>': width *= 2;
-		break; case '<': if (width > 1) width /= 2;
-		break; case 'f': flip ^= true;
-		break; case 'm': mirror ^= true;
-		break; case '+': scale++;
-		break; case '-': if (scale > 1) scale--;
-		break; default: if (in >= '0' && in <= '9') setBit(in);
-	}
-	return true;
-}
diff --git a/bin/man1/brot.1 b/bin/man1/brot.1
deleted file mode 100644
index 7c1a4087..00000000
--- a/bin/man1/brot.1
+++ /dev/null
@@ -1,63 +0,0 @@
-.Dd September 8, 2018
-.Dt BROT 1
-.Os
-.
-.Sh NAME
-.Nm brot
-.Nd Mandelbrot renderer
-.
-.Sh SYNOPSIS
-.Nm
-.Op Fl i Ar depth
-.Op Fl s Ar samples
-.Op Fl t Ar a+bi
-.Op Fl f Ar a+bi
-.
-.Sh DESCRIPTION
-.Nm
-renders the Mandelbrot set
-in grayscale.
-.
-.Pp
-The arguments are as follows:
-.Bl -tag -width Ds
-.It Fl f Ar a+bi
-Set complex transform factor.
-.
-.It Fl i Ar depth
-Set number of iterations.
-.
-.It Fl s Ar samples
-Set number of samples per pixel.
-.
-.It Fl t Ar a+bi
-Set complex translation term.
-.El
-.
-.Pp
-The interactive keys are as follows:
-.Bl -tag -width Ds
-.It Ic q
-Quit.
-.
-.It Ic ,.
-Adjust depth.
-.
-.It Ic []
-Adjust samples.
-.
-.It Ic hl
-Adjust real component of translation.
-.
-.It Ic kj
-Adjust imaginary componenent of translation.
-.
-.It Ic ui
-Adjust rotation.
-.
-.It Ic -+
-Adjust scale.
-.
-.It Ic 0
-Reset translation and transform.
-.El
diff --git a/bin/man1/gfxx.1 b/bin/man1/gfxx.1
deleted file mode 100644
index d3d1edbd..00000000
--- a/bin/man1/gfxx.1
+++ /dev/null
@@ -1,138 +0,0 @@
-.Dd September 8, 2018
-.Dt GFXX 1
-.Os
-.
-.Sh NAME
-.Nm gfxx
-.Nd graphics data explorer
-.
-.Sh SYNOPSIS
-.Nm
-.Op Fl fm
-.Op Fl c Ar space
-.Op Fl p Ar file
-.Op Fl e Ar lb
-.Op Fl E Ar lb
-.Op Fl b Ar bits
-.Op Fl n Ar offset
-.Op Fl w Ar width
-.Op Fl z Ar scale
-.Op Fl o Ar prefix
-.
-.Sh DESCRIPTION
-.Nm
-is an interactive graphics data explorer
-capable of dumping PNGs.
-.
-.Pp
-The arguments are as follows:
-.Bl -tag -width Ds
-.It Fl E Ar lb
-Set bit order to little or big endian.
-.
-.It Fl b Ar bits
-Set number of bits of padding,
-red,
-green
-and blue
-components.
-Four digits are required.
-.
-.It Fl c Ar space
-Set color space to one of
-.Cm indexed ,
-.Cm grayscale ,
-.Cm rgb .
-.
-.It Fl e Ar lb
-Set byte order to little or big endian.
-.
-.It Fl f
-Flip display vertically.
-.
-.It Fl m
-Mirror display horizontally.
-.
-.It Fl n Ar offset
-Set byte offset into data.
-.
-.It Fl o Ar prefix
-Set PNG output filename prefix.
-.
-.It Fl p Ar file
-Load indexed color palette from
-.Ar file .
-.
-.It Fl w Ar width
-Set display column width.
-.
-.It Fl z Ar scale
-Set display scale.
-.El
-.
-.Pp
-The interactive keys are as follows:
-.Bl -tag -width Ds
-.It Ic q
-Quit.
-.
-.It Ic x
-Export one frame as PNG.
-.
-.It Ic X
-Export each frame as PNG.
-.
-.It Ic o
-Print interactive options.
-.
-.It Ic []
-Select color space.
-.
-.It Ic p
-Sample indexed palette from top-left corner.
-.
-.It Ic P
-Export indexed palette as RGB data.
-.
-.It Ic {}
-Select bits preset.
-.
-.It Ic e
-Toggle byte order.
-.
-.It Ic E
-Toggle bit order.
-.
-.It Ic hl
-Adjust offset by byte.
-.
-.It Ic jk
-Adjust offset by pixel.
-.
-.It Ic HL
-Adjust offset by pixel row.
-.
-.It Ic JK
-Adjust offset by pixel row square.
-.
-.It Ic ,.
-Adjust display column width.
-.
-.It Ic <>
-Adjust display column width by half or double.
-.
-.It Ic f
-Toggle vertically flipped display.
-.
-.It Ic m
-Toggle horizontally mirrored display.
-.
-.It Ic -+
-Adjust display scale.
-.
-.It Ic 0-9
-Set bits.
-.El
-.
-.Sh SEE ALSO
-.Xr pngo 1