commit 7dac53a708dd3625c7aa43f97a79ff0ef94158e3
parent f452a00a4143a913e61a395cf9e4b8728fa0a7a6
Author: lumidify <nobody@lumidify.org>
Date:   Fri, 19 Feb 2021 22:43:45 +0100
Add wrapper for memory allocation
Diffstat:
| M | Makefile |  |  | 4 | ++-- | 
| M | box.c |  |  | 15 | ++++++--------- | 
| M | button.c |  |  | 8 | ++++---- | 
| M | config.mk |  |  | 2 | +- | 
| M | draw.c |  |  | 10 | +++++----- | 
| M | grid.c |  |  | 37 | ++++++++++++++++++------------------- | 
| M | label.c |  |  | 8 | ++++---- | 
| M | ltkd.c |  |  | 39 | +++++++++++++++++---------------------- | 
| A | memory.c |  |  | 71 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| A | memory.h |  |  | 34 | ++++++++++++++++++++++++++++++++++ | 
| M | scrollbar.c |  |  | 7 | +++---- | 
| D | text_line.c |  |  | 143 | ------------------------------------------------------------------------------- | 
| D | text_line.h |  |  | 52 | ---------------------------------------------------- | 
| M | text_pango.c |  |  | 11 | ++++++----- | 
| M | text_stb.c |  |  | 34 | +++++++++++++++------------------- | 
15 files changed, 186 insertions(+), 289 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
 include config.mk
 
-OBJ += color.o util.o ltkd.o ini.o grid.o box.o scrollbar.o button.o label.o draw.o
+OBJ += memory.o color.o util.o ltkd.o ini.o grid.o box.o scrollbar.o button.o label.o draw.o
 
 all: ltkd ltkc
 
@@ -16,4 +16,4 @@ ltkc: ltkc.o util.o
 .PHONY: clean
 
 clean:
-	rm -f $(OBJ) ltkc.o ltkd ltkc ltk.sock *.core
+	rm -f *.o ltkd ltkc ltk.sock *.core
diff --git a/box.c b/box.c
@@ -29,6 +29,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -88,9 +89,7 @@ ltk_box_draw(ltk_box *box, ltk_rect clip) {
 
 static ltk_box *
 ltk_box_create(ltk_window *window, const char *id, ltk_orientation orient) {
-	ltk_box *box = malloc(sizeof(ltk_box));
-	if (!box)
-		ltk_fatal("Unable to allocate memory for box.\n");
+	ltk_box *box = ltk_malloc(sizeof(ltk_box), "ltk_box_create");
 
 	ltk_fill_widget_defaults(&box->widget, id, window, <k_box_draw,
 	    NULL, <k_box_destroy, 0, LTK_BOX);
@@ -119,11 +118,11 @@ ltk_box_destroy(ltk_box *box, int shallow) {
 			ptr->destroy(ptr, shallow);
 		}
 	}
-	free(box->widgets);
+	ltk_free(box->widgets);
 	ltk_remove_widget(box->widget.window, box->widget.id);
-	free(box->widget.id);
+	ltk_free(box->widget.id);
 	box->sc->widget.destroy(box->sc, 0);
-	free(box);
+	ltk_free(box);
 }
 
 /* FIXME: Make this function name more consistent */
@@ -224,9 +223,7 @@ ltk_box_add(ltk_window *window, ltk_widget *widget, ltk_box *box, unsigned short
 	}
 	if (box->num_widgets >= box->num_alloc) {
 		size_t new_size = box->num_alloc > 0 ? box->num_alloc * 2 : 4;
-		ltk_widget **new = realloc(box->widgets, new_size * sizeof(ltk_widget *));
-		if (!new)
-			ltk_fatal_errno("Unable to allocate memory for widgets in box.\n");
+		ltk_widget **new = ltk_realloc(box->widgets, new_size * sizeof(ltk_widget *), "ltk_box_add");
 		box->num_alloc = new_size;
 		box->widgets = new;
 	}
