commit fea897c

uint  ·  2026-08-03 16:42:08 +0000 UTC
parent 09086f8
Refactor to ANSI C
15 files changed,  +542, -386
+26, -7
 1@@ -1,9 +1,12 @@
 2+.POSIX:
 3+
 4 include config.mk
 5 
 6 CC = cc
 7 AR = ar
 8-CFLAGS = -std=c99 -Wall -Wextra -O2
 9-CPPFLAGS = ${CONF_CPPFLAGS} -Iinclude
10+ARFLAGS = -r -c
11+CFLAGS = -ansi -pedantic-errors -Wall -Wextra -O2
12+CPPFLAGS = ${CONF_CPPFLAGS} -Iinclude -Ibuild
13 LDFLAGS = ${CONF_LDFLAGS}
14 
15 LIB_NAME = build/${CONF_LIB_NAME}
16@@ -19,21 +22,37 @@ LIB_OBJS = build/maus.o       \
17 all: ${LIB_NAME}
18 
19 ${LIB_NAME}: ${LIB_OBJS}
20-	${AR} -rcs $@ ${LIB_OBJS}
21+	${AR} ${ARFLAGS} $@ ${LIB_OBJS}
22 
23-build/maus.o: source/maus.c
24+build/maus.o: source/maus.c include/maus.h config.mk
25 	mkdir -p build
26 	${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus.c -o $@
27-build/maus_font.o: source/maus_font.c
28+build/maus_font.o: source/maus_font.c include/maus.h include/maus_font.h config.mk
29 	mkdir -p build
30 	${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus_font.c -o $@
31-build/utils.o: source/utils.c
32+build/utils.o: source/utils.c include/utils.h
33 	mkdir -p build
34 	${CC} ${CFLAGS} ${CPPFLAGS} -c source/utils.c -o $@
35-build/maus_x11.o: source/maus_x11.c
36+
37+# X11
38+build/maus_x11.o: source/maus_x11.c include/maus.h include/maus_x11.h config.mk
39 	mkdir -p build
40 	${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus_x11.c -o $@
41 
42+# Wayland
43+build/maus_wayland.o: source/maus_wayland.c include/maus.h include/maus_wayland.h build/xdg-shell-client-protocol.h config.mk
44+	mkdir -p build
45+	${CC} ${CFLAGS} ${CPPFLAGS} -c source/maus_wayland.c -o $@
46+build/xdg-shell-client-protocol.h:
47+	mkdir -p build
48+	wayland-scanner client-header ${PROTOS}/stable/xdg-shell/xdg-shell.xml $@
49+build/xdg-shell-protocol.c:
50+	mkdir -p build
51+	wayland-scanner private-code ${PROTOS}/stable/xdg-shell/xdg-shell.xml $@
52+build/xdg-shell-protocol.o: build/xdg-shell-protocol.c build/xdg-shell-client-protocol.h
53+	mkdir -p build
54+	${CC} ${CFLAGS} ${CPPFLAGS} -c build/xdg-shell-protocol.c -o $@
55+
56 clean:
57 	rm -rf build ${LIB_NAME} config.mk compile_flags.txt
58 
+8, -5
 1@@ -1,10 +1,10 @@
 2 ![logo](assets/logo_256x112.png)  
 3-is a small, cross-platform, software windowing library
 4+is a small, cross-platform, software windowing library **now in ANSI C**
 5 
 6 ### Building
 7 Unix:
 8 ```sh
 9-./configure --backend=[x11|wayland|mac]
10+./configure [x11|wayland|mac]
11 make # That's it!
12 ```
13 
14@@ -12,15 +12,18 @@ Windows:
15 ```
16 .\build.bat [msvc|gcc|clang]
17 ```
18+> If anyone is on Windows, please try to compile past the ANSI conversion.
19+> I pretty much converted it without checking so there may still be C99
20+> artefacts left behind.
21 
22 After building, you have a library which you link _your_ sources with. It is
23 located in `build/`.
24 
25 ### Usage
26 #### libmaus
27-Here is an annoted example for a basic window program which counts the number of
28-frames that have elapsed, draw the text and displays if you've pressed a key
29-(specifically 'A').
30+Here is an annoted (C99) example for a basic window program which counts the
31+number of frames that have elapsed, draw the text and displays if you've
32+pressed a key (specifically 'A').
33 
34 For the full list of functions and what they do, look at
35 [the header](include/maus.h).
+6, -4
 1@@ -2,14 +2,16 @@
 2 
 3 for arg do
 4 	case "$arg" in
 5-		--backend=*) backend="${arg#*=}" ;;
 6 		--help)
 7-			echo "Usage: ./configure [--backend=x11|wayland|mac]"
 8+			echo "Usage: ./configure [x11|wayland|mac]"
 9 			exit 0
10 			;;
11 		*)
12-			echo "Unknown argument: $arg"
13-			exit 1
14+			if [ -n "$backend" ]; then
15+				echo "Usage: ./configure [x11|wayland|mac]"
16+				exit 1
17+			fi
18+			backend="$arg"
19 			;;
20 	esac
21 done
+5, -3
 1@@ -1,8 +1,10 @@
 2+include ../../config.mk
 3+
 4 CC = cc
 5 CFLAGS = -std=c99 -Wall -Wextra -g
 6-CPPFLAGS = -DBACKEND_X11 -I../../include
 7-LIBS = -lX11 -lXext
 8-MAUS_LIB = ../../build/libmaus_x11.a
 9+CPPFLAGS = ${CONF_CPPFLAGS} -I../../include -I../../build
