ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit bf406bf2c7ad5025890a061780823576b65a67d7
parent 2e64aac7eba6791ed47514d37838b0d5d9d00cf1
Author: lumidify <nobody@lumidify.org>
Date:   Sun, 24 Oct 2021 15:21:13 +0200

Free memory properly on exit

There are probably still a lot of things missing here.

Diffstat:
Mbuffer.c | 12++++++++++--
Mcache.c | 2+-
Mkeys_basic.c | 18++++++++++++++++++
Mkeys_basic.h | 1+
Mledit.c | 13++++++-------
Msearch.c | 9++++-----
Msearch.h | 2+-
Mtxtbuf.c | 2++
Mutil.c | 9+++++++++
Mutil.h | 1+
Mwindow.c | 20++++++++++++++++++++
Mwindow.h | 1+
12 files changed, 74 insertions(+), 16 deletions(-)

diff --git a/buffer.c b/buffer.c @@ -52,7 +52,6 @@ ledit_buffer_set_mode(ledit_buffer *buffer, enum ledit_mode mode) { ledit_change_mode_group(buffer->undo); } -/* FIXME: destroy basic_attrs somewhere */ ledit_buffer * ledit_buffer_create(ledit_common *common, ledit_theme *theme, ledit_window *window) { if (basic_attrs == NULL) { @@ -181,11 +180,18 @@ ledit_buffer_destroy(ledit_buffer *buffer) { ledit_cache_destroy(buffer->cache); ledit_undo_stack_destroy(buffer->undo); free(buffer->lines); - if (buffer->filename) free(buffer->filename); + if (buffer->filename) + free(buffer->filename); free(buffer); } void +ledit_buffer_cleanup(void) { + if (basic_attrs) + pango_attr_list_unref(basic_attrs); +} + +void ledit_buffer_normalize_line(ledit_line *line) { if (line->gap < line->len) { memmove( @@ -231,6 +237,7 @@ ledit_buffer_set_line_selection(ledit_buffer *buffer, int line, int start_byte, pango_attr_list_insert(list, attr2); #endif pango_layout_set_attributes(l->layout, list); + pango_attr_list_unref(list); l->dirty = 1; } @@ -256,6 +263,7 @@ ledit_buffer_set_line_cursor_attrs(ledit_buffer *buffer, int line, int index) { pango_attr_list_insert(list, attr2); #endif pango_layout_set_attributes(l->layout, list); + pango_attr_list_unref(list); } else { pango_layout_set_attributes(l->layout, basic_attrs); } diff --git a/cache.c b/cache.c @@ -10,9 +10,9 @@ ledit_cache * ledit_cache_create(ledit_common *common) { - (void)common; /* FIXME: remove argument */ /* FIXME: prevent overflow */ ledit_cache *cache = ledit_malloc(sizeof(ledit_cache)); + cache->dpy = common->dpy; cache->entries = ledit_malloc(20 * sizeof(ledit_cache_pixmap)); for (int i = 0; i < 20; i++) { cache->entries[i].pixmap = None; diff --git a/keys_basic.c b/keys_basic.c @@ -62,6 +62,21 @@ static struct { struct key_stack_elem *stack; } key_stack = {0, 0, NULL}; +void +basic_key_cleanup(void) { + /* this should be safe since push_repetition_stack sets all new + elements to NULL when resizing the stack */ + for (size_t i = 0; i < repetition_stack.alloc; i++) { + free(repetition_stack.stack[i].key_text); + } + for (size_t i = 0; i < repetition_stack.tmp_alloc; i++) { + free(repetition_stack.tmp_stack[i].key_text); + } + free(repetition_stack.stack); + free(repetition_stack.tmp_stack); + free(key_stack.stack); +} + /* No, this isn't actually a stack. So what? */ static struct repetition_stack_elem *push_repetition_stack(void); static void finalize_repetition_stack(void); @@ -146,6 +161,9 @@ push_repetition_stack(void) { repetition_stack.tmp_stack, new_alloc * sizeof(struct repetition_stack_elem) ); + for (size_t i = repetition_stack.tmp_alloc; i < new_alloc; i++) { + repetition_stack.tmp_stack[i].key_text = NULL; + } repetition_stack.tmp_alloc = new_alloc; } e = &repetition_stack.tmp_stack[repetition_stack.tmp_len]; diff --git a/keys_basic.h b/keys_basic.h @@ -1 +1,2 @@ +void basic_key_cleanup(void); struct action basic_key_handler(ledit_buffer *buffer, XEvent *event, int lang_index); diff --git a/ledit.c b/ledit.c @@ -38,6 +38,7 @@ #include "undo.h" #include "buffer.h" #include "action.h" +#include "search.h" #include "keys.h" #include "keys_basic.h" @@ -230,14 +231,12 @@ setup(int argc, char *argv[]) { static void cleanup(void) { - /* FIXME: cleanup everything else */ - /* - ledit_cleanup_search(); - ledit_destroy_cache(); - ledit_destroy_undo_stack(buffer); - ledit_destroy_buffer(buffer); - */ + /* FIXME: check for other things to clean up */ + ledit_search_cleanup(); + basic_key_cleanup(); + ledit_buffer_destroy(buffer); ledit_window_destroy(window); + ledit_theme_destroy(&common, theme); XCloseDisplay(common.dpy); } diff --git a/search.c b/search.c @@ -19,7 +19,6 @@ #include "search.h" /* FIXME: make sure only whole utf8 chars are matched */ -/* FIXME: clean this up */ char *last_search = NULL; enum { FORWARD, @@ -27,15 +26,15 @@ enum { } last_dir = FORWARD; void -ledit_set_search_forward(char *pattern) { - last_dir = FORWARD; +ledit_search_cleanup(void) { free(last_search); - last_search = ledit_strdup(pattern); } void -ledit_cleanup_search(void) { +ledit_set_search_forward(char *pattern) { + last_dir = FORWARD; free(last_search); + last_search = ledit_strdup(pattern); } void diff --git a/search.h b/search.h @@ -5,7 +5,7 @@ enum ledit_search_state { SEARCH_NO_PATTERN }; -void ledit_cleanup_search(void); +void ledit_search_cleanup(void); void ledit_set_search_forward(char *pattern); void ledit_set_search_backward(char *pattern); enum ledit_search_state ledit_search_next(ledit_buffer *buffer, int *line_ret, int *byte_ret); diff --git a/txtbuf.c b/txtbuf.c @@ -32,6 +32,8 @@ txtbuf_shrink(txtbuf *buf) { void txtbuf_destroy(txtbuf *buf) { + if (!buf) + return; free(buf->text); free(buf); } diff --git a/util.c b/util.c @@ -1,3 +1,5 @@ +#include <stdlib.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> #include <pango/pangoxft.h> @@ -39,3 +41,10 @@ ledit_draw_grow(ledit_window *window, ledit_draw *draw, int w, int h) { XftDrawChange(draw->xftdraw, draw->pixmap); } } + +void +ledit_draw_destroy(ledit_window *window, ledit_draw *draw) { + XFreePixmap(window->common->dpy, draw->pixmap); + XftDrawDestroy(draw->xftdraw); + free(draw); +} diff --git a/util.h b/util.h @@ -6,3 +6,4 @@ typedef struct { ledit_draw *ledit_draw_create(ledit_window *window, int w, int h); void ledit_draw_grow(ledit_window *window, ledit_draw *draw, int w, int h); +void ledit_draw_destroy(ledit_window *window, ledit_draw *draw); diff --git a/window.c b/window.c @@ -415,7 +415,27 @@ ledit_window_create(ledit_common *common, ledit_theme *theme) { void ledit_window_destroy(ledit_window *window) { /* FIXME: cleanup everything else */ + pango_font_description_free(window->font); + g_object_unref(window->fontmap); + g_object_unref(window->context); + /* FIXME: is gc, etc. destroyed automatically when destroying window? */ + if (window->spotlist) + XFree(window->spotlist); XDestroyWindow(window->common->dpy, window->xwin); + g_object_unref(window->bb->mode); + /*g_object_unref(window->bb->ruler);*/ /* FIXME: implement ruler */ + g_object_unref(window->bb->line); + ledit_draw_destroy(window, window->bb->mode_draw); + ledit_draw_destroy(window, window->bb->line_draw); + free(window->bb->line_text); + free(window->bb); + free(window); +} + +void +ledit_window_cleanup(void) { + txtbuf_destroy(xsel.primary); + free(xsel.clipboard); } void diff --git a/window.h b/window.h @@ -42,6 +42,7 @@ typedef struct { ledit_window *ledit_window_create(ledit_common *common, ledit_theme *theme); void ledit_window_destroy(ledit_window *window); +void ledit_window_cleanup(void); /* FIXME: this is a bit confusing because there's a difference between editable text shown and non-editable message shown */