diff --git a/button.c b/button.c
@@ -30,6 +30,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -236,8 +237,7 @@ ltk_button_mouse_release(ltk_button *button, XEvent event) {
 static ltk_button *
 ltk_button_create(ltk_window *window, const char *id, const char *text) {
 	char *text_copy;
-	ltk_button *button = malloc(sizeof(ltk_button));
-	if (!button) ltk_fatal_errno("Unable to allocate memory for ltk_button.\n");
+	ltk_button *button = ltk_malloc(sizeof(ltk_button), "ltk_button_create");
 
 	ltk_fill_widget_defaults(&button->widget, id, window,
 	    <k_button_draw, <k_button_change_state, <k_button_destroy, 1, LTK_BUTTON);
@@ -268,8 +268,8 @@ ltk_button_destroy(ltk_button *button, int shallow) {
 	}
 	ltk_text_line_destroy(button->tl);
 	ltk_remove_widget(button->widget.window, button->widget.id);
-	free(button->widget.id);
-	free(button);
+	ltk_free(button->widget.id);
+	ltk_free(button);
 }
 
 /* button <button id> create <text> */
diff --git a/config.mk b/config.mk
@@ -1,6 +1,6 @@
 VERSION = -999
 
-CFLAGS = -D_POSIX_C_SOURCE=200809L -g -std=c99 -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 fontconfig` -pedantic
+CFLAGS = -DDEBUG -D_POSIX_C_SOURCE=200809L -g -std=c99 -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 fontconfig` -pedantic
 LDFLAGS = -lm `pkg-config --libs x11 fontconfig`
 # Comment when enabling pango rendering:
 OBJ = stb_truetype.o text_stb.o
diff --git a/draw.c b/draw.c
@@ -30,6 +30,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -80,8 +81,7 @@ ltk_draw_draw(ltk_draw *draw) {
 
 static ltk_draw *
 ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *color) {
-	ltk_draw *draw = malloc(sizeof(ltk_draw));
-	if (!draw) ltk_fatal_errno("Unable to allocate memory for ltk_draw.\n");
+	ltk_draw *draw = ltk_malloc(sizeof(ltk_draw), ltk_draw_create);
 
 	ltk_fill_widget_defaults(&draw->widget, id, window,
 	    <k_draw_draw, NULL, <k_draw_destroy, 1, LTK_DRAW);
@@ -90,7 +90,7 @@ ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *co
 	draw->widget.rect.h = h;
 	draw->pix = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth);
 	if (!ltk_create_xcolor(window, color, &draw->bg)) {
-		free(draw);
+		ltk_free(draw);
 		ltk_fatal_errno("Unable to allocate XColor.\n");
 	}
 	draw->fg = draw->bg;
@@ -130,9 +130,9 @@ ltk_draw_destroy(ltk_draw *draw, int shallow) {
 		return;
 	}
 	ltk_remove_widget(draw->widget.window, draw->widget.id);
-	free(draw->widget.id);
+	ltk_free(draw->widget.id);
 	XFreePixmap(draw->widget.window->dpy, draw->pix);
-	free(draw);
+	ltk_free(draw);
 }
 
 static void
