AnalogTerm2: Rework font memory management code.
authorMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 13 Jun 2023 11:31:49 +0000 (11:31 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Tue, 13 Jun 2023 11:31:49 +0000 (11:31 +0000)
mmsoftware/analogterm2/src/font.c
mmsoftware/analogterm2/tests/at2-aliases.sh

index cf844d6..051843a 100644 (file)
@@ -29,6 +29,9 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
 
 #include <state.h>
 #include <font.h>
 
 static font_t  *font_load(uint32_t, char *, unsigned int, unsigned int);
 static font_t  *font_new(void);
+static void    font_append(state_t *, font_t *);
 static void    font_free(font_t *);
 static ftable_t        *ftable_init(const uint32_t *, int, font_t *);
 static ftable_t        *ftable_new(font_t *);
 static void    ftable_free(ftable_t *);
+static void    ftable_append(state_t *, ftable_t *);
 static void    *font_glyph_new(state_t *, uint32_t);
 
 
@@ -260,6 +265,13 @@ static void
 font_free(font_t *font)
 {
 
+       if (font == NULL) {
+#ifndef NDEBUG
+               (void)fprintf(stderr, "font_free(NULL)\n");
+#endif
+               return;
+       }
+
        if (font->pixels != NULL)
                free(font->pixels);
        if (font->glyphs != NULL) {
@@ -272,6 +284,26 @@ font_free(font_t *font)
        free(font);
 }
 
+static void
+font_append(state_t *st, font_t *f)
+{
+       font_t *n, *o;
+
+#ifndef NDEBUG
+       (void)fprintf(stderr, "font_append(%p)\n", f);
+#endif
+
+       f->next = NULL;
+       if (st->font == NULL) {
+               st->font = f;
+               return;
+       }
+
+       for (n = st->font; n != NULL; n = n->next)
+               o = n;
+       o->next = f;
+}
+
 static ftable_t *
 ftable_init(const uint32_t *c, int n, font_t *f)
 {
@@ -321,6 +353,13 @@ static void
 ftable_free(ftable_t *t)
 {
 
+       if (t == NULL) {
+#ifndef NDEBUG
+               (void)fprintf(stderr, "ftable_free(NULL)\n");
+#endif
+               return;
+       }
+
        if (t->user && t->code != NULL) {
                free(t->code);
                t->code = NULL;
@@ -328,6 +367,26 @@ ftable_free(ftable_t *t)
        free(t);
 }
 
+static void
+ftable_append(state_t *st, ftable_t *t)
+{
+       ftable_t *n, *o;
+
+#ifndef NDEBUG
+       (void)fprintf(stderr, "ftable_append(%p)\n", t);
+#endif
+
+       t->next = NULL;
+       if (st->ftable == NULL) {
+               st->ftable = t;
+               return;
+       }
+
+       for (n = st->ftable; n != NULL; n = n->next)
+               o = n;
+       o->next = t;
+}
+
 /* We could use a slab allocator if we really needed performance allocating
  * many new characters.  Font loading is however not really performance
  * criticial, so let's keep memory compact for locality and faster refresh.
@@ -456,34 +515,34 @@ font_init(state_t *state, screen_t *screen)
 
        state->font_user = font_new();
 
-       state->ftable = ftable_init(latin2_characters,
-           sizeof(latin2_characters) / sizeof(uint32_t), state->font_latin2);
-       state->ftable->next = ftable_init(latin3_characters,
-           sizeof(latin3_characters) / sizeof(uint32_t), state->font_latin3);
-       state->ftable->next->next = ftable_init(latin4_characters,
-           sizeof(latin4_characters) / sizeof(uint32_t), state->font_latin4);
-       state->ftable->next->next->next = ftable_init(iso8859_14_characters,
+       state->ftable = NULL;
+       ftable_append(state, ftable_init(latin2_characters,
+           sizeof(latin2_characters) / sizeof(uint32_t), state->font_latin2));
+       ftable_append(state, ftable_init(latin3_characters,
+           sizeof(latin3_characters) / sizeof(uint32_t), state->font_latin3));
+       ftable_append(state, ftable_init(latin4_characters,
+           sizeof(latin4_characters) / sizeof(uint32_t), state->font_latin4));
+       ftable_append(state, ftable_init(iso8859_14_characters,
            sizeof(iso8859_14_characters) / sizeof(uint32_t),
-           state->font_iso8859_14);
-       state->ftable->next->next->next->next = ftable_init(misc_characters,
-           sizeof(misc_characters) / sizeof(uint32_t), state->font_misc);
+           state->font_iso8859_14));
+       ftable_append(state, ftable_init(misc_characters,
+           sizeof(misc_characters) / sizeof(uint32_t), state->font_misc));
 
        state->ftable_user = ftable_new(state->font_user);
-       state->ftable->next->next->next->next->next = state->ftable_user;
+       ftable_append(state, state->ftable_user);
 
        /* Contiguous block sets */
-       state->font = font_load(32, analogterm_ascii_9_bits,
-           analogterm_ascii_9_width, analogterm_ascii_9_height);
-       state->font->next = font_load(160, analogterm_latin_9_bits,
-           analogterm_latin_9_width, analogterm_latin_9_height);
-       state->font->next->next = font_load(9472, analogterm_graphics1_9_bits,
-           analogterm_graphics1_9_width, analogterm_graphics1_9_height);
-       state->font->next->next->next = font_load(129896,
-           analogterm_graphics2_9_bits, analogterm_graphics2_9_width,
-           analogterm_graphics2_9_height);
-       state->font->next->next->next->next = font_load(130032,
-           analogterm_graphics3_9_bits, analogterm_graphics3_9_width,
-           analogterm_graphics3_9_height);
+       state->font = NULL;
+       font_append(state, font_load(32, analogterm_ascii_9_bits,
+           analogterm_ascii_9_width, analogterm_ascii_9_height));
+       font_append(state, font_load(160, analogterm_latin_9_bits,
+           analogterm_latin_9_width, analogterm_latin_9_height));
+       font_append(state, font_load(9472, analogterm_graphics1_9_bits,
+           analogterm_graphics1_9_width, analogterm_graphics1_9_height));
+       font_append(state, font_load(129896, analogterm_graphics2_9_bits,
+           analogterm_graphics2_9_width, analogterm_graphics2_9_height));
+       font_append(state, font_load(130032, analogterm_graphics3_9_bits,
+           analogterm_graphics3_9_width, analogterm_graphics3_9_height));
 
        /*
         * If font is not the default size, programmatically regenerate
@@ -510,42 +569,56 @@ font_init(state_t *state, screen_t *screen)
        map_reset();
 }
 
+#define CLEANUP_NSIZE 64
+
 void
 font_cleanup(state_t *state)
 {
+       void *ptrs[CLEANUP_NSIZE];
+       int nptrs = 0;
+       ftable_t *t;
+       font_t *f;
 
        map_reset();
 
-       ftable_free(state->ftable->next->next->next->next->next);
-       state->ftable->next->next->next->next->next = NULL;
-       state->ftable_user = NULL;
-
-       ftable_free(state->ftable->next->next->next->next);
-       state->ftable->next->next->next->next = NULL;
-       ftable_free(state->ftable->next->next->next);
-       state->ftable->next->next->next = NULL;
-       ftable_free(state->ftable->next->next);
-       state->ftable->next->next = NULL;
-       ftable_free(state->ftable->next);
-       state->ftable->next = NULL;
-       ftable_free(state->ftable);
+       /* Collect ftables and free in reverse order */
+       for (nptrs = 0, t = state->ftable; t != NULL; t = t->next) {
+               if (nptrs == CLEANUP_NSIZE)
+                       err(EXIT_FAILURE,
+                           "font_cleanup() - increase CLEANUP_NSIZE");
+               ptrs[nptrs++] = t;
+       }
+       for (; nptrs > 0; nptrs--) {
+#ifndef NDEBUG
+               (void)fprintf(stderr, "ftable_free(%d, %p)\n",
+                   nptrs, ptrs[nptrs - 1]);
+#endif
+               ftable_free(ptrs[nptrs - 1]);
+       }
+
        state->ftable = NULL;
+       state->ftable_user = NULL; /* Was in above list */
+
+       /* Collect font structs and free in reverse order */
+       for (nptrs = 0, f = state->font; f != NULL; f = f->next) {
+               if (nptrs == CLEANUP_NSIZE)
+                       err(EXIT_FAILURE,
+                           "font_cleanup() - increase CLEANUP_NSIZE");
+               ptrs[nptrs++] = f;
+       }
+       for (; nptrs > 0; nptrs--) {
+#ifndef NDEBUG
+               (void)fprintf(stderr, "font_free(%d, %p)\n",
+                   nptrs, ptrs[nptrs - 1]);
+#endif
+               font_free(ptrs[nptrs - 1]);
+       }
 
-       state->font->next->next->next->next->next = NULL;
-       font_free(state->font->next->next->next->next);
-       state->font->next->next->next->next = NULL;
-       font_free(state->font->next->next->next);
-       state->font->next->next->next = NULL;
-       font_free(state->font->next->next);
-       state->font->next->next = NULL;
-       font_free(state->font->next);
-       state->font->next = NULL;
-       font_free(state->font);
        state->font = NULL;
 
+       /* Glyph-order sets not in list */
        font_free(state->font_user);
        state->font_user = NULL;
-
        font_free(state->font_misc);
        state->font_misc = NULL;
        font_free(state->font_iso8859_14);
index 358badc..c25c4be 100755 (executable)
@@ -89,6 +89,7 @@ alias atred14="printf '\033[?658467;230;0;38h'"
 alias atred15="printf '\033[?658467;255;96;255h'"
 alias atred16="printf '\033[?658467;200;96;255h'"
 alias atred17="printf '\033[?658467;192;128;255h'"
+alias atbutter="printf '\033[?658467;246;223;147h'"
 
 # Cursor control
 alias atcurdisable="printf '\033[?658467;65549h'"