URI: 
       tFix many syntax errors - ltkx - GUI toolkit for X11 (WIP)
  HTML git clone git://lumidify.org/ltkx.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 1242d3b3fcdb252a60c422b8eb15396e641fd656
   DIR parent d992e1c9a4486549c34466de7e54c5a87d5eb6a6
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Wed, 13 May 2020 22:14:24 +0200
       
       Fix many syntax errors
       
       Diffstat:
         M Makefile                            |       4 ++--
         M array.h                             |       7 +++----
         M gap_buffer.h                        |      32 +++++++++++++++++++------------
         M stack.h                             |      62 +++++++++++++++++--------------
         M text_buffer.c                       |     109 +++++++++++++++++--------------
         M text_buffer.h                       |      19 +++++++++----------
         M text_edit.c                         |       2 +-
       
       7 files changed, 129 insertions(+), 106 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       t@@ -1,7 +1,7 @@
        LIBS = -lm `pkg-config --libs x11 harfbuzz fontconfig fribidi`
        STD = -std=c99
        CFLAGS = -g -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 harfbuzz fontconfig fribidi` -pedantic
       -OBJ = stb_truetype.o text-common.o text-hb.o ltk.o ini.o grid.o button.o test1.o
       +OBJ = stb_truetype.o text-common.o text_buffer.o text-hb.o ltk.o ini.o grid.o button.o test1.o
        
        test1: $(OBJ)
                gcc $(STD) -o $@ $(OBJ) $(LIBS)
       t@@ -12,4 +12,4 @@ test1: $(OBJ)
        .PHONY: clean
        
        clean:
       -        rm -f stb_truetype.o text-common.o text-hb.o ltk.o ini.o grid.o button.o test1.o test1
       +        rm -f $(OBJ) test1
   DIR diff --git a/array.h b/array.h
       t@@ -32,7 +32,7 @@ struct ltk_array_##name {                                                                \
                type *buf;                                                                        \
                size_t buf_size;                                                                \
                size_t len;                                                                        \
       -}                                                                                        \
       +};                                                                                        \
        struct ltk_array_##name *ltk_array_create_##name(size_t initial_len);                        \
        void ltk_array_resize_##name(struct ltk_array_##name *ar, size_t size);                        \
        void ltk_array_destroy_##name(struct ltk_array_##name *ar);                                \
       t@@ -46,14 +46,14 @@ ltk_array_create_##name(size_t initial_len) {                                                \
                        (void)fprintf(stderr, "Array length is zero\n");                        \
                        exit(1);                                                                \
                }                                                                                \
       -        struct ltk_gap_buffer_##name *ar = malloc(sizeof(struct ltk_array_##name));        \
       +        struct ltk_array_##name *ar = malloc(sizeof(struct ltk_array_##name));                \
                if (!ar) goto error;                                                                \
                ar->buf = malloc(initial_len * sizeof(type));                                        \
                if (!ar->buf) goto error;                                                        \
                ar->buf_size = initial_len;                                                        \
                ar->len = 0;                                                                        \
        error:                                                                                        \
       -        (void)fprintf("Out of memory while trying to allocate array\n");                \
       +        (void)fprintf(stderr, "Out of memory while trying to allocate array\n");        \
                exit(1);                                                                        \
        }                                                                                        \
                                                                                                \
       t@@ -76,7 +76,6 @@ ltk_array_resize_##name(struct ltk_array_##name *ar, size_t len) {                        \
                size_t new_size;                                                                \
                if (4 * len <= ar->buf_size) {                                                        \
                        new_size = 2 * len;                                                        \
       -        }                                                                                \
                } else if (len > ar->buf_size) {                                                \
                        new_size = 2 * len;                                                        \
                } else {                                                                        \
   DIR diff --git a/gap_buffer.h b/gap_buffer.h
       t@@ -33,14 +33,18 @@ struct ltk_gap_buffer_##name {                                                        \
                size_t buf_size;                                                        \
                size_t gap_left;                                                        \
                size_t gap_size;                                                        \
       +        size_t len;                                                                \
        };                                                                                \
                                                                                        \
        struct ltk_gap_buffer_##name * ltk_gap_buffer_create_##name(void);                \
        struct ltk_gap_buffer_##name *                                                        \
        ltk_gap_buffer_create_from_data_##name(type *data, size_t len);                        \
       +type ltk_gap_buffer_get_##name(struct ltk_gap_buffer_##name *gb, size_t index);        \
       +void ltk_gap_buffer_set_##name(                                                        \
       +    struct ltk_gap_buffer_##name *gb, size_t index, type data);                        \
        void ltk_gap_buffer_resize_gap_##name(                                                \
            struct ltk_gap_buffer_##name *gb, int len);                                        \
       -void ltk_gap_buffer_insert_##name(struct ltk_gap_buffer_##type *gb,                \
       +void ltk_gap_buffer_insert_##name(struct ltk_gap_buffer_##name *gb,                \
            type *new, size_t start, size_t len);                                        \
        void ltk_gap_buffer_insert_single_##name(                                        \
            struct ltk_gap_buffer_##name *gb, type new);                                \
       t@@ -62,6 +66,7 @@ ltk_gap_buffer_create_##name(void) {                                                \
                gb->buf_size = 8;                                                        \
                gb->gap_left = 0;                                                        \
                gb->gap_size = 8;                                                        \
       +        gb->len = 0;                                                                \
                return gb;                                                                \
        error:                                                                                \
                (void)fprintf(stderr, "Out of memory while trying to"                        \
       t@@ -80,6 +85,7 @@ ltk_gap_buffer_create_from_data_##name(type *data, size_t len) {                \
                }                                                                        \
                gb->buf = data;                                                                \
                gb->buf_size = len;                                                        \
       +        gb->len = len;                                                                \
                gb->gap_left = 0;                                                        \
                gb->gap_size = 0;                                                        \
                return gb;                                                                \
       t@@ -89,20 +95,20 @@ type                                                                                \
        ltk_gap_buffer_get_##name(struct ltk_gap_buffer_##name *gb, size_t index) {        \
                if (index < gb->gap_left)                                                \
                        return gb->buf[index];                                                \
       -        else if (index < gb->buf_size - gb->gap_size)                                \
       -                return gb->buf[index - gb->gap_size];                                \
       -        (void)fprintf("Gap buffer index out of bounds\n");                        \
       +        else if (index + gb->gap_size < gb->len)                                \
       +                return gb->buf[index + gb->gap_size];                                \
       +        (void)fprintf(stderr, "Gap buffer index out of bounds\n");                \
                exit(1);                                                                \
        }                                                                                \
                                                                                        \
        void                                                                                \
       -ltk_gap_buffer_get_##name(                                                        \
       +ltk_gap_buffer_set_##name(                                                        \
            struct ltk_gap_buffer_##name *gb, size_t index, type data) {                \
                if (index < gb->gap_left)                                                \
                        gb->buf[index] = data;                                                \
       -        else if (index < gb->buf_size - gb->gap_size)                                \
       -                gb->buf[index - gb->gap_size] = data;                                \
       -        (void)fprintf("Gap buffer index out of bounds\n");                        \
       +        else if (index + gb->gap_size < gb->len)                                \
       +                gb->buf[index + gb->gap_size] = data;                                \
       +        (void)fprintf(stderr, "Gap buffer index out of bounds\n");                \
                exit(1);                                                                \
        }                                                                                \
                                                                                        \
       t@@ -118,8 +124,8 @@ ltk_gap_buffer_resize_gap_##name(                                                \
                   manually, so it could potentially be copied twice, which really        \
                   wouldn't be good. Maybe use realloc if only a small part is after        \
                   the gap and just regular malloc otherwise? */                        \
       -        int new_size = gb->buf_size - gb->gap-size + len;                        \
       -        struct ltk_gap_buffer_##name *new = malloc(new_size * sizeof(type));        \
       +        int new_size = gb->buf_size - gb->gap_size + len;                        \
       +        type *new = malloc(new_size * sizeof(type));        \
                if (!new) {                                                                \
                        (void)fprintf(stderr, "Out of memory while trying to"                \
                            "resize gap buffer\n");                                        \
       t@@ -128,7 +134,7 @@ ltk_gap_buffer_resize_gap_##name(                                                \
                for (int i = 0; i < gb->gap_left; i++) {                                \
                        new[i] = gb->buf[i];                                                \
                }                                                                        \
       -        for (int i = gb->gap_left + gb->gap_size; i < gb->buf_size) {                \
       +        for (int i = gb->gap_left + gb->gap_size; i < gb->buf_size; i++) {        \
                        new[i - gb->gap_size + len] = gb->buf[i];                        \
                }                                                                        \
                free(gb->buf);                                                                \
       t@@ -145,6 +151,7 @@ ltk_gap_buffer_insert_##name(struct ltk_gap_buffer_##name *gb,                        \
                }                                                                        \
                gb->gap_left = gb->gap_left + len;                                        \
                gb->gap_size -= len;                                                        \
       +        gb->len += len;                                                                \
        }                                                                                \
                                                                                        \
        void                                                                                \
       t@@ -164,7 +171,7 @@ ltk_gap_buffer_move_gap_##name(                                                        \
                        return;                                                                \
                }                                                                        \
                if (pos >= gb->gap_left) {                                                \
       -                for (int i = gb->gap_left; i < pos) {                                \
       +                for (int i = gb->gap_left; i < pos; i++) {                        \
                                gb->buf[i] = gb->buf[i + gb->gap_size];                        \
                        }                                                                \
                } else {                                                                \
       t@@ -177,6 +184,7 @@ ltk_gap_buffer_move_gap_##name(                                                        \
                                                                                        \
        void ltk_gap_buffer_clear_##name(struct ltk_gap_buffer_##name *gb) {                \
                gb->gap_left = 0;                                                        \
       +        gb->len = 0;                                                                \
                gb->gap_size = gb->buf_size;                                                \
        }                                                                                \
                                                                                        \
   DIR diff --git a/stack.h b/stack.h
       t@@ -22,9 +22,12 @@
         * SOFTWARE.
         */
        
       +#ifndef _LTK_STACK_H_
       +#define _LTK_STACK_H_
       +
        /* This is a "macro'd" and modified version of raqm's stack */
        
       -#define LTK_INIT_STACK_DECL(name, type1, type2, data1, data2)                        \
       +#define LTK_STACK_INIT_DECL(name, type1, type2, data1, data2)                        \
        struct ltk_stack_##name {                                                        \
          size_t capacity;                                                                \
          size_t size;                                                                        \
       t@@ -32,24 +35,24 @@ struct ltk_stack_##name {                                                        \
          type2 *data2;                                                                        \
        };                                                                                \
                                                                                        \
       -static int ltk_stack_pop_##name(ltk_stack_##name *stack);                        \
       -static data1 ltk_stack_top1_##name(ltk_stack##name *stack);                        \
       -static void ltk_stack_destroy_##name(ltk_stack_##name *stack);                        \
       -static int ltk_stack_push_##name(                                                \
       -    ltk_stack_##name *stack, type1 data1, type2 data2);                                \
       -static data2 ltk_stack_top2_##name(ltk_stack##name *stack);                        \
       -static ltk_stack_##name *ltk_stack_create_##name (size_t max);
       +int ltk_stack_pop_##name(struct ltk_stack_##name *stack);                        \
       +type1 ltk_stack_top1_##name(struct ltk_stack_##name *stack, type1 def);                \
       +void ltk_stack_destroy_##name(struct ltk_stack_##name *stack);                        \
       +int ltk_stack_push_##name(                                                        \
       +    struct ltk_stack_##name *stack, type1 data1, type2 data2);                        \
       +type2 ltk_stack_top2_##name(struct ltk_stack_##name *stack, type2 def);                \
       +struct ltk_stack_##name *ltk_stack_create_##name(size_t max);
        
       -#define LTK_INIT_STACK_IMPL(name, type1, type2, data1, data2)                        \
       -static ltk_stack_##name *                                                        \
       -ltk_stack_create_##name (size_t max) {                                                \
       -        ltk_stack_##name *stack;                                                \
       -        stack = malloc(sizeof(ltk_stack_##name));                                \
       +#define LTK_STACK_INIT_IMPL(name, type1, type2, data1, data2)                        \
       +struct ltk_stack_##name *                                                        \
       +ltk_stack_create_##name(size_t max) {                                                \
       +        struct ltk_stack_##name *stack;                                                \
       +        stack = malloc(sizeof(struct ltk_stack_##name));                        \
                if (!stack) goto error;                                                        \
                                                                                        \
       -        stack->data1 = malloc(sizeof(data1) * max);                                \
       +        stack->data1 = malloc(sizeof(type1) * max);                                \
                if (!stack->data1) goto error;                                                \
       -        stack->data2 = malloc(sizeof(data2) * max);                                \
       +        stack->data2 = malloc(sizeof(type2) * max);                                \
                if (!stack->data2) goto error;                                                \
                                                                                        \
                stack->size = 0;                                                        \
       t@@ -57,12 +60,12 @@ ltk_stack_create_##name (size_t max) {                                                \
                                                                                        \
                return stack;                                                                \
        error:                                                                                \
       -        (void)fprintf("Cannot allocate memory for stack\n");                        \
       +        (void)fprintf(stderr, "Cannot allocate memory for stack\n");                \
                exit(1);                                                                \
        }                                                                                \
                                                                                        \
       -static int                                                                        \
       -ltk_stack_pop_##name(ltk_stack_##name *stack) {                                        \
       +int                                                                                \
       +ltk_stack_pop_##name(struct ltk_stack_##name *stack) {                                \
                if (!stack->size)                                                        \
                        return 0;                                                        \
                                                                                        \
       t@@ -71,24 +74,25 @@ ltk_stack_pop_##name(ltk_stack_##name *stack) {                                        \
          return 1;                                                                        \
        }                                                                                \
                                                                                        \
       -static data1                                                                        \
       -ltk_stack_top1_##name(ltk_stack##name *stack, type1 default) {                        \
       +type1                                                                                \
       +ltk_stack_top1_##name(struct ltk_stack_##name *stack, type1 def) {                \
                if (!stack->size)                                                        \
       -                return default;                                                        \
       +                return def;                                                        \
                                                                                        \
                return stack->data1[stack->size];                                        \
        }                                                                                \
                                                                                        \
       -static data2                                                                        \
       -ltk_stack_top2_##name(ltk_stack##name *stack, type2 default) {                        \
       +type2                                                                                \
       +ltk_stack_top2_##name(struct ltk_stack_##name *stack, type2 def) {                \
                if (!stack->size)                                                        \
       -                return default;                                                        \
       +                return def;                                                        \
                                                                                        \
                return stack->data2[stack->size];                                        \
        }                                                                                \
                                                                                        \
       -static int                                                                        \
       -ltk_stack_push_##name(ltk_stack_##name *stack, type1 data1, type2 data2) {        \
       +int                                                                                \
       +ltk_stack_push_##name(struct ltk_stack_##name *stack,                                \
       +    type1 data1, type2 data2) {                                                        \
                if (stack->size == stack->capacity)                                        \
                        return 0;                                                        \
                                                                                        \
       t@@ -99,9 +103,11 @@ ltk_stack_push_##name(ltk_stack_##name *stack, type1 data1, type2 data2) {        \
                return 1;                                                                \
        }                                                                                \
                                                                                        \
       -static void                                                                        \
       -ltk_stack_destroy_##name(ltk_stack_##name *stack) {                                \
       +void                                                                                \
       +ltk_stack_destroy_##name(struct ltk_stack_##name *stack) {                        \
          free(stack->data1);                                                                \
          free(stack->data2);                                                                \
          free(stack);                                                                        \
        }
       +
       +#endif /* _LTK_STACK_H_ */
   DIR diff --git a/text_buffer.c b/text_buffer.c
       t@@ -21,8 +21,6 @@
         * SOFTWARE.
         */
        
       -/* NOTE: THIS DOESN'T HAVE ANY USABLE CODE YET! */
       -
        #include <stdio.h>
        #include <stdlib.h>
        #include <stdint.h>
       t@@ -35,8 +33,11 @@
        #include <fribidi.h>
        #include <harfbuzz/hb.h>
        #include <harfbuzz/hb-ot.h>
       -#include "textedit_wip.h"
        #include "text-common.h"
       +#include "gap_buffer.h"
       +#include "array.h"
       +#include "stack.h"
       +#include "text_buffer.h"
        #include "ltk.h"
        
        extern Ltk *ltk_global;
       t@@ -46,11 +47,13 @@ LTK_GAP_BUFFER_INIT_IMPL(script, hb_script_t)
        LTK_GAP_BUFFER_INIT_IMPL(int, int)
        LTK_ARRAY_INIT_IMPL(level, FriBidiLevel)
        LTK_ARRAY_INIT_IMPL(int, int)
       -LTK_STACK_INIT_IMPL(script, int, hb_script_t, pair_index, script);
       +LTK_STACK_INIT_IMPL(script, int, hb_script_t, pair_index, script)
        
        /* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
       +/* FIXME: rename this once everything is cleaned up (currently conflicts with the
       +   old render function */
        void
       -ltk_render_text_line(
       +ltk_render_text_line_new(
                struct ltk_text_line *tl,
                int max_width,
                Display *dpy,
       t@@ -69,11 +72,11 @@ ltk_render_text_line(
                struct ltk_text_run *cur = tl->first_run;
                do {
                        for (int i = 0; i < cur->num_glyphs; i++) {
       -                        cur_x += cur->glyphs[i]->x_advance;
       +                        cur_x += cur->glyphs[i].x_advance;
                                if (cur_x > max_width) {
                                        int j = 0;
                                        for (j = i; j >= 0; j--) {
       -                                        if (cur->glyphs[j]->cluster != cur->glyphs[i]->cluster) {
       +                                        if (cur->glyphs[j].cluster != cur->glyphs[i].cluster) {
                                                        /* must increase one again so the actual
                                                           next character is used */
                                                        j++;
       t@@ -93,7 +96,7 @@ ltk_render_text_line(
                XGetWindowAttributes(dpy, window, &attrs);
                int depth = attrs.depth;
                tl->img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * tl->wrap_indeces->len, 32, 0);
       -        tl->img->data = calloc(img->bytes_per_line, img->height);
       +        tl->img->data = calloc(tl->img->bytes_per_line, tl->img->height);
                XInitImage(tl->img);
        
                int b;
       t@@ -109,6 +112,7 @@ ltk_render_text_line(
        
                cur = tl->first_run;
                int x, y;
       +        double a;
                int cur_line_x = 0;
                int cur_line = 0;
                LtkGlyph *glyph;
       t@@ -118,7 +122,7 @@ ltk_render_text_line(
                   to do in that case */
                while (cur) {
                        for (int k = 0; k < cur->len; k++) {
       -                        glyph = cur->glyphs[k];
       +                        glyph = &cur->glyphs[k];
                                if (cur_line < tl->wrap_indeces->len - 1 &&
                                    glyph->cluster >= tl->wrap_indeces->buf[cur_line + 1]) {
                                        cur_line++;
       t@@ -221,7 +225,7 @@ ltk_resolve_scripts(struct ltk_text_line *tl) {
                int last_set_index = -1;
                hb_script_t last_script = HB_SCRIPT_INVALID;
                hb_script_t cur_script;
       -        ltk_stack_script *stack = NULL;
       +        struct ltk_stack_script *stack = NULL;
                hb_unicode_funcs_t* unicode_funcs = hb_unicode_funcs_get_default();
        
                stack = ltk_stack_create_script(tl->len);
       t@@ -272,14 +276,14 @@ ltk_resolve_scripts(struct ltk_text_line *tl) {
                }
        
                /* Loop backwards and change any remaining Common or Inherit characters to
       -        * take the script if the next character.
       +        * take the script of the next character.
                * https://github.com/HOST-Oman/libraqm/issues/95
                */
                hb_script_t scr;
                for (int i = tl->len - 2; i >= 0;  --i) {
                        scr = ltk_gap_buffer_get_script(tl->scripts, i);
                        if (scr == HB_SCRIPT_INHERITED || scr == HB_SCRIPT_COMMON) {
       -                        ltk_gap_buffer_set_script(tl->scripts,
       +                        ltk_gap_buffer_set_script(tl->scripts, i,
                                    ltk_gap_buffer_get_script(tl->scripts, i + 1));
                        }
                }
       t@@ -292,7 +296,7 @@ ltk_resolve_scripts(struct ltk_text_line *tl) {
        /* End stuff stolen from raqm */
        /* Update: That's a lie; much more is stolen from raqm. */
        
       -static struct
       +static struct ltk_text_run *
        ltk_text_run_create(size_t start_index, size_t len, hb_script_t script, hb_direction_t dir) {
                struct ltk_text_run *run = malloc(sizeof(struct ltk_text_run));
                if (!run) {
       t@@ -312,8 +316,8 @@ ltk_text_line_itemize(struct ltk_text_line *tl) {
                ltk_resolve_scripts(tl);
                struct ltk_text_run *first_run = NULL;
                struct ltk_text_run *cur_run = NULL;
       -        FriBidilevel last_level;
       -        FriBidilevel cur_level;
       +        FriBidiLevel last_level;
       +        FriBidiLevel cur_level;
                hb_script_t last_script;
                hb_script_t cur_script;
                size_t start_index = 0;
       t@@ -322,12 +326,12 @@ ltk_text_line_itemize(struct ltk_text_line *tl) {
                int par_is_rtl = FRIBIDI_IS_RTL(tl->dir);
                while (start_index < tl->len) {
                        end_index = start_index;
       -                cur_level = last_level = ltk_gap_buffer_get_level(tl->bidi_levels, start_index);
       +                cur_level = last_level = tl->bidi_levels->buf[start_index];
                        cur_script = last_script = ltk_gap_buffer_get_script(tl->scripts, start_index);
                        while (end_index < tl->len &&
                            cur_level == last_level && cur_script == last_script) {
                                end_index++;
       -                        cur_level = ltk_gap_buffer_get_level(tl->bidi_levels, end_index);
       +                        cur_level = tl->bidi_levels->buf[end_index];
                                cur_script = ltk_gap_buffer_get_script(tl->scripts, end_index);
                        }
                        dir = HB_DIRECTION_LTR;
       t@@ -375,14 +379,14 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
                tr->num_glyphs = 0;
        
                buf = hb_buffer_create();
       -        hb_buffer_set_direction(buf, run->dir);
       -        hb_buffer_set_script(buf, run->script);
       +        hb_buffer_set_direction(buf, tr->dir);
       +        hb_buffer_set_script(buf, tr->script);
                /* WARNING: vis_buf has to be normalized (without gap) for this! */
       -        hb_buffer_add_codepoints(buf, tl->vis-buf, tl->len, tr->start_index, tr->len);
       +        hb_buffer_add_codepoints(buf, tl->vis_buf, tl->len, tr->start_index, tr->len);
                /* According to https://harfbuzz.github.io/the-distinction-between-levels-0-and-1.html
                 * this should be level 1 clustering instead of level 0 */
                hb_buffer_set_cluster_level(buf, HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS);
       -        hb_shape(font->hb, buf, NULL, 0);
       +        hb_shape(tr->font->hb, buf, NULL, 0);
                ginf = hb_buffer_get_glyph_infos(buf, &tr->num_glyphs);
                gpos = hb_buffer_get_glyph_positions(buf, &tr->num_glyphs);
                float scale = stbtt_ScaleForMappingEmToPixels(&tr->font->info, font_size);
       t@@ -390,9 +394,9 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
                int x_min = INT_MAX, x_max = INT_MIN, y_min = INT_MAX, y_max = INT_MIN;
                int x_abs = 0, y_abs = 0, x1_abs, y1_abs, x2_abs, y2_abs;
                /* magic, do not touch */
       -        tr->glyphs = malloc(sizeof(LtkGlyph) * num_glyph);
       +        tr->glyphs = malloc(sizeof(LtkGlyph) * tr->num_glyphs);
                if (!tr->glyphs) {
       -                (void)fprintf("Cannot allocate space for glyphs.\n");
       +                (void)fprintf(stderr, "Cannot allocate space for glyphs.\n");
                        exit(1);
                }
                /* FIXME: should x_max be calculated using glyph->info->w?
       t@@ -402,7 +406,7 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
                for (int i = 0; i < tr->num_glyphs; i++) {
                        gi = &ginf[i];
                        gp = &gpos[i];
       -                glyph = tr->glyphs[i];
       +                glyph = &tr->glyphs[i];
                        glyph->cluster = gi->cluster;
                        glyph->info = ltk_get_glyph_info(tr->font, gi->codepoint, scale, glyph_cache);
                        glyph->info->refs++;
       t@@ -448,7 +452,7 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr,
        
        static void
        ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
       -        struct ltk_text_run *run = tl->runs;
       +        struct ltk_text_run *run = tl->first_run;
                tl->y_max = INT_MIN;
                tl->y_min = INT_MAX;
                tl->w = tl->h = 0;
       t@@ -473,26 +477,26 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
                        run->font = kh_value(tm->font_cache, k);
                        FcPatternDestroy(match);
                        FcPatternDestroy(pat);
       -                ltk_text_run_shape(tm, run, tl->font_size, font_id, &y_max);
       +                ltk_text_run_shape(tm, run, tl, tl->font_size, font_id, &y_max);
                        if (tl->y_max < y_max)
                                tl->y_max = y_max;
                        /* tr->start_y is -y_min */
       -                if (tl->y_min > -tr->start_y)
       -                        tl->y_min = -tr->start_y;
       -                tl->w += tr->w;
       +                if (tl->y_min > -run->start_y)
       +                        tl->y_min = -run->start_y;
       +                tl->w += run->w;
                        run = run->next;
                };
                tl->h = tl->y_max - tl->y_min;
        
                /* calculate the actual position of the characters */
       -        run = tl->runs;
       +        run = tl->first_run;
                int x = 0;
                LtkGlyph *glyph;
                while (run) {
                        int cur_x = x + run->start_x;
                        int cur_y = tl->h - tl->y_max; /* baseline (I think?) */
                        for (int i = 0; i < run->len; i++) {
       -                        glyph = run->glyphs[i];
       +                        glyph = &run->glyphs[i];
                                glyph->x_abs = cur_x + glyph->info->xoff + glyph->x_offset;
                                glyph->y_abs = cur_y - glyph->info->yoff - glyph->y_offset;
                                cur_x += glyph->x_advance;
       t@@ -503,21 +507,19 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
                }
        }
        
       -/* FIXME: Don't destroy fonts, etc. every time the line is recalculated */
       -/* Maybe decrease font refs but don't destroy until after the runs have been re-shaped */
        void
       -ltk_text_run_destroy(struct ltk_text_line *tl, struct ltk_text_run *tr) {
       +ltk_text_run_destroy(struct ltk_text_run *tr) {
                khash_t(glyphinfo) *gcache;
                LtkFont *font;
                LtkGlyph *glyph;
                khint_t k;
       -        k = kh_get(glyphinfo, ltk_global->tm->glyph_cache, tr->font_id << 16 + tl->font_size);
       +        k = kh_get(glyphinfo, ltk_global->tm->glyph_cache, tr->font_id << 16 + tr->font_size);
                gcache = kh_value(ltk_global->tm->glyph_cache, k);
                for (int i = 0; i < tr->len; i++) {
       -                glyph = tr->glyphs[i];
       +                glyph = &tr->glyphs[i];
                        if (--glyph->info->refs < 1) {
       -                        k = kh_get(glyphinfo, cache, glyph->info->id);
       -                        kh_del(glyphinfo, cache, k);
       +                        k = kh_get(glyphinfo, gcache, glyph->info->id);
       +                        kh_del(glyphinfo, gcache, k);
                                ltk_destroy_glyph_info(glyph->info);
                        }
                }
       t@@ -532,9 +534,9 @@ ltk_text_run_destroy(struct ltk_text_line *tl, struct ltk_text_run *tr) {
        }
        
        void
       -ltk_text_line_destroy_runs(struct ltk_text_line *tl) {
       +ltk_text_line_destroy_runs(struct ltk_text_run *runs) {
                struct ltk_text_run *cur, *last;
       -        cur = tl->first_run;
       +        cur = runs;
                while (cur) {
                        last = cur;
                        ltk_text_run_destroy(cur);
       t@@ -547,6 +549,10 @@ ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
                ltk_gap_buffer_clear_uint32(tl->vis_buf);
                ltk_gap_buffer_clear_int(tl->log2vis);
                ltk_gap_buffer_clear_int(tl->vis2log);
       +        /* yeah, this is hacky */
       +        tl->vis_buf->len = tl->vis_buf->buf_size;
       +        tl->log2vis->len = tl->log2vis->buf_size;
       +        tl->vis2log->len = tl->vis2log->buf_size;
                size_t gap_pos = tl->log_buf->gap_left;
                size_t gap_end = tl->log_buf->buf_size - tl->log_buf->gap_size;
                ltk_gap_buffer_move_gap_uint32(tl->log_buf, gap_end);
       t@@ -555,9 +561,13 @@ ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
                    &tl->dir, tl->vis_buf, tl->log2vis, tl->vis2log, tl->bidi_levels
                );
                ltk_gap_buffer_move_gap_uint32(tl->log_buf, gap_pos);
       -        ltk_text_line_destroy_runs(tl); /* FIXME: IMPLEMENT */
       +        struct ltk_text_run *old_runs = tl->first_run;
                ltk_text_line_itemize(tl);
                ltk_text_line_shape(tm, tl);
       +        /* this needs to be done after shaping so the fonts, etc. aren't
       +           removed if their reference counts drop and then loaded again
       +           right afterwards */
       +        ltk_text_line_destroy_runs(old_runs);
        }
        
        
       t@@ -579,7 +589,7 @@ ltk_text_line_insert_text(struct ltk_text_line *tl, uint32_t *text, size_t len) 
                }
                */
                ltk_gap_buffer_insert_uint32(tl->log_buf, text, 0, len);
       -        if (len > tl->scripts->gap-size)
       +        if (len > tl->scripts->gap_size)
                        ltk_gap_buffer_resize_gap_script(tl->scripts, len + 8);
                hb_unicode_funcs_t *ufuncs = hb_unicode_funcs_get_default();
                for (int i = 0; i < len; i++) {
       t@@ -593,9 +603,10 @@ ltk_text_line_insert_text(struct ltk_text_line *tl, uint32_t *text, size_t len) 
                if (len > tl->vis2log->gap_size)
                        ltk_gap_buffer_resize_gap_int(tl->vis2log, len + 8);
                if (len + tl->bidi_levels->len > tl->bidi_levels->buf_size)
       -                ltk_array_resize_levels(tl->bidi_levels, tl->bidi_levels->len + len + 8);
       +                ltk_array_resize_level(tl->bidi_levels, tl->bidi_levels->len + len + 8);
                tl->len += len;
       -        ltk_text_line_recalculate(tl);
       +        /* FIXME: Why am I passing tm? It's global anyways */
       +        ltk_text_line_recalculate(tl, ltk_global->tm);
        }
        
        /* must be NULL-terminated */
       t@@ -604,9 +615,9 @@ ltk_text_line_insert_utf8(struct ltk_text_line *tl, char *text) {
                size_t len = u8_strlen(text);
                uint32_t *new = malloc(sizeof(uint32_t) * len);
                if (!new) {
       -                (void)fprintf("Error allocating memory for string\n");
       +                (void)fprintf(stderr, "Error allocating memory for string\n");
                        exit(1);
       -        ]
       +        }
                size_t inc = 0;
                for (int i = 0; i < len; i++)
                        new[i] = u8_nextmemchar(text, &inc);
       t@@ -623,9 +634,9 @@ ltk_text_line_create(void) {
                line->vis_buf = ltk_gap_buffer_create_uint32();
                line->log2vis = ltk_gap_buffer_create_int();
                line->vis2log = ltk_gap_buffer_create_int();
       -        line->bidi_levels = ltk_array_create_levels(8);
       +        line->bidi_levels = ltk_array_create_level(8);
                line->wrap_indeces = ltk_array_create_int(1);
       -        line->runs = NULL;
       +        line->first_run = NULL;
                line->cur_run = NULL;
                line->next = NULL;
                line->height = 0;
       t@@ -657,7 +668,7 @@ ltk_text_line_destroy(struct ltk_text_line *tl) {
                ltk_gap_buffer_destroy_int(tl->vis2log);
                ltk_array_destroy_level(tl->bidi_levels);
                ltk_array_destroy_int(tl->wrap_indeces);
       -        ltk_text_line_destroy_runs(tl);
       +        ltk_text_line_destroy_runs(tl->first_run);
                if (tl->img) XDestroyImage(tl->img);
                free(tl);
        }
   DIR diff --git a/text_buffer.h b/text_buffer.h
       t@@ -21,8 +21,8 @@
         * SOFTWARE.
         */
        
       -#ifndef _TEXT_HB_H_
       -#define _TEXT_HB_H_
       +#ifndef _TEXT_BUFFER_H_
       +#define _TEXT_BUFFER_H_
        
        /*
        Requires the following includes:
       t@@ -31,10 +31,6 @@ Requires the following includes:
        <fontconfig/fontconfig.h>
        */
        
       -#include "gap_buffer.h"
       -#include "array.h"
       -#include "stack.h"
       -
        /* Note: hb_script_t and FriBidiLevel are really just uint32_t's, but
           I'm not sure if I should rely on that, so they're separate here */
        LTK_GAP_BUFFER_INIT_DECL(uint32, uint32_t)
       t@@ -42,7 +38,7 @@ LTK_GAP_BUFFER_INIT_DECL(script, hb_script_t)
        LTK_GAP_BUFFER_INIT_DECL(int, int)
        LTK_ARRAY_INIT_DECL(level, FriBidiLevel)
        LTK_ARRAY_INIT_DECL(int, int)
       -LTK_STACK_INIT_DECL(script, int, hb_script_t, pair_index, script);
       +LTK_STACK_INIT_DECL(script, int, hb_script_t, pair_index, script)
        
        struct ltk_text_run {
                LtkGlyph *glyphs;
       t@@ -50,15 +46,16 @@ struct ltk_text_run {
                struct ltk_text_run *next;
                struct ltk_text_run *last;
                size_t start_index;
       -        size_t len;
       +        size_t len; /* FIXME: THIS IS NOT THE NUMBER OF GLYPHS; IT IS THE ACTUAL NUMBER OF CHARACTERS REPRESENTED BY THIS RUN */
                int start_x;
                int start_y;
                int w;
                LtkFont *font;
                uint16_t font_id;
       +        uint16_t font_size;
                hb_script_t script;
                hb_direction_t dir;
       -}
       +};
        
        struct ltk_text_line {
                struct ltk_gap_buffer_uint32 *log_buf; /* buffer of the logical text */
       t@@ -72,7 +69,7 @@ struct ltk_text_line {
                struct ltk_text_run *cur_run; /* current node in the linked list of runs */
                struct ltk_text_line *next; /* next text line in the buffer */
                unsigned int height; /* height of the line (including wrapping) */
       -        FribidiCharType dir; /* overall paragraph direction */
       +        FriBidiCharType dir; /* overall paragraph direction */
                struct ltk_array_int *wrap_indeces;
                size_t len;
                uint16_t font_size;
       t@@ -88,3 +85,5 @@ struct ltk_text_buffer {
                struct ltk_text_line *cur_line;
                unsigned int line_gap;
        };
       +
       +#endif /* _TEXT_BUFFER_H_ */
   DIR diff --git a/text_edit.c b/text_edit.c
       t@@ -30,7 +30,7 @@ ltk_draw_text_edit(LtkTextEdit *te) {
                LtkRect rect = te->widget.rect;
                LtkWindow *window = te->widget.window;
                if (!te->tl->img)
       -                ltk_render_text_line(te->tl, rect.w, ltk_global->display, window->xwindow, window->gc, ltk_global->colormap, fg, bg);
       +                ltk_render_text_line_new(te->tl, rect.w, ltk_global->display, window->xwindow, window->gc, ltk_global->colormap, fg, bg);
                XPutImage(ltk_global->display, window->xwindow, window->gc, te->tl->img, 0, 0, rect.x, rect.y, te->tl->w, te->tl->h);
        }