diff --git a/grid.c b/grid.c
@@ -36,6 +36,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -109,9 +110,7 @@ ltk_grid_draw(ltk_grid *grid, ltk_rect clip) {
 
 static ltk_grid *
 ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) {
-	ltk_grid *grid = malloc(sizeof(ltk_grid));
-	if (!grid)
-		ltk_fatal("Unable to allocate memory for grid.\n");
+	ltk_grid *grid = ltk_malloc(sizeof(ltk_grid), "ltk_grid_create");
 
 	ltk_fill_widget_defaults(&grid->widget, id, window, <k_grid_draw,
 	    NULL, <k_grid_destroy, 0, LTK_GRID);
@@ -124,14 +123,14 @@ ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) {
 
 	grid->rows = rows;
 	grid->columns = columns;
-	grid->widget_grid = malloc(rows * columns * sizeof(ltk_widget));
-	grid->row_heights = malloc(rows * sizeof(int));
-	grid->column_widths = malloc(rows * sizeof(int));
-	grid->row_weights = malloc(rows * sizeof(int));
-	grid->column_weights = malloc(columns * sizeof(int));
+	grid->widget_grid = ltk_malloc(rows * columns * sizeof(ltk_widget), "ltk_grid_create");
+	grid->row_heights = ltk_malloc(rows * sizeof(int), "ltk_grid_create");
+	grid->column_widths = ltk_malloc(rows * sizeof(int), "ltk_grid_create");
+	grid->row_weights = ltk_malloc(rows * sizeof(int), "ltk_grid_create");
+	grid->column_weights = ltk_malloc(columns * sizeof(int), "ltk_grid_create");
 	/* Positions have one extra for the end */
-	grid->row_pos = malloc((rows + 1) * sizeof(int));
-	grid->column_pos = malloc((columns + 1) * sizeof(int));
+	grid->row_pos = ltk_malloc((rows + 1) * sizeof(int), "ltk_grid_create");
+	grid->column_pos = ltk_malloc((columns + 1) * sizeof(int), "ltk_grid_create");
 	/* FIXME: wow, that's horrible, this should just use memset */
 	int i;
 	for (i = 0; i < rows; i++) {
@@ -172,16 +171,16 @@ ltk_grid_destroy(ltk_grid *grid, int shallow) {
 			}
 		}
 	}
-	free(grid->widget_grid);
-	free(grid->row_heights);
-	free(grid->column_widths);
-	free(grid->row_weights);
-	free(grid->column_weights);
-	free(grid->row_pos);
-	free(grid->column_pos);
+	ltk_free(grid->widget_grid);
+	ltk_free(grid->row_heights);
+	ltk_free(grid->column_widths);
+	ltk_free(grid->row_weights);
+	ltk_free(grid->column_weights);
+	ltk_free(grid->row_pos);
+	ltk_free(grid->column_pos);
 	ltk_remove_widget(grid->widget.window, grid->widget.id);
-	free(grid->widget.id);
-	free(grid);
+	ltk_free(grid->widget.id);
+	ltk_free(grid);
 }
 
 static void
diff --git a/label.c b/label.c
@@ -30,6 +30,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -94,8 +95,7 @@ ltk_label_draw(ltk_label *label, ltk_rect clip) {
 static ltk_label *
 ltk_label_create(ltk_window *window, const char *id, const char *text) {
 	char *text_copy;
-	ltk_label *label = malloc(sizeof(ltk_label));
-	if (!label) ltk_fatal_errno("Unable to allocate memory for ltk_label.\n");
+	ltk_label *label = ltk_malloc(sizeof(ltk_label), "ltk_label_create");
 
 	ltk_fill_widget_defaults(&label->widget, id, window,
 	    <k_label_draw, NULL, <k_label_destroy, 1, LTK_LABEL);
@@ -126,8 +126,8 @@ ltk_label_destroy(ltk_label *label, int shallow) {
 	}
 	ltk_text_line_destroy(label->tl);
 	ltk_remove_widget(label->widget.window, label->widget.id);
-	free(label->widget.id);
-	free(label);
+	ltk_free(label->widget.id);
+	ltk_free(label);
 }
 
 /* label <label id> create <text> */
diff --git a/ltkd.c b/ltkd.c
@@ -47,6 +47,7 @@
 #include "ini.h"
 #include "khash.h"
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -257,10 +258,10 @@ ltk_mainloop(ltk_window *window) {
 							ltk_fatal_errno("Unable to queue event.\n");
 					}
 				}
-				free(cur->data);
+				ltk_free(cur->data);
 				last = cur;
 				cur = cur->prev;
-				free(last);
+				ltk_free(last);
 			} while (cur);
 			window->first_event = window->last_event = NULL;
 		} 