10+LIBS = ${CONF_LDFLAGS}
11+MAUS_LIB = ../../build/${CONF_LIB_NAME}
12 
13 SRC = main.c
14 
+1, -1
1@@ -25,7 +25,7 @@ void handle_ev(Maus* mw, MausEvent* ev)
2 		case MAUS_EV_KEY: {
3 			(void)0;
4 
5-			bool* keys = mw->key_syms;
6+			int8_t* keys = mw->key_syms;
7 			if (keys[MAUS_KEY_CONTROL_L] && keys[MAUS_KEY_Q]) {
8 				maus_close(mw);
9 				exit(EXIT_SUCCESS);
+36, -39
  1@@ -1,7 +1,6 @@
  2 #ifndef MAUSWIN_H
  3 #define MAUSWIN_H
  4 
  5-#include <stdbool.h>
  6 #include <stdio.h>
  7 #include <stdint.h>
  8 
  9@@ -53,7 +52,7 @@
 10 	 ((uint32_t)(c).r << 16) | \
 11 	 ((uint32_t)(c).g <<  8) | \
 12 	 ((uint32_t)(c).b))
 13-/* ... */
 14+
 15 #define MAUS_PIXEL_AT(mw, x, y) ((mw)->bfb[(y) * (mw)->stride + (x)])
 16 
 17 typedef enum {
 18@@ -63,7 +62,7 @@ typedef enum {
 19 	MAUS_EV_MOUSE_BUTTON,
 20 	MAUS_EV_MOUSE_MOTION,
 21 	MAUS_EV_RESIZE,
 22-	MAUS_EV_REDRAW, /* TODO: MAUS_EV_REDRAW for windows */
 23+	MAUS_EV_REDRAW /* TODO: MAUS_EV_REDRAW for windows */
 24 } MausEventType;
 25 
 26 typedef struct {
 27@@ -76,31 +75,29 @@ typedef struct {
 28 typedef struct {
 29 	MausEventType type;
 30 
 31-	union {
 32-		struct {
 33-			uint32_t code; /* raw, backend keycode */
 34-			MausKey  key;  /* logical, mapped key */
 35-			char     text; /* translated text from key */
 36-			bool     pressed;
 37-		} key;
 38+	struct {
 39+		uint32_t code; /* raw, backend keycode */
 40+		MausKey  key;  /* logical, mapped key */
 41+		char     text; /* translated text from key */
 42+		int8_t     pressed;
 43+	} key;
 44 
 45+	struct {
 46 		struct {
 47-			struct {
 48-				MausMouseButton button;
 49-				bool            pressed;
 50-			} button;
 51-
 52-			struct {
 53-				int32_t x;
 54-				int32_t y;
 55-			} motion;
 56-		} mouse;
 57+			MausMouseButton button;
 58+			int8_t            pressed;
 59+		} button;
 60 
 61 		struct {
 62-			uint32_t width;
 63-			uint32_t height;
 64-		} resize;
 65-	};
 66+			int32_t x;
 67+			int32_t y;
 68+		} motion;
 69+	} mouse;
 70+
 71+	struct {
 72+		uint32_t width;
 73+		uint32_t height;
 74+	} resize;
 75 } MausEvent;
 76 
 77 typedef struct {
 78@@ -118,11 +115,11 @@ typedef struct {
 79 	int32_t     x;
 80 	int32_t     y;
 81 
 82-	bool key_codes[MAUS_KEYCODE_LAST]; /* physical keys */
 83-	bool key_syms[MAUS_KEY_LAST];      /* logical keys */
 84+	int8_t key_codes[MAUS_KEYCODE_LAST]; /* physical keys */
 85+	int8_t key_syms[MAUS_KEY_LAST];      /* logical keys */
 86 
 87 	MausCursor cursor;
 88-	bool       mouse_buttons[MAUS_MOUSE_BUTTON_LAST];
 89+	int8_t       mouse_buttons[MAUS_MOUSE_BUTTON_LAST];
 90 } Maus;
 91 
 92 /* clear screen with color: `col` */
 93@@ -134,14 +131,14 @@ void maus_clipboard_set_text(Maus* mw, const char* text);
 94 /* get text from system clipboard */
 95 char* maus_clipboard_get_text(Maus* mw);
 96 
 97-/* close a Maus. returns false on fail */
 98+/* close a Maus. returns 0 on fail */
 99 void maus_close(Maus* mw);
100 
101-/* close a window without the whole Maus. returns false on fail */
102-bool maus_close_window(Maus* mw);
103+/* close a window without the whole Maus. returns 0 on fail */
104+int8_t maus_close_window(Maus* mw);
105 
106-/* create window from Maus. returns false on fail */
107-bool maus_create_window(Maus* mw);
108+/* create window from Maus. returns 0 on fail */
109+int8_t maus_create_window(Maus* mw);
110 
111 /* log message to output `fd` and die */
112 void maus_die(const char* fmt, ...);
113@@ -156,20 +153,20 @@ Maus* maus_init(const char* title, int x, int y, int width, int height);
114 void maus_log(FILE* fd, const char* fmt, ...);
115 
116 /* poll for events then fill `ev` with retrieved events.
117-   returns true if event polled, else false.
118+   returns 1 if event polled, else 0.
119    note: can burn cpu cycles */
120-bool maus_event_poll(Maus* mw, MausEvent* ev);
121+int8_t maus_event_poll(Maus* mw, MausEvent* ev);
122 
123-/* poll for events then fill `ev` with retrieved events. returns true if event
124-   polled, else false. note, thread goes to sleep until an event arrives */
125+/* poll for events then fill `ev` with retrieved events. returns 1 if event
126+   polled, else 0. note, thread goes to sleep until an event arrives */
127 void maus_event_wait(Maus* mw, MausEvent* ev);
128 
129 /* present the pixelbuffer to the screen */
130 void maus_present(Maus* mw);
131 
132-/* resize window to specified width and height. returns true on resize success,
133-   else false */
134-bool maus_resize(Maus* mw, uint32_t width, uint32_t height);
135+/* resize window to specified width and height. returns 1 on resize success,
136+   else 0 */
137+int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height);
138 
139 /* cap framerate to targetted fps */
140 void maus_target_fps(Maus* mw, uint32_t fps);
+12, -13
 1@@ -2,29 +2,28 @@
 2 #define MAUS_FONT_H
 3 
 4 #include <stdint.h>
 5-#include <stdbool.h>
 6 
 7 #include "maus.h"
 8 
 9 #define MAUS_BDF_GLYPHS_MAX 256
10 
11 typedef struct {
12-    uint8_t* bmp;
13-    uint16_t w;
14-    uint16_t h;
15-    int16_t  xoff;
16-    int16_t  yoff;
17-    uint16_t adv;
18-    bool     valid;
19+	uint8_t* bmp;
20+	uint16_t w;
21+	uint16_t h;
22+	int16_t  xoff;
23+	int16_t  yoff;
24+	uint16_t adv;
25+	int8_t   valid;
26 } MausGlyph;
27 
28 typedef struct {
29-    MausGlyph glyphs[MAUS_BDF_GLYPHS_MAX];
30+	MausGlyph glyphs[MAUS_BDF_GLYPHS_MAX];
31 
32-    int32_t asc;
33-    int32_t dsc;
34-    int32_t cellh;
35-    int32_t cellw;
36+	int32_t asc;
37+	int32_t dsc;
38+	int32_t cellh;
39+	int32_t cellw;
40 } MausFont;
41 
42 /* Loops through text passing parameters to glyph drawer */
+3, -3
 1@@ -59,7 +59,7 @@ typedef enum {
 2 	MAUS_KEY_KP_DECIMAL,    MAUS_KEY_KP_DIVIDE, MAUS_KEY_KP_MULTIPLY,
 3 	MAUS_KEY_KP_SUBTRACT,   MAUS_KEY_KP_ADD,    MAUS_KEY_KP_ENTER,  MAUS_KEY_KP_EQUAL,
 4 
 5-	MAUS_KEY_LAST,
 6+	MAUS_KEY_LAST
 7 } MausKey;
 8 
 9 typedef struct {
10@@ -71,7 +71,7 @@ typedef enum {
11 	MAUS_CURSOR_STATE_VISIBLE,
12 	MAUS_CURSOR_STATE_HIDDEN,
13 	MAUS_CURSOR_STATE_LOCKED,
14-	MAUS_CURSOR_STATE_FREE,
15+	MAUS_CURSOR_STATE_FREE
16 } MausCursorState;
17 
18 typedef enum {
19@@ -81,7 +81,7 @@ typedef enum {
20 	MAUS_MOUSE_BUTTON_RIGHT,
21 	MAUS_MOUSE_BUTTON_SCROLL_UP,
22 	MAUS_MOUSE_BUTTON_SCROLL_DOWN,
23-	MAUS_MOUSE_BUTTON_LAST,
24+	MAUS_MOUSE_BUTTON_LAST
25 } MausMouseButton;
26 
27 #endif /* MAUS_KEYS_H */
+1, -2
 1@@ -1,7 +1,6 @@
 2 #ifndef MAUS_WIN_H
 3 #define MAUS_WIN_H
 4 
 5-#include <stdbool.h>
 6 #include <stdint.h>
 7 
 8 #include <windows.h>
 9@@ -12,7 +11,7 @@ typedef struct {
10 	HDC       hdc;
11 	HBITMAP   hbm;
12 	HDC       memdc;
13-	bool      resized;
14+	int8_t    resized;
15 	uint32_t  rw;
16 	uint32_t  rh;
17 } MausBackend;
+3, -3
 1@@ -1,14 +1,14 @@
 2 #ifndef MAUS_X11_H
 3 #define MAUS_X11_H
 4 
 5-#include <stdbool.h>
 6+#include <stdint.h>
 7 
 8 #include <X11/Xlib.h>
 9 #include <X11/extensions/XShm.h>
10 
11 typedef enum {
12 	MAUS_ATOM_WM_DELETE_WINDOW,
13-	MAUS_ATOM_LAST,
14+	MAUS_ATOM_LAST
15 } MausX11Atoms;
16 
17 typedef struct {
18@@ -19,7 +19,7 @@ typedef struct {
19 	GC       gc;
20 
21 	XShmSegmentInfo shm;
22-	bool            shmat;
23+	int8_t          shmat;
24 	XImage*         image; /* TODO: XImage path */
25 } MausBackend;
26 
+28, -15
 1@@ -22,6 +22,7 @@ static void vlog(FILE* fd, const char* fmt, va_list ap)
 2 void maus_die(const char* fmt, ...)
 3 {
 4 	va_list ap;
 5+
 6 	va_start(ap, fmt);
 7 	vlog(stderr, fmt, ap);
 8 	va_end(ap);
 9@@ -34,25 +35,29 @@ uint64_t maus_get_time_ns(void)
10 #if !defined(_WIN32)
11 	struct timespec ts;
12 	clock_gettime(CLOCK_MONOTONIC, &ts);
13-	return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
14+	return ts.tv_sec * 1000000000 + ts.tv_nsec;
15 #else
16 	static LARGE_INTEGER frequency = {0};
17+	LARGE_INTEGER counter;
18+	uint64_t sec;
19+	uint64_t rem;
20+
21 	if (frequency.QuadPart == 0)
22 		QueryPerformanceFrequency(&frequency);
23 
24-	LARGE_INTEGER counter;
25 	QueryPerformanceCounter(&counter);
26 
27-	uint64_t sec = counter.QuadPart / frequency.QuadPart;
28-	uint64_t rem = counter.QuadPart % frequency.QuadPart;
29+	sec = counter.QuadPart / frequency.QuadPart;
30+	rem = counter.QuadPart % frequency.QuadPart;
31 
32-	return (sec * 1000000000ULL) + ((rem * 1000000000ULL) / frequency.QuadPart);
33+	return (sec * 1000000000) + ((rem * 1000000000) / frequency.QuadPart);
34 #endif
35 }
36 
37 void maus_log(FILE* fd, const char* fmt, ...)
38 {
39 	va_list ap;
40+
41 	va_start(ap, fmt);
42 	vlog(fd, fmt, ap);
43 	fputc('\n', fd);
44@@ -61,24 +66,32 @@ void maus_log(FILE* fd, const char* fmt, ...)
45 
46 void maus_target_fps(Maus* mw, uint32_t fps)
47 {
48+	uint64_t ns_frame;
49+	uint64_t cur_time;
50+	uint64_t elapsed;
51+	uint64_t sleep;
52+
53+	#if !defined(_WIN32)
54+	struct timespec ts;
55+	#endif
56+
57 	if (fps == 0)
58 		return;
59 
60-	uint64_t ns_frame = 1000000000ULL / fps; /* max ns a frame can take */
61-	uint64_t cur_time = maus_get_time_ns();
62-	uint64_t elapsed = cur_time - mw->frame_time_last;
63+	ns_frame = 1000000000 / fps; /* max ns a frame can take */
64+	cur_time = maus_get_time_ns();
65+	elapsed = cur_time - mw->frame_time_last;
66 
67 	/* if early finish, sleep for the remaining time balance */
68 	if (elapsed < ns_frame) {
69-		uint64_t sleep = ns_frame - elapsed;
70+		sleep = ns_frame - elapsed;
71 	#if !defined(_WIN32)
72-		struct timespec ts;
73-		ts.tv_sec = sleep / 1000000000ULL;
74-		ts.tv_nsec = sleep % 1000000000ULL;
75+		ts.tv_sec = sleep / 1000000000;
76+		ts.tv_nsec = sleep % 1000000000;
77 		nanosleep(&ts, NULL);
78-	#else /* unix */
79-		Sleep((DWORD)((sleep + 999999ULL) / 1000000ULL));
80-	#endif /* platform */
81+	#else
82+		Sleep((DWORD)((sleep + 999999) / 1000000));
83+	#endif
84 	}
85 
86 	mw->frame_time_last = maus_get_time_ns();
+177, -122
  1@@ -5,17 +5,152 @@
  2 #include "maus.h"
  3 #include "maus_font.h"
  4 
  5+static void glyph_to_buf(int32_t sgx, int32_t egx, int32_t sgy, int32_t egy,
  6+                         int32_t gox, int32_t goy, MausGlyph* g, uint32_t col_up,
  7+                         uint32_t* buf, uint32_t stride);
  8+
  9+/* "blit" a glpyh to some buffer */
 10+static void glyph_to_buf(int32_t sgx, int32_t egx, int32_t sgy, int32_t egy,
 11+                         int32_t gox, int32_t goy, MausGlyph* g, uint32_t col_up,
 12+                         uint32_t* buf, uint32_t stride)
 13+{
 14+	int gy;
 15+	int gx;
 16+	int32_t dstx;
 17+
 18+	uint32_t* row;
 19+	int32_t offset;
 20+
 21+	for (gy = sgy; gy < egy; gy++) {
 22+		int dsty = goy + gy;
 23+
 24+		/* calculate row pointer once per scanline */
 25+		row = buf + (dsty * stride);
 26+		offset = gy * g->w;
 27+
 28+		for (gx = sgx; gx < egx; gx++) {
 29+			if (g->bmp[offset + gx] > 0) {
 30+				dstx = gox + gx;
 31+				row[dstx] = col_up;
 32+			}
 33+		}
 34+	}
 35+}
 36+
 37+static int8_t parse_glyphs(FILE* f, MausFont* font, char* line, size_t line_size,
 38+                           int32_t* encoding, int32_t* advance, int32_t* bw, int32_t* bh,
 39+                           int32_t* xoff, int32_t* yoff, int8_t* seen)
 40+{
 41+	int32_t rowbits;
 42+
 43+	int32_t x;
 44+	int32_t y;
 45+	uint64_t bits;
 46+
 47+	MausGlyph* g;
 48+
 49+	while (fgets(line, line_size, f)) {
 50+		if (sscanf(line, "ENCODING %d", encoding) == 1)
 51+			continue;
 52+		if (sscanf(line, "DWIDTH %d", advance) == 1)
 53+			continue;
 54+		if (sscanf(line, "BBX %d %d %d %d", bw, bh, xoff, yoff) == 4)
 55+			continue;
 56+
 57+		if (strncmp(line, "BITMAP", 6) == 0) {
 58+			/* invalid character code
 59+			   TODO: just skip it */
 60+			if (*encoding < 0 || *encoding >= MAUS_BDF_GLYPHS_MAX)
 61+				break;
 62+
 63+			/* empty/invalid size */
 64+			if (*bw <= 0 || *bh <= 0)
 65+				break;
 66+
 67+			g = &font->glyphs[*encoding];
 68+			free(g->bmp); /* prevent leak on hot reload */
 69+			memset(g, 0, sizeof(*g));
 70+
 71+			g->w = *bw;
 72+			g->h = *bh;
 73+			g->xoff = *xoff;
 74+			g->yoff = *yoff;
 75+			g->adv = *advance;
 76+
 77+			g->bmp = calloc((size_t)(*bw) * (*bh), 1);
 78+			if (!g->bmp) {
 79+				fclose(f);
 80+				maus_font_free(font);
 81+				return 0;
 82+			}
 83+
 84+			/* each bmp row in BDF is padded as a multiple
 85+			   of 8 bits. this rounds width up to the next
 86+			   multiple of 8 */
 87+			rowbits = (*bw + 7) & ~7;
 88+
 89+			for (y = 0; y < *bh; y++) {
 90+				/* missing row */
 91+				if (!fgets(line, line_size, f)) {
 92+					fclose(f);
 93+					maus_font_free(font);
 94+					return 0;
 95+				}
 96+
 97+				bits = strtoull(line, NULL, 16); /* hex to bits */
 98+				for (x = 0; x < *bw; x++) {
 99+					int bit = rowbits - 1 - x;
100+
101+					if ((bits >> bit) & 1)
102+						g->bmp[y * (*bw) + x] = 255; /* solid */
103+				}
104+			}
105+
106+			g->valid = 1;
107+			if (*advance > font->cellw)
108+				font->cellw = *advance;
109+			*seen = 1;
110+
111+			continue;
112+		}
113+
114+		if (strncmp(line, "ENDCHAR", 7) == 0)
115+			break;
116+	}
117+
118+	return 1;
119+}
120+
121 void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
122                     const char* text, MausColor col)
123 {
124+	uint32_t col_up = MAUS_UNPACK_COL(col);
125+
126+	size_t i;
127+
128+	/* current coordinates */
129+	int32_t cx = x;
130+	int32_t cy = y;
131+
132+	/* origins to start drawing glyph from */
133+	int32_t gox;
134+	int32_t goy;
135+
136+	/* starting glyph coordinates */
137+	int32_t sgx;
138+	int32_t sgy;
139+
140+	/* ending glyph coordinates */
141+	int32_t egx;
142+	int32_t egy;
143+
144+	/* current glyph pointer */
145+	MausGlyph* g;
146+
147 	if (!mw || !mw->bfb || !font || !text)
148 		return;
149 
150-	uint32_t col_up = MAUS_UNPACK_COL(col);
151-	int32_t cx = x; /* current x */
152-	int32_t cy = y; /* current y */
153-
154-	for (size_t i = 0; text[i] != '\0'; i++) {
155+	for (i = 0; text[i] != '\0'; i++) {
156 		char c = text[i];
157 
158 		if (c == '\n') {
159@@ -24,7 +159,7 @@ void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
160 			continue;
161 		}
162 
163-		MausGlyph* g = &font->glyphs[(uint8_t)c];
164+		g = &font->glyphs[(uint8_t)c];
165 		if (!g->valid) {
166 			/* still advance cx if character invalid */
167 			cx += (font->cellw > 0 ? font->cellw : 8);
168@@ -32,70 +167,57 @@ void maus_draw_text(Maus* mw, MausFont* font, int32_t x, int32_t y,
169 		}
170 
171 		/* origins to start drawing glyph from */
172-		int32_t gox = cx + g->xoff;
173-		int32_t goy = cy + font->asc - g->h - g->yoff;
174+		gox = cx + g->xoff;
175+		goy = cy + font->asc - g->h - g->yoff;
176 
177 		/* starting coordinates */
178-		int sgx = (-gox > 0) ? -gox : 0;
179-		int sgy = (-goy > 0) ? -goy : 0;
180+		sgx = (-gox > 0) ? -gox : 0;
181+		sgy = (-goy > 0) ? -goy : 0;
182 
183-		/* ending coordinates. if glyph runs over right/bottom, clamp it */
184-		int end_gx = (mw->width - gox < g->w) ? (mw->width - gox) : g->w;
185-		int end_gy = (mw->height - goy < g->h) ?(mw->height - goy) : g->h;
186+		egx = (mw->width - gox < g->w) ? (mw->width - gox) : g->w;
187+		egy = (mw->height - goy < g->h) ?(mw->height - goy) : g->h;
188 
189 		/* cull glyphs which start off screen */
190-		if (sgx >= end_gx || sgy >= end_gy) {
191+		if (sgx >= egx || sgy >= egy) {
192 			cx += g->adv;
193 			continue;
194 		}
195 
196-		/* "blit" font to framebuffer */
197-		for (int gy = sgy; gy < end_gy; gy++) {
198-			int dsty = goy + gy;
199-
200-			/* calculate row pointer once per scanline */
201-			uint32_t* row = mw->bfb + (dsty * mw->stride);
202-			int offset = gy * g->w;
203-
204-			for (int gx = sgx; gx < end_gx; gx++) {
205-				if (g->bmp[offset + gx] > 0) {
206-					int dstx = gox + gx;
207-					row[dstx] = col_up;
208-				}
209-			}
210-		}
211-
212+		glyph_to_buf(sgx, egx, sgy, egy, gox, goy, g, col_up, mw->bfb, mw->stride);
213 		cx += g->adv;
214 	}
215 }
216 
217 MausFont* maus_font_load(const char* path)
218 {
219-	FILE* fp = fopen(path, "r");
220-	if (!fp) {
221+	FILE* f = fopen(path, "r");
222+	MausFont* font = calloc(1, sizeof(MausFont));
223+	char line[1024];
224+
225+	int32_t asc = -1;
226+	int32_t dsc = -1;
227+	int32_t encoding = -1;
228+	int32_t advance = 0;
229+	int32_t bw = 0; /* bmp width */
230+	int32_t bh = 0; /* bmp height */
231+	int32_t xoff = 0;
232+	int32_t yoff = 0;
233+	int8_t seen = 0;
234+
235+	int i;
236+
237+	if (!f) {
238 		maus_log(stderr, "failed to load font \"%s\"", path);
239 		return NULL;
240 	}
241 
242-	MausFont* font = calloc(1, sizeof(MausFont));
243 	if (!font) {
244 		maus_log(stderr, "failed to calloc font");
245-		fclose(fp);
246+		fclose(f);
247 		return NULL;
248 	}
249 
250-	char line[1024];
251-	int asc = -1;
252-	int dsc = -1;
253-	int encoding = -1;
254-	int advance = 0;
255-	int bw = 0; /* bmp width */
256-	int bh = 0; /* bmp height */
257-	int xoff = 0;
258-	int yoff = 0;
259-	bool seen_any_glyph = 0;
260-
261-	while (fgets(line, sizeof(line), fp)) {
262+	while (fgets(line, sizeof(line), f)) {
263 		if (sscanf(line, "FONT_ASCENT %d", &asc) == 1)
264 			continue;
265 		if (sscanf(line, "FONT_DESCENT %d", &dsc) == 1)
266@@ -113,83 +235,14 @@ MausFont* maus_font_load(const char* path)
267 		xoff = 0;
268 		yoff = 0;
269 
270-		while (fgets(line, sizeof(line), fp)) {
271-			if (sscanf(line, "ENCODING %d", &encoding) == 1)
272-				continue;
273-			if (sscanf(line, "DWIDTH %d", &advance) == 1)
274-				continue;
275-			if (sscanf(line, "BBX %d %d %d %d", &bw, &bh, &xoff, &yoff) == 4)
276-				continue;
277-
278-			if (strncmp(line, "BITMAP", 6) == 0) {
279-				int rowbits;
280-
281-				/* invalid character code
282-				   TODO: just skip it */
283-				if (encoding < 0 || encoding >= MAUS_BDF_GLYPHS_MAX)
284-					break;
285-
286-				/* empty/invalid size */
287-				if (bw <= 0 || bh <= 0)
288-					break;
289-
290-				MausGlyph* g = &font->glyphs[encoding];
291-				free(g->bmp); /* prevent leak on hot reload */
292-				memset(g, 0, sizeof(*g));
293-
294-				g->w = bw;
295-				g->h = bh;
296-				g->xoff = xoff;
297-				g->yoff = yoff;
298-				g->adv = advance;
299-
300-				g->bmp = calloc((size_t)bw * bh, 1);
301-				if (!g->bmp) {
302-					fclose(fp);
303-					maus_font_free(font);
304-					return NULL;
305-				}
306-
307-				/* each bmp row in BDF is padded as a multiple
308-				   of 8 bits. this rounds width up to the next
309-				   multiple of 8 */
310-				rowbits = (bw + 7) & ~7;
311-
312-				for (int y = 0; y < bh; y++) {
313-					uint64_t bits;
314-
315-					/* missing row */
316-					if (!fgets(line, sizeof(line), fp)) {
317-						fclose(fp);
318-						maus_font_free(font);
319-						return NULL;
320-					}
321-
322-					bits = strtoull(line, NULL, 16); /* hex to bits */
323-					for (int x = 0; x < bw; x++) {
324-						int bit = rowbits - 1 - x;
325-
326-						if ((bits >> bit) & 1)
327-							g->bmp[y * bw + x] = 255; /* solid */
328-					}
329-				}
330-
331-				g->valid = true;
332-				if (advance > font->cellw)
333-					font->cellw = advance;
334-				seen_any_glyph = true;
335-
336-				continue;
337-			}
338-
339-			if (strncmp(line, "ENDCHAR", 7) == 0)
340-				break;
341-		}
342+		if (!parse_glyphs(f, font, line, sizeof(line), &encoding, &advance, &bw, &bh, &xoff, &yoff, &seen))
343+			return NULL;
344 	}
345 
346-	fclose(fp);
347 
348-	if (!seen_any_glyph) {
349+	fclose(f);
350+
351+	if (!seen) {
352 		free(font);
353 		return NULL;
354 	}
355@@ -199,7 +252,7 @@ MausFont* maus_font_load(const char* path)
356 		asc = 0;
357 		dsc = 0;
358 
359-		for (int i = 0; i < MAUS_BDF_GLYPHS_MAX; i++) {
360+		for (i = 0; i < MAUS_BDF_GLYPHS_MAX; i++) {
361 			MausGlyph* g = &font->glyphs[i];
362 
363 			/* unloaded glpyh */
364@@ -230,10 +283,12 @@ MausFont* maus_font_load(const char* path)
365 
366 void maus_font_free(MausFont* font)
367 {
368+	int i;
369+
370 	if (!font)
371 		return;
372 
373-	for (int i = 0; i < MAUS_BDF_GLYPHS_MAX; i++)
374+	for (i = 0; i < MAUS_BDF_GLYPHS_MAX; i++)
375 		free(font->glyphs[i].bmp);
376 
377 	free(font);
+106, -77
  1@@ -10,9 +10,9 @@ typedef struct {
  2 	MausKey maus;
  3 } KeyMapEntry;
  4 
  5-static bool fb_create(Maus* mw);
  6+static int8_t fb_create(Maus* mw);
  7 static void fb_destroy(Maus* mw);
  8-static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw);
  9+static int8_t handle_event(const MSG* msg, MausEvent* ev, Maus* mw);
 10 static MausKey vk_to_mauskey(UINT vk);
 11 static UINT resolve_lr(UINT vk, LPARAM lparam);
 12 static char translate_text(UINT vk, UINT scan);
 13@@ -38,14 +38,16 @@ static const KeyMapEntry keymap[] = {
 14 	{ VK_DIVIDE,   MAUS_KEY_KP_DIVIDE }, { VK_DECIMAL,  MAUS_KEY_KP_DECIMAL },
 15 };
 16 
 17-static bool fb_create(Maus* mw)
 18+static int8_t fb_create(Maus* mw)
 19 {
 20 	MausBackend* be = &mw->backend;
 21+	BITMAPINFO bmi = {0};
 22+	HDC dc = GetDC(NULL);
 23+
 24 	be->hbm = NULL;
 25 	mw->fb = NULL;
 26 	mw->stride = 0;
 27 
 28-	BITMAPINFO bmi = {0};
 29 	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 30 	bmi.bmiHeader.biWidth = mw->width;
 31 	bmi.bmiHeader.biHeight = -mw->height;
 32@@ -53,7 +55,6 @@ static bool fb_create(Maus* mw)
 33 	bmi.bmiHeader.biBitCount = 32;
 34 	bmi.bmiHeader.biCompression = BI_RGB;
 35 
 36-	HDC dc = GetDC(NULL);
 37 	be->memdc = CreateCompatibleDC(dc);
 38 	be->hbm = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)&mw->fb, NULL, 0);
 39 	ReleaseDC(NULL, dc);
 40@@ -62,13 +63,13 @@ static bool fb_create(Maus* mw)
 41 		if (be->memdc)
 42 			DeleteDC(be->memdc);
 43 		maus_log(stderr, "CreateDIBSection failed");
 44-		return false;
 45+		return 0;
 46 	}
 47 
 48 	SelectObject(be->memdc, be->hbm);
 49 
 50 	mw->stride = mw->width;
 51-	return true;
 52+	return 1;
 53 }
 54 
 55 static void fb_destroy(Maus* mw)
 56@@ -88,7 +89,7 @@ static void fb_destroy(Maus* mw)
 57 	mw->stride = 0;
 58 }
 59 
 60-static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
 61+static int8_t handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
 62 {
 63 	UINT scan;
 64 	UINT vk;
 65@@ -98,52 +99,52 @@ static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
 66 	switch (msg->message) {
 67 		case WM_QUIT:
 68 			ev->type = MAUS_EV_CLOSE;
 69-			return true;
 70+			return 1;
 71 
 72 		case WM_MOUSEMOVE:
 73 			ev->type = MAUS_EV_MOUSE_MOTION;
 74 			ev->mouse.motion.x = GET_X_LPARAM(msg->lParam);
 75 			ev->mouse.motion.y = GET_Y_LPARAM(msg->lParam);
 76-			return true;
 77+			return 1;
 78 
 79 		case WM_LBUTTONDOWN:
 80 			ev->type = MAUS_EV_MOUSE_BUTTON;
 81 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
 82-			ev->mouse.button.pressed = true;
 83-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = true;
 84-			return true;
 85+			ev->mouse.button.pressed = 1;
 86+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = 1;
 87+			return 1;
 88 		case WM_LBUTTONUP:
 89 			ev->type = MAUS_EV_MOUSE_BUTTON;
 90 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_LEFT;
 91-			ev->mouse.button.pressed = false;
 92-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = false;
 93-			return true;
 94+			ev->mouse.button.pressed = 0;
 95+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_LEFT] = 0;
 96+			return 1;
 97 
 98 		case WM_RBUTTONDOWN:
 99 			ev->type = MAUS_EV_MOUSE_BUTTON;
100 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
101-			ev->mouse.button.pressed = true;
102-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = true;
103-			return true;
104+			ev->mouse.button.pressed = 1;
105+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = 1;
106+			return 1;
107 		case WM_RBUTTONUP:
108 			ev->type = MAUS_EV_MOUSE_BUTTON;
109 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_RIGHT;
110-			ev->mouse.button.pressed = false;
111-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = false;
112-			return true;
113+			ev->mouse.button.pressed = 0;
114+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_RIGHT] = 0;
115+			return 1;
116 
117 		case WM_MBUTTONDOWN:
118 			ev->type = MAUS_EV_MOUSE_BUTTON;
119 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
120-			ev->mouse.button.pressed = true;
121-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = true;
122-			return true;
123+			ev->mouse.button.pressed = 1;
124+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = 1;
125+			return 1;
126 		case WM_MBUTTONUP:
127 			ev->type = MAUS_EV_MOUSE_BUTTON;
128 			ev->mouse.button.button = MAUS_MOUSE_BUTTON_MIDDLE;
129-			ev->mouse.button.pressed = false;
130-			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = false;
131-			return true;
132+			ev->mouse.button.pressed = 0;
133+			mw->mouse_buttons[MAUS_MOUSE_BUTTON_MIDDLE] = 0;
134+			return 1;
135 
136 		case WM_MOUSEWHEEL:
137 			delta = GET_WHEEL_DELTA_WPARAM(msg->wParam);
138@@ -151,8 +152,8 @@ static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
139 			                     : MAUS_MOUSE_BUTTON_SCROLL_DOWN;
140 			ev->type = MAUS_EV_MOUSE_BUTTON;
141 			ev->mouse.button.button = mbtype;
142-			ev->mouse.button.pressed = true;
143-			return true;
144+			ev->mouse.button.pressed = 1;
145+			return 1;
146 
147 		case WM_KEYDOWN:
148 		case WM_SYSKEYDOWN:
149@@ -161,15 +162,15 @@ static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
150 
151 			ev->type = MAUS_EV_KEY;
152 			ev->key.code = (uint32_t)msg->wParam;
153-			ev->key.pressed = true;
154+			ev->key.pressed = 1;
155 			ev->key.key = vk_to_mauskey(vk);
156 			ev->key.text = translate_text((UINT)msg->wParam, scan);
157 
158 			if (ev->key.code < MAUS_KEYCODE_LAST)
159-				mw->key_codes[ev->key.code] = true;
160+				mw->key_codes[ev->key.code] = 1;
161 			if (ev->key.key != MAUS_KEY_NONE)
162-				mw->key_syms[ev->key.key] = true;
163-			return true;
164+				mw->key_syms[ev->key.key] = 1;
165+			return 1;
166 
167 		case WM_KEYUP:
168 		case WM_SYSKEYUP:
169@@ -177,18 +178,18 @@ static bool handle_event(const MSG* msg, MausEvent* ev, Maus* mw)
170 
171 			ev->type = MAUS_EV_KEY;
172 			ev->key.code = (uint32_t)msg->wParam;
173-			ev->key.pressed = false;
174+			ev->key.pressed = 0;
175 			ev->key.key = vk_to_mauskey(vk);
176 			ev->key.text = 0;
177 
178 			if (ev->key.code < MAUS_KEYCODE_LAST)
179-				mw->key_codes[ev->key.code] = false;
180+				mw->key_codes[ev->key.code] = 0;
181 			if (ev->key.key != MAUS_KEY_NONE)
182-				mw->key_syms[ev->key.key] = false;
183-			return true;
184+				mw->key_syms[ev->key.key] = 0;
185+			return 1;
186 	}
187 
188-	return false;
189+	return 0;
190 }
191 
192 static MausKey vk_to_mauskey(UINT vk)
193@@ -228,11 +229,13 @@ static UINT resolve_lr(UINT vk, LPARAM lparam)
194 static char translate_text(UINT vk, UINT scan)
195 {
196 	BYTE state[256];
197+	WCHAR buf[4];
198+	int n;
199+
200+	n = ToUnicode(vk, scan, state, buf, 4, 0);
201+
202 	if (!GetKeyboardState(state))
203 		return 0;
204-
205-	WCHAR buf[4];
206-	int n = ToUnicode(vk, scan, state, buf, 4, 0);
207 	if (n == 1 && buf[0] < 0x80)
208 		return (buf[0] == '\r') ? '\n' : (char)buf[0];
209 
210@@ -241,16 +244,19 @@ static char translate_text(UINT vk, UINT scan)
211 
212 static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
213 {
214+	Maus* mw;
215+	MausBackend* be;
216+
217 	if (msg == WM_DESTROY) {
218 		PostQuitMessage(EXIT_SUCCESS);
219 		return 0;
220 	}
221 
222 	if (msg == WM_SIZE) {
223-		Maus* mw = (Maus*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
224+		mw = (Maus*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
225 		if (mw) {
226-			MausBackend* be = &mw->backend;
227-			be->resized = true;
228+			be = &mw->backend;
229+			be->resized = 1;
230 			be->rw = LOWORD(lp);
231 			be->rh = HIWORD(lp);
232 		}
233@@ -264,20 +270,27 @@ void maus_clear(Maus* mw, MausColor col)
234 {
235 	uint32_t col_up = MAUS_UNPACK_COL(col);
236 	uint32_t pxs = mw->height * mw->width;
237-	for (uint32_t i = 0; i < pxs; i++)
238+	uint32_t i;
239+
240+	for (i = 0; i < pxs; i++)
241 		mw->bfb[i] = col_up;
242 }
243 
244 void maus_clipboard_set_text(Maus* mw, const char* text)
245 {
246 	MausBackend* be = &mw->backend;
247+	size_t len = strlen(text) + 1;
248+	HGLOBAL hmem;
249+
250+	void* ptr;
251+
252 	if (!text || !OpenClipboard(be->hwnd))
253 		return;
254+
255 	EmptyClipboard();
256-	size_t len = strlen(text) + 1;
257-	HGLOBAL hmem = GlobalAlloc(GMEM_MOVEABLE, len);
258+	hmem = GlobalAlloc(GMEM_MOVEABLE, len);
259 	if (hmem) {
260-		void* ptr = GlobalLock(hmem);
261+		ptr = GlobalLock(hmem);
262 		if (ptr) {
263 			memcpy(ptr, text, len);
264 			GlobalUnlock(hmem);
265@@ -296,23 +309,28 @@ void maus_clipboard_set_text(Maus* mw, const char* text)
266 char* maus_clipboard_get_text(Maus* mw)
267 {
268 	MausBackend* be = &mw->backend;
269+	HANDLE hmem;
270+
271+	const char* text;
272+	size_t len;
273+
274 	if (!OpenClipboard(be->hwnd))
275 		return NULL;
276 
277-	HANDLE hmem = GetClipboardData(CF_TEXT);
278+	hmem = GetClipboardData(CF_TEXT);
279 	if (!hmem) {
280 		CloseClipboard();
281 		return NULL;
282 	}
283 
284-	const char* text = GlobalLock(hmem);
285+	text = GlobalLock(hmem);
286 	if (text) {
287 		if (mw->clipboard) {
288 			free(mw->clipboard);
289 			mw->clipboard = NULL;
290 		}
291 
292-		size_t len = strlen(text) + 1;
293+		len = strlen(text) + 1;
294 		mw->clipboard = malloc(len);
295 		if (mw->clipboard)
296 			memcpy(mw->clipboard, text, len);
297@@ -327,6 +345,7 @@ char* maus_clipboard_get_text(Maus* mw)
298 void maus_close(Maus* mw)
299 {
300 	MausBackend* be = &mw->backend;
301+
302 	fb_destroy(mw);
303 	if (mw->bfb) {
304 		free(mw->bfb);
305@@ -340,34 +359,35 @@ void maus_close(Maus* mw)
306 		(void) maus_close_window(mw);
307 }
308 
309-bool maus_close_window(Maus* mw)
310+int8_t maus_close_window(Maus* mw)
311 {
312 	MausBackend* be = &mw->backend;
313 
314 	if (be->hwnd) {
315 		DestroyWindow(be->hwnd);
316 		be->hwnd = NULL;
317-		return true;
318+		return 1;
319 	}
320 
321-	return false;
322+	return 0;
323 }
324 
325 
326-bool maus_create_window(Maus* mw)
327+int8_t maus_create_window(Maus* mw)
328 {
329 	MausBackend* be = &mw->backend;
330 	be->hInst = GetModuleHandle(NULL);
331-
332 	WNDCLASS wc = {0};
333+
334+	RECT r = { 0, 0, mw->width, mw->height };
335+
336 	wc.lpfnWndProc = WndProc;
337 	wc.hInstance = be->hInst;
338 	wc.lpszClassName = "MausWindow";
339 	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
340 	if (!RegisterClass(&wc))
341-		return false;
342+		return 0;
343 
344-	RECT r = { 0, 0, mw->width, mw->height };
345 	AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
346 
347 	be->hwnd = CreateWindowEx(
348@@ -378,12 +398,12 @@ bool maus_create_window(Maus* mw)
349 	);
350 
351 	if (!be->hwnd)
352-		return false;
353+		return 0;
354 
355 	SetWindowLongPtr(be->hwnd, GWLP_USERDATA, (LONG_PTR)mw);
356 	ShowWindow(be->hwnd, SW_SHOW);
357 	UpdateWindow(be->hwnd);
358-	return true;
359+	return 1;
360 }
361 
362 Maus* maus_init(const char* title, int x, int y, int width, int height)
363@@ -418,29 +438,30 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
364 	return mw;
365 }
366 
367-bool maus_event_poll(Maus* mw, MausEvent* ev)
368+int8_t maus_event_poll(Maus* mw, MausEvent* ev)
369 {
370 	MausBackend* be = &mw->backend;
371 	MSG msg;
372+
373 	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
374 		TranslateMessage(&msg);
375 		DispatchMessage(&msg);
376 		ev->type = MAUS_EV_NONE;
377 
378 		if (handle_event(&msg, ev, mw))
379-			return true;
380+			return 1;
381 	}
382 
383 	/* WM_SIZE doesnt is handled separately */
384 	if (be->resized) {
385-		be->resized = false;
386+		be->resized = 0;
387 		ev->type = MAUS_EV_RESIZE;
388 		ev->resize.width = be->rw;
389 		ev->resize.height = be->rh;
390-		return true;
391+		return 1;
392 	}
393 
394-	return false;
395+	return 0;
396 }
397 
398 void maus_event_wait(Maus* mw, MausEvent* ev)
399@@ -448,8 +469,10 @@ void maus_event_wait(Maus* mw, MausEvent* ev)
400 	MausBackend* be = &mw->backend;
401 	MSG msg;
402 
403+	int r;
404+
405 	for (;;) {
406-		int r = GetMessage(&msg, NULL, 0, 0);
407+		r = GetMessage(&msg, NULL, 0, 0);
408 		if (r <= 0) {
409 			ev->type = MAUS_EV_CLOSE;
410 			return;
411@@ -461,7 +484,7 @@ void maus_event_wait(Maus* mw, MausEvent* ev)
412 
413 		/* WM_SIZE doesnt is handled separately */
414                 if (be->resized) {
415-			be->resized = false;
416+			be->resized = 0;
417 			ev->type = MAUS_EV_RESIZE;
418 			ev->resize.width = be->rw;
419 			ev->resize.height = be->rh;
420@@ -476,22 +499,27 @@ void maus_event_wait(Maus* mw, MausEvent* ev)
421 void maus_present(Maus* mw)
422 {
423 	MausBackend* be = &mw->backend;
424+	HDC wdc;
425+
426+	uint32_t bytes;
427+
428 	if (!be->hwnd || !be->memdc)
429 		return;
430-	HDC wdc = GetDC(be->hwnd);
431 
432-	uint32_t bytes = mw->stride * mw->height * sizeof(uint32_t);
433+	wdc = GetDC(be->hwnd);
434+
435+	bytes = mw->stride * mw->height * sizeof(uint32_t);
436 	memcpy(mw->fb, mw->bfb, bytes);
437 
438 	BitBlt(wdc, 0, 0, mw->width, mw->height, be->memdc, 0, 0, SRCCOPY);
439 	ReleaseDC(be->hwnd, wdc);
440 }
441 
442-bool maus_resize(Maus* mw, uint32_t width, uint32_t height)
443+int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
444 {
445 	if (width == 0 || height == 0 ||
446-	    (mw->width == width && mw->height == height))
447-		return false;
448+	   (mw->width == width && mw->height == height))
449+		return 0;
450 
451 	fb_destroy(mw);
452 	if (mw->bfb) {
453@@ -503,13 +531,13 @@ bool maus_resize(Maus* mw, uint32_t width, uint32_t height)
454 	mw->height = height;
455 
456 	if (!fb_create(mw))
457-		return false;
458+		return 0;
459 
460 	mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
461 	if (!mw->bfb)
462-		return false;
463+		return 0;
464 
465-	return true;
466+	return 1;
467 }
468 
469 void maus_cur_set_mode(Maus* mw, MausCursorState state)
470@@ -517,6 +545,8 @@ void maus_cur_set_mode(Maus* mw, MausCursorState state)
471 	MausBackend* be = &mw->backend;
472 	HWND hwnd = be->hwnd;
473 
474+	RECT r;
475+
476 	if (!hwnd) {
477 		maus_log(stderr, "hwnd is NULL");
478 		return;
479@@ -537,7 +567,6 @@ void maus_cur_set_mode(Maus* mw, MausCursorState state)
480 
481 	/* lock cursor */
482 	if (state == MAUS_CURSOR_STATE_LOCKED) {
483-		RECT r;
484 		GetClientRect(hwnd, &r);
485 		MapWindowPoints(hwnd, NULL, (POINT*)&r, 2);
486 
+126, -90
  1@@ -1,5 +1,4 @@
  2 #include <limits.h>
  3-#include <stdbool.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <sys/shm.h>
  7@@ -21,11 +20,11 @@ typedef struct {
  8 	MausKey maus;
  9 } KeyMapEntry;
 10 
 11-static bool fb_create(Maus* mw);
 12-static bool fb_create_shm(Maus* mw);
 13-/* TODO? static bool fb_create_ximage(Maus* mw); */
 14+static int8_t fb_create(Maus* mw);
 15+static int8_t fb_create_shm(Maus* mw);
 16+/* TODO static int8_t fb_create_ximage(Maus* mw); */
 17 static void fb_destroy(Maus* mw);
 18-static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw);
 19+static int8_t handle_event(XEvent* xev, MausEvent* ev, Maus* mw);
 20 static MausKey keysym_to_mauskey(KeySym sym);
 21 static MausMouseButton mouse_button_to_maus(int btn);
 22 static int xerr(Display* dpy, XErrorEvent* ev);
 23@@ -59,11 +58,12 @@ static const KeyMapEntry keymap[] = {
 24 
 25 static int xerrored;
 26 
 27-static bool fb_create(Maus* mw)
 28+static int8_t fb_create(Maus* mw)
 29 {
 30 	MausBackend* be = &mw->backend;
 31+
 32 	be->image = NULL;
 33-	be->shmat = false;
 34+	be->shmat = 0;
 35 	be->shm.shmid = -1;
 36 	be->shm.shmaddr = NULL;
 37 	mw->fb = NULL;
 38@@ -73,43 +73,48 @@ static bool fb_create(Maus* mw)
 39 }
 40 
 41 /* allocate and store a new shm for the framebuffer */
 42-static bool fb_create_shm(Maus* mw)
 43+static int8_t fb_create_shm(Maus* mw)
 44 {
 45 	MausBackend* be = &mw->backend;
 46-	if (!XShmQueryExtension(be->display))
 47-		return false;
 48-
 49 	int scr = DefaultScreen(be->display);
 50 	int depth = DefaultDepth(be->display, scr);
 51 	Visual* vis = DefaultVisual(be->display, scr);
 52+
 53+	size_t size;
 54+	int (*old_xerr)(Display*, XErrorEvent*);
 55+
 56+	if (!XShmQueryExtension(be->display))
 57+		return 0;
 58+
 59 	if (!vis) {
 60 		maus_log(stderr, "could not get default visual");
 61-		return false;
 62+		return 0;
 63 	}
 64 
 65 	be->image = XShmCreateImage(
 66 		be->display, vis, depth, ZPixmap, NULL,
 67 		&be->shm, mw->width, mw->height
 68 	);
 69+
 70 	if (!be->image) {
 71 		maus_log(stderr, "could not create XImage (shm)");
 72-		return false;
 73+		return 0;
 74 	}
 75 
 76 	if (be->image->bits_per_pixel != 32) {
 77 		XDestroyImage(be->image);
 78 		be->image = NULL;
 79 		maus_log(stderr, "XImage not 32bpp");
 80-		return false;
 81+		return 0;
 82 	}
 83 
 84-	size_t size = be->image->bytes_per_line * be->image->height;
 85+	size = be->image->bytes_per_line * be->image->height;
 86 	be->shm.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
 87 	if (be->shm.shmid < 0) {
 88 		XDestroyImage(be->image);
 89 		be->image = NULL;
 90 		maus_log(stderr, "shmget() failed");
 91-		return false;
 92+		return 0;
 93 	}
 94 
 95 	be->shm.shmaddr = shmat(be->shm.shmid, NULL, 0);
 96@@ -118,14 +123,14 @@ static bool fb_create_shm(Maus* mw)
 97 		XDestroyImage(be->image);
 98 		be->image = NULL;
 99 		maus_log(stderr, "shmat() failed");
100-		return false;
101+		return 0;
102 	}
103 
104 	be->shm.readOnly = False;
105 	be->image->data = be->shm.shmaddr;
106 
107 	xerrored = 0;
108-	int (*old_xerr)(Display*, XErrorEvent*) = XSetErrorHandler(xerr);
109+	old_xerr = XSetErrorHandler(xerr);
110 
111 	if (!XShmAttach(be->display, &be->shm))
112 		xerrored = 1;
113@@ -142,26 +147,27 @@ static bool fb_create_shm(Maus* mw)
114 		be->shm.shmaddr = NULL;
115 		be->shm.shmid = -1;
116 		maus_log(stderr, "XShmAttach failed");
117-		return false;
118+		return 0;
119 	}
120 
121 	shmctl(be->shm.shmid, IPC_RMID, NULL);
122 
123-	be->shmat = true;
124+	be->shmat = 1;
125 	mw->fb = (uint32_t*) be->image->data;
126 	mw->stride = be->image->bytes_per_line / sizeof(uint32_t);
127 
128-	return true;
129+	return 1;
130 }
131 
132 static void fb_destroy(Maus* mw)
133 {
134 	MausBackend* be = &mw->backend;
135 	Display* dpy = be->display;
136+
137 	if (be->shmat) {
138 		XShmDetach(dpy, &be->shm);
139 		XSync(dpy, False);
140-		be->shmat = false;
141+		be->shmat = 0;
142 	}
143 
144 	if (be->image) {
145@@ -185,73 +191,82 @@ static void fb_destroy(Maus* mw)
146 	mw->stride = 0;
147 }
148 
149-static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
150+static int8_t handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
151 {
152 	MausBackend* be = &mw->backend;
153 	uint32_t code = 0;
154 	unsigned int mb;
155 	MausMouseButton mbtype;
156 
157+	char buf[8] = {0};
158+	int len;
159+
160+	KeySym sym;
161+
162+	XSelectionRequestEvent* req;
163+	XEvent rsp; /* response */
164+	Atom utf8_string;
165+	Atom clipboard;
166+
167 	switch (xev->type) {
168 		case Expose:
169 			if (xev->xexpose.count != 0)
170-				return false;
171+				return 0;
172 			ev->type = MAUS_EV_REDRAW;
173-			return true;
174+			return 1;
175 
176 		case ClientMessage:
177 			if ((Atom)xev->xclient.data.l[0] == be->atoms[MAUS_ATOM_WM_DELETE_WINDOW]) {
178 				ev->type = MAUS_EV_CLOSE;
179-				return true;
180+				return 1;
181 			}
182 			break;
183 
184 		case MappingNotify:
185 			XRefreshKeyboardMapping(&xev->xmapping);
186-			return true;
187+			return 1;
188 			break;
189 
190 		case KeyPress: {
191 			ev->type = MAUS_EV_KEY;
192 			code = xev->xkey.keycode;
193 			ev->key.code = code;
194-			ev->key.pressed = true;
195+			ev->key.pressed = 1;
196 			if (code < MAUS_KEYCODE_LAST)
197-			        mw->key_codes[code] = true;
198+			        mw->key_codes[code] = 1;
199 
200 			/* grab the raw, base sym */
201-			KeySym sym = XLookupKeysym(&xev->xkey, 0);
202+			sym = XLookupKeysym(&xev->xkey, 0);
203 			ev->key.key = keysym_to_mauskey(sym);
204 			if (ev->key.key != MAUS_KEY_NONE)
205-			        mw->key_syms[ev->key.key] = true;
206+			        mw->key_syms[ev->key.key] = 1;
207 
208-			char buf[8] = {0};
209-			int len = XLookupString(&xev->xkey, buf, sizeof(buf), NULL, NULL);
210+			len = XLookupString(&xev->xkey, buf, sizeof(buf), NULL, NULL);
211 			if (len > 0)
212-			        ev->key.text = (buf[0] == '\r') ? '\n' : buf[0];
213+				ev->key.text = (buf[0] == '\r') ? '\n' : buf[0];
214 			else
215-			        ev->key.text = 0;
216+				ev->key.text = 0;
217 
218-			return true;
219+			return 1;
220 		}
221 
222 		case KeyRelease: {
223 			ev->type = MAUS_EV_KEY;
224 			code = xev->xkey.keycode;
225 			ev->key.code = code;
226-			ev->key.pressed = false;
227+			ev->key.pressed = 0;
228 			ev->key.text = 0;
229 
230 			if (code < MAUS_KEYCODE_LAST)
231-			        mw->key_codes[code] = false;
232+			        mw->key_codes[code] = 0;
233 
234 			/* unset base sym set on `KeyPress` */
235-			KeySym sym = XLookupKeysym(&xev->xkey, 0);
236+			sym = XLookupKeysym(&xev->xkey, 0);
237 			ev->key.key = keysym_to_mauskey(sym);
238 			if (ev->key.key != MAUS_KEY_NONE)
239-			        mw->key_syms[ev->key.key] = false;
240+			        mw->key_syms[ev->key.key] = 0;
241 
242-			return true;
243+			return 1;
244 		}
245 
246 		case ButtonPress:
247@@ -259,37 +274,36 @@ static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
248 			mb = xev->xbutton.button;
249 			mbtype = mouse_button_to_maus(mb);
250 			ev->mouse.button.button = mbtype;
251-			ev->mouse.button.pressed = true;
252-			mw->mouse_buttons[mbtype] = true;
253-			return true;
254+			ev->mouse.button.pressed = 1;
255+			mw->mouse_buttons[mbtype] = 1;
256+			return 1;
257 
258 		case ButtonRelease:
259 			ev->type = MAUS_EV_MOUSE_BUTTON;
260 			mb = xev->xbutton.button;
261 			mbtype = mouse_button_to_maus(mb);
262 			ev->mouse.button.button = mbtype;
263-			ev->mouse.button.pressed = false;
264-			mw->mouse_buttons[mbtype] = false;
265-			return true;
266+			ev->mouse.button.pressed = 0;
267+			mw->mouse_buttons[mbtype] = 0;
268+			return 1;
269 
270 		case MotionNotify:
271 			ev->type = MAUS_EV_MOUSE_MOTION;
272 			ev->mouse.motion.x = xev->xmotion.x;
273 			ev->mouse.motion.y = xev->xmotion.y;
274-			return true;
275+			return 1;
276 
277 		case ConfigureNotify:
278 			ev->type = MAUS_EV_RESIZE;
279 			ev->resize.width = xev->xconfigure.width;
280 			ev->resize.height = xev->xconfigure.height;
281-			return true;
282+			return 1;
283 
284 		case SelectionRequest: {
285-			XSelectionRequestEvent* req = &xev->xselectionrequest;
286-			XEvent rsp; /* response */
287+			req = &xev->xselectionrequest;
288 
289-			Atom utf8_string = XInternAtom(be->display, "UTF8_STRING", False);
290-			Atom clipboard = XInternAtom(be->display, "CLIPBOARD", False);
291+			utf8_string = XInternAtom(be->display, "UTF8_STRING", False);
292+			clipboard = XInternAtom(be->display, "CLIPBOARD", False);
293 
294 			rsp.type = SelectionNotify;
295 			rsp.xselection.display = req->display;
296@@ -317,15 +331,17 @@ static bool handle_event(XEvent* xev, MausEvent* ev, Maus* mw)
297 			XSendEvent(req->display, req->requestor, False, 0, &rsp);
298 			XFlush(be->display);
299 
300-			return false; /* skip maus polling it */
301+			return 0; /* skip maus polling it */
302 		}
303 	}
304 
305-	return false;
306+	return 0;
307 }
308 
309 static MausKey keysym_to_mauskey(KeySym sym)
310 {
311+	size_t i;
312+
313 	if (sym >= 0x20 && sym <= 0x7E)
314 		return (MausKey)sym;
315 
316@@ -334,7 +350,7 @@ static MausKey keysym_to_mauskey(KeySym sym)
317 	if (sym >= XK_KP_0 && sym <= XK_KP_9)
318 		return MAUS_KEY_KP_0 + (sym - XK_KP_0);
319 
320-	for (size_t i = 0; i < sizeof(keymap)/ sizeof(keymap[0]); i++) {
321+	for (i = 0; i < sizeof(keymap)/ sizeof(keymap[0]); i++) {
322 		if (keymap[i].x11 == sym)
323 			return keymap[i].maus;
324 	}
325@@ -365,6 +381,8 @@ static int xerr(Display* dpy, XErrorEvent* ev)
326 void maus_clipboard_set_text(Maus* mw, const char* text)
327 {
328 	MausBackend* be = &mw->backend;
329+	Atom clipboard;
330+
331 	if (!be->display || be->win == None)
332 		return;
333 
334@@ -377,7 +395,7 @@ void maus_clipboard_set_text(Maus* mw, const char* text)
335 	if (text)
336 		mw->clipboard = maus_strdup(text);
337 
338-	Atom clipboard = XInternAtom(be->display, "CLIPBOARD", False);
339+	clipboard = XInternAtom(be->display, "CLIPBOARD", False);
340 	XSetSelectionOwner(be->display, clipboard, be->win, CurrentTime);
341 	XFlush(be->display);
342 }
343@@ -389,6 +407,19 @@ char* maus_clipboard_get_text(Maus* mw)
344 	Atom utf8_string = XInternAtom(be->display, "UTF8_STRING", False);
345 	Atom maus_clipboard_prop = XInternAtom(be->display, "MAUS_CLIPBOARD_PROP", False);
346 
347+	XEvent xev;
348+	int8_t ok = 0;
349+
350+	int timeout;
351+
352+	Atom actual_type;
353+	int actual_fmt;
354+	unsigned long nitems;
355+	unsigned long bytes_after;
356+	unsigned char* prop_data = NULL;
357+
358+	char* res = NULL;
359+
360 	/* fetch clipboard data to `maus_clipboard_prop`
361 	   window property */
362 	XConvertSelection(
363@@ -398,12 +429,10 @@ char* maus_clipboard_get_text(Maus* mw)
364 	XFlush(be->display);
365 
366 	/* check for selection response */
367-	XEvent xev;
368-	bool ok = false;
369-	for (int timeout = 0; timeout < 10000; timeout++) { 
370+	for (timeout = 0; timeout < 10000; timeout++) { 
371 		if (XCheckTypedWindowEvent(be->display, be->win, SelectionNotify, &xev)) {
372 			if (xev.xselection.property != None)
373-				ok = true;
374+				ok = 1;
375 			break;
376 		}
377 	}
378@@ -411,18 +440,12 @@ char* maus_clipboard_get_text(Maus* mw)
379 		return NULL;
380 
381 	/* read string off property */
382-	Atom actual_type;
383-	int actual_fmt;
384-	unsigned long nitems;
385-	unsigned long bytes_after;
386-	unsigned char* prop_data = NULL;
387 	XGetWindowProperty(
388 		be->display, be->win, maus_clipboard_prop, 0,LONG_MAX,
389 		True, utf8_string, &actual_type, &actual_fmt, &nitems,
390 		&bytes_after, &prop_data
391 	);
392 
393-	char* res = NULL;
394 	if (prop_data) {
395 		res = maus_strdup((char*)prop_data);
396 		XFree(prop_data);
397@@ -434,6 +457,7 @@ char* maus_clipboard_get_text(Maus* mw)
398 void maus_close(Maus* mw)
399 {
400 	MausBackend* be = &mw->backend;
401+
402 	fb_destroy(mw);
403 	if (mw->bfb) {
404 		free(mw->bfb);
405@@ -450,9 +474,10 @@ void maus_close(Maus* mw)
406 		XCloseDisplay(be->display);
407 }
408 
409-bool maus_close_window(Maus* mw)
410+int8_t maus_close_window(Maus* mw)
411 {
412 	MausBackend* be = &mw->backend;
413+
414 	if (be->gc) {
415 		XFreeGC(be->display, be->gc);
416 		be->gc = 0;
417@@ -463,10 +488,10 @@ bool maus_close_window(Maus* mw)
418 		XDestroyWindow(be->display, be->win);
419 	}
420 
421-	return true;
422+	return 1;
423 }
424 
425-bool maus_create_window(Maus* mw)
426+int8_t maus_create_window(Maus* mw)
427 {
428 	MausBackend* be = &mw->backend;
429 	Display* dpy = be->display;
430@@ -480,12 +505,13 @@ bool maus_create_window(Maus* mw)
431 	);
432 
433 	if (*win == None)
434-		return false;
435+		return 0;
436 
437 	XSelectInput(dpy, *win,
438 		ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
439 		ButtonReleaseMask | PointerMotionMask | StructureNotifyMask
440 	);
441+
442 	/* no black flashing when resizing */
443 	XSetWindowBackgroundPixmap(dpy, *win, None);
444 
445@@ -502,33 +528,35 @@ bool maus_create_window(Maus* mw)
446 	if (!be->gc) {
447 		maus_log(stderr, "failed to create window GC");
448 		maus_close_window(mw);
449-		return false;
450+		return 0;
451 	}
452 
453-	return true;
454+	return 1;
455 }
456 
457 void maus_clear(Maus* mw, MausColor col)
458 {
459 	uint32_t col_up = MAUS_UNPACK_COL(col);
460 	uint32_t pxs = mw->height * mw->width;
461-	for (uint32_t i = 0; i < pxs; i++)
462+	uint32_t i;
463+	for (i = 0; i < pxs; i++)
464 		mw->bfb[i] = col_up;
465 }
466 
467 Maus* maus_init(const char* title, int x, int y, int width, int height)
468 {
469+	Display* d = XOpenDisplay(NULL);
470+	Maus* mw = calloc(1, sizeof(Maus));
471+	MausBackend* be = &mw->backend;
472+
473 	if (MAUS_WARN_BACKEND_AUTO_SEL)
474 		maus_log(stderr, "backend auto-selected: X11");
475 
476-	Display* d = XOpenDisplay(NULL);
477 	if (!d) {
478 		maus_die("failed to open X11 display");
479 		return NULL;
480 	}
481 
482-	Maus* mw = calloc(1, sizeof(Maus));
483-	MausBackend* be = &mw->backend;
484 	be->display = d;
485 	be->root = DefaultRootWindow(d);
486 	be->win = None;
487@@ -542,7 +570,7 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
488 
489 	be->gc = 0;
490 	be->image = NULL;
491-	be->shmat = false;
492+	be->shmat = 0;
493 	be->shm.shmid = -1;
494 	be->shm.shmaddr = NULL;
495 	if (!fb_create(mw)) {
496@@ -562,25 +590,27 @@ Maus* maus_init(const char* title, int x, int y, int width, int height)
497 	return mw;
498 }
499 
500-bool maus_event_poll(Maus* mw, MausEvent* ev)
501+int8_t maus_event_poll(Maus* mw, MausEvent* ev)
502 {
503 	MausBackend* be = &mw->backend;
504 	XEvent xev;
505+
506 	while (XPending(be->display)) {
507 		XNextEvent(be->display, &xev);
508 		ev->type = MAUS_EV_NONE;
509 		if (handle_event(&xev, ev, mw))
510-			return true;
511+			return 1;
512 
513 	}
514 
515-	return false;
516+	return 0;
517 }
518 
519 void maus_event_wait(Maus* mw, MausEvent* ev)
520 {
521 	MausBackend* be = &mw->backend;
522 	XEvent xev;
523+
524 	for (;;) {
525 		XNextEvent(be->display, &xev);
526 		ev->type = MAUS_EV_NONE;
527@@ -592,10 +622,12 @@ void maus_event_wait(Maus* mw, MausEvent* ev)
528 void maus_present(Maus* mw)
529 {
530 	MausBackend* be = &mw->backend;
531+	uint32_t bytes;
532+
533 	if (!be->image || be->win == None)
534 		return;
535 
536-	uint32_t bytes = mw->stride * mw->height * sizeof(uint32_t);
537+	bytes = mw->stride * mw->height * sizeof(uint32_t);
538 	memcpy(mw->fb, mw->bfb, bytes);
539 
540 	XShmPutImage(
541@@ -606,12 +638,13 @@ void maus_present(Maus* mw)
542 	XFlush(be->display);
543 }
544 
545-bool maus_resize(Maus* mw, uint32_t width, uint32_t height)
546+int8_t maus_resize(Maus* mw, uint32_t width, uint32_t height)
547 {
548 	MausBackend* be = &mw->backend;
549+
550 	if (width == 0 || height == 0 ||
551 	    (mw->width == width && mw->height == height))
552-		return false;
553+		return 0;
554 
555 	fb_destroy(mw);
556 	if (mw->bfb) {
557@@ -626,13 +659,13 @@ bool maus_resize(Maus* mw, uint32_t width, uint32_t height)
558 	XFlush(be->display);
559 
560 	if (!fb_create(mw))
561-		return false;
562+		return 0;
563 
564 	mw->bfb = calloc(mw->stride * mw->height, sizeof(uint32_t));
565 	if (!mw->bfb)
566-		return false;
567+		return 0;
568 
569-	return true;
570+	return 1;
571 }
572 
573 void maus_cur_set_mode(Maus* mw, MausCursorState state)
574@@ -641,6 +674,9 @@ void maus_cur_set_mode(Maus* mw, MausCursorState state)
575 	Display* dpy = be->display;
576 	Window win = be->win;
577 
578+	Mask mask;
579+	int grab;
580+
581 	if (!dpy) {
582 		maus_log(stderr, "display is NULL");
583 		return;
584@@ -660,7 +696,7 @@ void maus_cur_set_mode(Maus* mw, MausCursorState state)
585 	/* hide cursor */
586 	if (state == MAUS_CURSOR_STATE_HIDDEN) {
587 		Pixmap blank_pm = XCreatePixmap(dpy, win, 1, 1, 1);
588-		XColor black = {.red=0, .green=0, .blue=0};
589+		XColor black = {0, 0, 0, 0, 0, 0};
590 		Cursor blank_cur = XCreatePixmapCursor(
591 			dpy, blank_pm, blank_pm, &black, &black, 0, 0
592 		);
593@@ -674,8 +710,8 @@ void maus_cur_set_mode(Maus* mw, MausCursorState state)
594 
595 	/* lock cursor */
596 	if (state == MAUS_CURSOR_STATE_LOCKED) {
597-		Mask mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
598-		int grab = XGrabPointer(
599+		mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
600+		grab = XGrabPointer(
601 			dpy, win, True, mask, GrabModeAsync,
602 			GrabModeAsync, win, None, CurrentTime
603 		);
+4, -2
 1@@ -5,11 +5,13 @@
 2 
 3 char* maus_strdup(const char* src)
 4 {
 5+	size_t len;
 6+	char* dst;
 7 	if (src == NULL)
 8 		return NULL;
 9 
10-	size_t len = strlen(src);
11-	char* dst = malloc(len + 1);
12+	len = strlen(src);
13+	dst = malloc(len + 1);
14 	if (dst == NULL)
15 		return NULL;
16