@@ -324,9 +325,7 @@ get_sock_path(char *basedir, Window id) {
 
 	len = strlen(basedir);
 	/* FIXME: MAKE SURE THIS IS ACTUALLY BIG ENOUGH! */
-	path = malloc(len + 20);
-	if (!path)
-		return NULL;
+	path = ltk_malloc(len + 20, "get_sock_path");
 	/* FIXME: also check for less than 0 */
 	if (snprintf(path, len + 20, "%s/%d.sock", basedir, id) >= len + 20)
 		ltk_fatal("Tell lumidify to fix his code.\n");
@@ -345,10 +344,10 @@ open_log(char *dir) {
 		return NULL;
 	f = fopen(path, "a");
 	if (!f) {
-		free(path);
+		ltk_free(path);
 		return NULL;
 	}
-	free(path);
+	ltk_free(path);
 
 	return f;
 }
@@ -358,23 +357,23 @@ ltk_cleanup(void) {
 	if (listenfd >= 0)
 		close(listenfd);
 	if (ltk_dir)
-		free(ltk_dir);
+		ltk_free(ltk_dir);
 	if (ltk_logfile)
 		fclose(ltk_logfile);
 	if (sock_path) {
 		unlink(sock_path);
-		free(sock_path);
+		ltk_free(sock_path);
 	}
 
 	for (int i = 0; i < MAX_SOCK_CONNS; i++) {
 		if (sockets[i].fd >= 0)
 			close(sockets[i].fd);
 		if (sockets[i].read)
-			free(sockets[i].read);
+			ltk_free(sockets[i].read);
 		if (sockets[i].to_write)
-			free(sockets[i].to_write);
+			ltk_free(sockets[i].to_write);
 		if (sockets[i].tokens.tokens)
-			free(sockets[i].tokens.tokens);
+			ltk_free(sockets[i].tokens.tokens);
 	}
 
 	if (widget_hash)
@@ -515,13 +514,11 @@ ltk_create_xcolor(ltk_window *window, const char *hex, XColor *col) {
 void
 ltk_queue_event(ltk_window *window, ltk_event_type type, const char *id, const char *data) {
 	/* FIXME: make it nicer and safer */
-	struct ltk_event_queue *new = malloc(sizeof(struct ltk_event_queue));
-	if (!new) ltk_fatal_errno("Unable to queue event.\n");
+	struct ltk_event_queue *new = ltk_malloc(sizeof(struct ltk_event_queue), "ltk_queue_event");
 	new->event_type = type;
 	int id_len = strlen(id);
 	int data_len = strlen(data);
-	new->data = malloc(id_len + data_len + 3);
-	if (!new->data) ltk_fatal_errno("Unable to queue event.\n");
+	new->data = ltk_malloc(id_len + data_len + 3, "ltk_queue_event");
 	strcpy(new->data, id);
 	new->data[id_len] = ' ';
 	strcpy(new->data + id_len + 1, data);
@@ -588,9 +585,7 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int 
 	char *theme_path;
 	XWindowAttributes attrs;
 
-	ltk_window *window = malloc(sizeof(ltk_window));
-	if (!window)
-		ltk_fatal_errno("Not enough memory left for window!\n");
+	ltk_window *window = ltk_malloc(sizeof(ltk_window), "ltk_create_window");
 
 	window->dpy = XOpenDisplay(NULL);
 	window->screen = DefaultScreen(window->dpy);
@@ -665,8 +660,8 @@ ltk_destroy_window(ltk_window *window) {
 	/* FIXME: This doesn't work because it can sometimes be a readonly
 	   string from ltk_window_setup_theme_defaults! */
 	if (window->theme.font)
-		free(window->theme.font);
-	free(window);
+		ltk_free(window->theme.font);
+	ltk_free(window);
 }
 
 void
@@ -962,7 +957,7 @@ push_token(struct token_list *tl, char *token) {
 	if (tl->num_tokens >= tl->num_alloc) {
 		new_size = (tl->num_alloc * 2) > (tl->num_tokens + 1) ?
 			   (tl->num_alloc * 2) : (tl->num_tokens + 1);
-		char **new = realloc(tl->tokens, new_size * sizeof(char *));
+		char **new = ltk_realloc(tl->tokens, new_size * sizeof(char *), "push_token");
 		if (!new) return -1;
 		tl->tokens = new;
 		tl->num_alloc = new_size;
diff --git a/memory.c b/memory.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the Lumidify ToolKit (LTK)
+ * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdarg.h>
+#include "color.h"
+#include "ltk.h"
+
+void *
+ltk_malloc(size_t size, const char *caller) {
+	void *ptr = malloc(size);
+	if (!ptr)
+		ltk_fatal("%s: out of memory.\n", caller);
+	#ifdef DEBUG
+	fprintf(stderr, "DEBUG: malloc: address %p, %zu bytes.\n", ptr, size);
+	#endif
+	return ptr;
+}
+
+void *
+ltk_calloc(size_t nmemb, size_t size, const char *caller) {
+	void *ptr = calloc(nmemb, size);
+	if (!ptr)
+		ltk_fatal("%s: out of memory.\n", caller);
+	#ifdef DEBUG
+	fprintf(stderr, "DEBUG: calloc: address %p, %zu bytes.\n", ptr, size);
+	#endif
+	return ptr;
+}
+
+void *
+ltk_realloc(void *ptr, size_t size, const char *caller) {
+	void *new_ptr = realloc(ptr, size);
+	if (!new_ptr)
+		ltk_fatal("%s: out of memory.\n", caller);
+	#ifdef DEBUG
+	fprintf(stderr, "DEBUG: realloc: old %p, new %p, %zu bytes.\n", ptr, new_ptr, size);
+	#endif
+	return new_ptr;
+}
+
+void
+ltk_free(void *ptr) {
+	#ifdef DEBUG
+	fprintf(stderr, "DEBUG: free: address %p\n", ptr);
+	#endif
+	free(ptr);
+}
diff --git a/memory.h b/memory.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the Lumidify ToolKit (LTK)
+ * Copyright (c) 2021 lumidify <nobody@lumidify.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _LTK_MEMORY_H_
+#define _LTK_MEMORY_H_
+
+/* FIXME: Move ltk_warn, etc. to util.* */
+
+void *ltk_malloc(size_t size, const char *caller);
+void *ltk_calloc(size_t nmemb, size_t size, const char *caller);
+void *ltk_realloc(void *ptr, size_t size, const char *caller);
+void ltk_free(void *ptr);
+
+#endif /* _LTK_MEMORY_H_ */
diff --git a/scrollbar.c b/scrollbar.c
@@ -30,6 +30,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -221,9 +222,7 @@ ltk_scrollbar_motion_notify(ltk_scrollbar *sc, XEvent event) {
 
 ltk_scrollbar *
 ltk_scrollbar_create(ltk_window *window, ltk_orientation orient, void (*callback)(void *), void *data) {
-	ltk_scrollbar *sc = malloc(sizeof(ltk_scrollbar));
-	if (!sc)
-		ltk_fatal_errno("Unable to allocate memory for scrollbar.\n");
+	ltk_scrollbar *sc = ltk_malloc(sizeof(ltk_scrollbar), "ltk_scrollbar_create");
 	ltk_fill_widget_defaults(sc, NULL, window, <k_scrollbar_draw,
 	    NULL, <k_scrollbar_destroy, 1, LTK_UNKNOWN);
 	sc->last_mouse_x = sc->last_mouse_y = 0;
@@ -245,5 +244,5 @@ ltk_scrollbar_create(ltk_window *window, ltk_orientation orient, void (*callback
 
 static void
 ltk_scrollbar_destroy(ltk_scrollbar *scrollbar, int shallow) {
-	free(scrollbar);
+	ltk_free(scrollbar);
 }
diff --git a/text_line.c b/text_line.c
@@ -1,143 +0,0 @@
-/*
- * This file is part of the Lumidify ToolKit (LTK)
- * Copyright (c) 2020 lumidify <nobody@lumidify.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "text_common.h"
-#include "text_line.h"
-#include "util.h"
-
-void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm);
-void ltk_cleanup_text(void);
-
-LtkTextLine *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width);
-void ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg);
-void ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip);
-void ltk_text_line_set_width(LtkTextLine *tl, int width);
-void ltk_text_line_get_size(LtkTextLine *tl, int *w, int *h);
-void ltk_text_line_destroy(LtkTextLine *tl);
-
-static void ltk_text_line_create_glyphs(struct ltk_text_line *tl);
-static void ltk_text_line_draw_glyph(ltk_glyph *glyph, int xoff, int yoff,
-    XImage *img, XColor fg);
-static XImage *ltk_create_ximage(Display *dpy, int w, int h, int depth,
-    XColor bg);
-
-static XImage *
-ltk_create_ximage(Display *dpy, int w, int h, int depth, XColor bg) {
-	XImage *img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, w, h, 32, 0);
-	img->data = calloc(img->bytes_per_line, img->height);
-	XInitImage(img);
-
-	int b;
-	for (int i = 0; i < h; i++) {
-		b = img->bytes_per_line * i;
-		for (int j = 0; j < w; j++) {
-			img->data[b++] = bg.blue / 257;
-			img->data[b++] = bg.green / 257;
-			img->data[b++] = bg.red / 257;
-			b++;
-		}
-	}
-
-	return img;
-}
-
-/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
-static void
-ltk_text_line_draw_glyph(ltk_glyph *glyph, int xoff, int yoff, XImage *img, XColor fg) {
-	int x = glyph->x + xoff;
-	int y = glyph->y + yoff;
-	double a;
-	int b;
-	for (int i = 0; i < glyph->info->h; i++) {
-		for (int j = 0; j < glyph->info->w; j++) {
-			if (y + i >= img->height || x + j >= img->width ||
-			    y + i < 0 || x + i < 0)
-				continue;
-			b = (y + i) * img->bytes_per_line + (x + j) * 4;
-			a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0;
-			img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)img->data[b] * 257) / 257;
-			img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)img->data[b + 1] * 257) / 257;
-			img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)img->data[b + 2] * 257) / 257;
-		}
-	}
-}
-
-XImage *
-ltk_text_line_render(
-	struct ltk_text_line *tl,
-	Display *dpy,
-	Window window,
-	GC gc,
-	Colormap colormap,
-	XColor fg,
-	XColor bg)
-{
-	ltk_glyph *glyph;
-
-	XWindowAttributes attrs;
-	XGetWindowAttributes(dpy, window, &attrs);
-	int depth = attrs.depth;
-	/* FIXME: pass old image; if it has same dimensions, just clear it */
-	XImage *img = ltk_create_ximage(dpy, tl->w, tl->h, depth, bg);
-	for (int i = 0; i < tl->glyph_len; i++) {
-		ltk_text_line_draw_glyph(&tl->glyphs[i], -tl->x_min, -tl->y_min, img, fg);
-	}
-	return img;
-}
-
-static void
-ltk_text_line_create_glyphs(LtkTextLine *tl) {
-	int x_min, x_max, y_min, y_max;
-	ltk_text_to_glyphs(tl->glyphs, tl->glyph_len, tl->text, tl->font_size,
-	    &x_min, &y_min, &x_max, &y_max);
-	/* for drawing the glyphs at the right position on the image */
-	tl->x_min = x_min;
-	tl->y_min = y_min;
-	tl->w = x_max - x_min;
-	tl->h = y_max - y_min;
-}
-
-LtkTextLine *
-ltk_text_line_create(uint16_t font_size, char *text, int width) {
-	LtkTextLine *line = malloc(sizeof(LtkTextLine));
-	if (!line) ltk_err("ltk_text_line_create (basic)");
-	line->text = text;
-	line->glyph_len = u8_strlen(text);
-	line->glyphs = malloc(line->glyph_len * sizeof(ltk_glyph));
-	line->font_size = font_size;
-	ltk_text_line_create_glyphs(line);
-	return line;
-}
-
-void
-ltk_text_line_destroy(LtkTextLine *tl) {
-	free(tl->text);
-	/* FIXME: Reference count glyph infos */
-	free(tl->glyphs);
-	free(tl);
-}
diff --git a/text_line.h b/text_line.h
@@ -1,52 +0,0 @@
-/*
- * This file is part of the Lumidify ToolKit (LTK)
- * Copyright (c) 2020 lumidify <nobody@lumidify.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef _TEXT_LINE_H_
-#define _TEXT_LINE_H_
-
-/*
-Requires the following includes:
-<X11/Xlib.h>, <X11/Xutil.h>, <stdint.h>
-*/
-
-typedef struct {
-	char *text;
-	ltk_glyph *glyphs;
-	size_t glyph_len;
-	uint16_t font_size;
-	int w;
-	int h;
-	int x_min;
-	int y_min;
-} LtkTextLine;
-
-void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm);
-void ltk_cleanup_text(void);
-LtkTextLine *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width);
-void ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg);
-void ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y);
-void ltk_text_line_set_width(LtkTextLine *tl, int width);
-void ltk_text_line_get_size(LtkTextLine *tl, int *w, int *h);
-void ltk_text_line_destroy(LtkTextLine *tl);
-
-#endif /* _TEXT_LINE_H_ */
diff --git a/text_pango.c b/text_pango.c
@@ -10,6 +10,7 @@
 
 #include <pango/pangoxft.h>
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -49,7 +50,8 @@ ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm) {
 
 void
 ltk_cleanup_text(void) {
-	if (tm.default_font) free(tm.default_font);
+	/* FIXME: strdup, etc. wrapper */
+	if (tm.default_font) ltk_free(tm.default_font);
 	/* FIXME: destroy fontmap and context */
 }
 
@@ -62,8 +64,7 @@ LtkTextLine *
 ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) {
 	if (!tm.context)
 		ltk_err("ltk_text_line_create (pango): text not initialized yet");
-	LtkTextLine *line = malloc(sizeof(LtkTextLine));
-	if (!line) ltk_err("ltk_text_line_create (pango)");
+	LtkTextLine *line = ltk_malloc(sizeof(LtkTextLine), "ltk_text_line_create");
 	line->text = text;
 	line->font_size = font_size;
 	line->layout = pango_layout_new(tm.context);
@@ -115,6 +116,6 @@ ltk_text_line_destroy(LtkTextLine *tl) {
 	g_object_unref(tl->layout);
 	XftDrawDestroy(tl->draw);
 	XFreePixmap(tm.dpy, tl->pixmap);
-	free(tl->text);
-	free(tl);
+	ltk_free(tl->text);
+	ltk_free(tl);
 }
diff --git a/text_stb.c b/text_stb.c
@@ -35,6 +35,7 @@
 #include "khash.h"
 #include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */
 
+#include "memory.h"
 #include "color.h"
 #include "ltk.h"
 #include "util.h"
@@ -200,8 +201,7 @@ void
 ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap cm) {
 	tm.fonts_bufsize = 1;
 	tm.glyph_cache = kh_init(glyphcache);
-	tm.fonts = malloc(sizeof(LtkFont *));
-	if (!tm.fonts) ltk_err("ltk_init_text");
+	tm.fonts = ltk_malloc(sizeof(LtkFont *), "ltk_init_text");
 	ltk_load_default_font(default_font);
 	tm.dpy = dpy;
 	tm.screen = screen;
@@ -224,8 +224,7 @@ ltk_cleanup_text(void) {
 
 static LtkGlyphInfo *
 ltk_create_glyph_info(LtkFont *font, int id, float scale) {
-	LtkGlyphInfo *glyph = malloc(sizeof(LtkGlyphInfo));
-	if (!glyph) ltk_err("ltk_create_glyph_info");
+	LtkGlyphInfo *glyph = ltk_malloc(sizeof(LtkGlyphInfo), "ltk_create_glyph_info");
 
 	glyph->id = id;
 	glyph->refs = 0;
@@ -239,8 +238,8 @@ ltk_create_glyph_info(LtkFont *font, int id, float scale) {
 
 static void
 ltk_destroy_glyph_info(LtkGlyphInfo *gi) {
-	free(gi->alphamap);
-	free(gi);
+	ltk_free(gi->alphamap);
+	ltk_free(gi);
 }
 
 static LtkGlyphInfo *
@@ -321,8 +320,7 @@ ltk_load_default_font(char *name) {
 static LtkFont *
 ltk_create_font(char *path, uint16_t id, int index) {
 	unsigned long len;
-	LtkFont *font = malloc(sizeof(LtkFont));
-	if (!font) ltk_err("ltk_create_font (stb)");
+	LtkFont *font = ltk_malloc(sizeof(LtkFont), "ltk_create_font");
 	char *contents = ltk_read_file(path, &len);
 	if (!contents)
 		ltk_fatal_errno("Unable to read font file %s\n", path);
@@ -341,16 +339,15 @@ ltk_create_font(char *path, uint16_t id, int index) {
 
 static void
 ltk_destroy_font(LtkFont *font) {
-	free(font->info.data);
-	free(font);
+	ltk_free(font->info.data);
+	ltk_free(font);
 }
 
 static LtkFont *
 ltk_load_font(char *path, int index) {
 	LtkFont *font = ltk_create_font(path, tm.font_id_cur++, index);
 	if (tm.num_fonts == tm.fonts_bufsize) {
-		LtkFont *new = realloc(tm.fonts, tm.fonts_bufsize * 2 * sizeof(LtkFont *));
-		if (!new) ltk_err("ltk_load_font");
+		LtkFont *new = ltk_realloc(tm.fonts, tm.fonts_bufsize * 2 * sizeof(LtkFont *), "ltk_load_font");
 		tm.fonts = new;
 		tm.fonts_bufsize *= 2;
 	}
@@ -474,7 +471,7 @@ ltk_unref_glyphs(ltk_glyph *glyphs, int num_glyphs) {
 static XImage *
 ltk_create_ximage(int w, int h, int depth, XColor bg) {
 	XImage *img = XCreateImage(tm.dpy, CopyFromParent, depth, ZPixmap, 0, NULL, w, h, 32, 0);
-	img->data = calloc(img->bytes_per_line, img->height);
+	img->data = ltk_calloc(img->bytes_per_line, img->height, "ltk_create_ximage");
 	XInitImage(img);
 
 	int b;
@@ -572,13 +569,12 @@ ltk_text_line_create_glyphs(LtkTextLine *tl) {
 
 LtkTextLine *
 ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) {
-	LtkTextLine *line = malloc(sizeof(LtkTextLine));
-	if (!line) ltk_err("ltk_text_line_create (basic)");
+	LtkTextLine *line = ltk_malloc(sizeof(LtkTextLine), "ltk_text_line_create");
 	line->window = window;
 	line->img = NULL;
 	line->text = text;
 	line->glyph_len = u8_strlen(text);
-	line->glyphs = malloc(line->glyph_len * sizeof(LtkGlyph));
+	line->glyphs = ltk_malloc(line->glyph_len * sizeof(LtkGlyph), "ltk_text_line_create");
 	line->font_size = font_size;
 	ltk_text_line_create_glyphs(line);
 	return line;
@@ -586,8 +582,8 @@ ltk_text_line_create(Window window, uint16_t font_size, char *text, int width) {
 
 void
 ltk_text_line_destroy(LtkTextLine *tl) {
-	free(tl->text);
+	ltk_free(tl->text);
 	/* FIXME: Reference count glyph infos */
-	free(tl->glyphs);
-	free(tl);
+	ltk_free(tl->glyphs);
+	ltk_free(tl);
 }