URI: 
       tFix infinite loop in text wrapping; standardize some function names - 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 6dd04b169616da62128fa4e952b005d6139c9100
   DIR parent 212c90119c1d23d23f18fc5ed5c5ab5af494b79f
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Thu, 21 May 2020 20:41:43 +0200
       
       Fix infinite loop in text wrapping; standardize some function names
       
       Diffstat:
         M button.c                            |      21 +++++++++++----------
         M button.h                            |       6 +++---
         M ltk.c                               |       6 ++++--
         M test1.c                             |      13 ++++---------
         M text_buffer.c                       |      17 ++++++++++++-----
         M text_edit.c                         |      14 +++++++-------
         M text_edit.h                         |       7 +++----
       
       7 files changed, 44 insertions(+), 40 deletions(-)
       ---
   DIR diff --git a/button.c b/button.c
       t@@ -38,8 +38,8 @@
        
        extern Ltk *ltk_global;
        
       -void ltk_button_ini_handler(LtkTheme *theme, const char *prop, const char *value)
       -{
       +void
       +ltk_button_ini_handler(LtkTheme *theme, const char *prop, const char *value) {
                if (theme->button == NULL) {
                        theme->button = malloc(sizeof(LtkButtonTheme));
                }
       t@@ -76,8 +76,8 @@ void ltk_button_ini_handler(LtkTheme *theme, const char *prop, const char *value
                }
        }
        
       -void ltk_draw_button(LtkButton *button)
       -{
       +void
       +ltk_button_draw(LtkButton *button) {
                LtkButtonTheme *theme = ltk_global->theme->button;
                LtkWindow *window = button->widget.window;
                LtkRect rect = button->widget.rect;
       t@@ -150,15 +150,15 @@ void ltk_draw_button(LtkButton *button)
                XPutImage(ltk_global->display, window->xwindow, window->gc, img, 0, 0, text_x, text_y, button->tl->w, button->tl->h);
        }
        
       -LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callback) (void *, XEvent, void *), void *data)
       -{
       +LtkButton *
       +ltk_button_create(LtkWindow *window, const char *text, void (*callback) (void *, XEvent, void *), void *data) {
                LtkButton *button = malloc(sizeof(LtkButton));
        
                if (button == NULL) {
                        ltk_fatal("ERROR: Unable to allocate memory for LtkButton.\n");
                }
        
       -        ltk_fill_widget_defaults(&button->widget, window, &ltk_draw_button, &ltk_destroy_button, 1);
       +        ltk_fill_widget_defaults(&button->widget, window, &ltk_button_draw, &ltk_button_destroy, 1);
                button->widget.mouse_release = &ltk_button_mouse_release;
        
                button->callback = callback;
       t@@ -179,8 +179,8 @@ LtkButton *ltk_create_button(LtkWindow *window, const char *text, void (*callbac
                return button;
        }
        
       -void ltk_destroy_button(LtkButton *button)
       -{
       +void
       +ltk_button_destroy(LtkButton *button) {
                if (!button) {
                        (void)printf("WARNING: Tried to destroy NULL button.\n");
                }
       t@@ -195,7 +195,8 @@ void ltk_destroy_button(LtkButton *button)
        
        /* FIXME: is the fixme below supposed to be for the function above? */
        /* FIXME: ungrid button if gridded */
       -void ltk_button_mouse_release(LtkButton *button, XEvent event) {
       +void
       +ltk_button_mouse_release(LtkButton *button, XEvent event) {
                if (button->widget.state == LTK_HOVERACTIVE && button->callback) {
                        button->callback(button, event, button->data);
                }
   DIR diff --git a/button.h b/button.h
       t@@ -61,11 +61,11 @@ typedef struct LtkButtonTheme {
                XColor fill_disabled;
        } LtkButtonTheme;
        
       -void ltk_draw_button(LtkButton *button);
       +void ltk_button_draw(LtkButton *button);
        
       -LtkButton *ltk_create_button(LtkWindow * window, const char *text, void (*callback) (void *, XEvent, void *), void *data);
       +LtkButton *ltk_button_create(LtkWindow * window, const char *text, void (*callback) (void *, XEvent, void *), void *data);
        
       -void ltk_destroy_button(LtkButton *button);
       +void ltk_button_destroy(LtkButton *button);
        
        void ltk_button_mouse_release(LtkButton *button, XEvent event);
        
   DIR diff --git a/ltk.c b/ltk.c
       t@@ -185,13 +185,15 @@ void ltk_window_other_event(void *widget, XEvent event)
                        unsigned int w, h;
                        w = event.xconfigure.width;
                        h = event.xconfigure.height;
       +                int orig_w = window->rect.w;
       +                int orig_h = window->rect.h;
                        if (ptr && ptr->resize
       -                    && (window->rect.w != w || window->rect.h != h)) {
       +                    && (orig_w != w || orig_h != h)) {
                                window->rect.w = w;
                                window->rect.h = h;
                                ptr->rect.w = w;
                                ptr->rect.h = h;
       -                        ptr->resize(ptr);
       +                        ptr->resize(ptr, orig_w, orig_h);
                                ltk_redraw_window(window);
                        }
                }
   DIR diff --git a/test1.c b/test1.c
       t@@ -21,7 +21,6 @@ int main(int argc, char *argv[])
        {
                ltk_init("themes/default.ini");
                LtkWindow *window1 = ltk_create_window("Cool Window!", 0, 0, 500, 500);
       -/*    LtkWindow *window2 = ltk_create_window("Cool Window!", 0, 0, 500, 500);*/
                LtkGrid *grid1 = ltk_create_grid(window1, 2, 2);
                window1->root_widget = grid1;
                ltk_set_row_weight(grid1, 0, 1);
       t@@ -29,18 +28,14 @@ int main(int argc, char *argv[])
                ltk_set_column_weight(grid1, 0, 1);
                ltk_set_column_weight(grid1, 1, 1);
                /* Test callback functions */
       -        LtkButton *button1 = ltk_create_button(window1, "I'm a button!", &bob1, NULL);
       +        LtkButton *button1 = ltk_button_create(window1, "I'm a button!", &bob1, NULL);
                ltk_grid_widget(button1, grid1, 0, 0, 1, 1, LTK_STICKY_LEFT | LTK_STICKY_RIGHT);
                /* Test manual callback functions */
       -        LtkButton *button2 = ltk_create_button(window1, "I'm a button!", NULL, NULL);
       +        LtkButton *button2 = ltk_button_create(window1, "I'm a button!", NULL, NULL);
                button2->widget.mouse_release = &bob2;
                ltk_grid_widget(button2, grid1, 0, 1, 1, 1, LTK_STICKY_TOP | LTK_STICKY_BOTTOM);
       -        //LtkButton *button3 = ltk_create_button(window1, "I'm a button!", NULL);
       -        //ltk_grid_widget(button3, grid1, 1, 0, 1, 1, LTK_STICKY_TOP | LTK_STICKY_BOTTOM | LTK_STICKY_RIGHT);
       -        //LtkButton *button4 = ltk_create_button(window1, "I'm a button!", NULL);
       -        //LtkButton *button4 = ltk_create_button(window1, "پَیدایش", NULL);
       -        LtkTextEdit *edit = ltk_create_text_edit(window1, "ہمارے بارے میں blabla bla");
       -        LtkButton *button4 = ltk_create_button(window1, "ہمارے بارے میں blablabla", &bob3, edit);
       +        LtkTextEdit *edit = ltk_text_edit_create(window1, "ہمارے بارے میں blabla bla");
       +        LtkButton *button4 = ltk_button_create(window1, "ہمارے بارے میں blablabla", &bob3, edit);
                ltk_grid_widget(button4, grid1, 1, 0, 1, 1, LTK_STICKY_TOP | LTK_STICKY_BOTTOM | LTK_STICKY_RIGHT);
                ltk_grid_widget(edit, grid1, 1, 1, 1, 1, LTK_STICKY_LEFT | LTK_STICKY_BOTTOM | LTK_STICKY_TOP | LTK_STICKY_RIGHT);
                ltk_mainloop();
   DIR diff --git a/text_buffer.c b/text_buffer.c
       t@@ -77,6 +77,7 @@ ltk_text_line_cleanup_soft_lines(struct ltk_array_line *soft_lines, int old_len)
                ltk_array_resize_line(soft_lines, soft_lines->len);
        }
        
       +/* FIXME: this is a few pixels off! */
        void
        ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
                struct timeval t1, t2;
       t@@ -129,9 +130,11 @@ ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
                                                /* FIXME: fix behavior when line isn't wide enough for single char
                                                   (currently causes infinite loop) */
                                                for (int j = i; j < cur->num_glyphs; j++) {
       -                                                if (cur->glyphs[j].cluster != glyph->cluster || j == cur->num_glyphs - 1) {
       +                                                if (cur->glyphs[j].cluster != glyph->cluster ||
       +                                                    j == cur->num_glyphs - 1 || sl->len == 0) {
                                                                if (j == cur->num_glyphs - 1 &&
       -                                                            cur->glyphs[j].cluster == glyph->cluster) {
       +                                                            cur->glyphs[j].cluster == glyph->cluster &&
       +                                                            sl->len > 0) {
                                                                        i = j;
                                                                        last_linebreak = cur_start;
                                                                } else {
       t@@ -172,8 +175,11 @@ ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
                                        int cur_w = sl->w + glyph->x_abs + glyph->info->w - cur_start;
                                        if (cur_w > max_width) {
                                                for (int j = i; j >= 0; j--) {
       -                                                if (cur->glyphs[j].cluster != glyph->cluster || j == 0) {
       -                                                        if (j == 0 && cur->glyphs[j].cluster == glyph->cluster) {
       +                                                if (cur->glyphs[j].cluster != glyph->cluster ||
       +                                                    j == 0 || sl->len == 0) {
       +                                                        if (j == 0 &&
       +                                                            cur->glyphs[j].cluster == glyph->cluster &&
       +                                                            sl->len > 0) {
                                                                        i = j;
                                                                        last_linebreak = cur_start;
                                                                } else {
       t@@ -252,7 +258,7 @@ ltk_soft_line_draw_glyph(LtkGlyph *glyph, XImage *img, struct ltk_soft_line *sl,
                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 < 0 || x < 0)
       +                        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;
       t@@ -263,6 +269,7 @@ ltk_soft_line_draw_glyph(LtkGlyph *glyph, XImage *img, struct ltk_soft_line *sl,
                }
        }
        
       +/* FIXME: the glyph drawing function sometimes receives negative x positions */
        /* FIXME: Fix memory leaks... */
        XImage *
        ltk_text_line_render(
   DIR diff --git a/text_edit.c b/text_edit.c
       t@@ -40,14 +40,14 @@
        extern Ltk *ltk_global;
        
        void
       -ltk_draw_text_edit(LtkTextEdit *te) {
       +ltk_text_edit_draw(LtkTextEdit *te) {
                if (!te->img)
                        ltk_text_edit_resize(te, 0, 0);
                LtkRect rect = te->widget.rect;
                LtkWindow *window = te->widget.window;
                int x = rect.x;
                if (te->tl->dir == HB_DIRECTION_RTL)
       -                x += rect.w - te->tl->w_wrapped;
       +                x += rect.w - te->img->width;
                XSetForeground(ltk_global->display, window->gc, ltk_global->theme->window->bg.pixel);
                XFillRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h);
                XPutImage(
       t@@ -64,7 +64,7 @@ ltk_draw_text_edit(LtkTextEdit *te) {
        void
        ltk_text_edit_resize(LtkTextEdit *te, int orig_w, int orig_h) {
                if (te->tl->soft_lines->len == 1 &&
       -            te->widget.rect.w >= te->tl->w_wrapped && orig_w >= te->tl->w_wrapped)
       +            te->widget.rect.w >= te->img->width && orig_w >= te->img->width)
                        return;
                XColor fg = ltk_global->theme->window->fg;
                XColor bg = ltk_global->theme->window->bg;
       t@@ -91,12 +91,12 @@ ltk_text_edit_tmp(LtkTextEdit *te, XEvent event) {
        #endif
        
        LtkTextEdit *
       -ltk_create_text_edit(LtkWindow *window, const char *text) {
       +ltk_text_edit_create(LtkWindow *window, const char *text) {
                LtkTextEdit *te = malloc(sizeof(LtkTextEdit));
                if (!te)
                        ltk_fatal("ERROR: Unable to allocate memory for LtkTextEdit.\n");
                te->img = NULL;
       -        ltk_fill_widget_defaults(&te->widget, window, &ltk_draw_text_edit, &ltk_destroy_text_edit, 1);
       +        ltk_fill_widget_defaults(&te->widget, window, &ltk_text_edit_draw, &ltk_text_edit_destroy, 1);
                /*te->widget.mouse_press = &ltk_text_edit_tmp;*/
                te->widget.resize = &ltk_text_edit_resize;
                te->tl = ltk_text_line_create(20);
       t@@ -110,10 +110,10 @@ ltk_text_edit_insert_text(LtkTextEdit *te, const char *text) {
                ltk_text_line_insert_utf8(te->tl, 0, text);
                ltk_text_edit_resize(te, 0, 0);
                /* FIXME: Need to "queue redraw" for whole window */
       -        ltk_draw_text_edit(te);
       +        ltk_text_edit_draw(te);
        }
        
       -void ltk_destroy_text_edit(LtkTextEdit *te) {
       +void ltk_text_edit_destroy(LtkTextEdit *te) {
                ltk_text_line_destroy(te->tl);
                if (te->img) XDestroyImage(te->img);
                free(te);
   DIR diff --git a/text_edit.h b/text_edit.h
       t@@ -30,11 +30,10 @@ typedef struct {
                XImage *img;
        } LtkTextEdit;
        
       -/* FIXME: standardize ltk_<widget>_destroy, etc. instead of ltk_destroy_<widget> */
       -void ltk_draw_text_edit(LtkTextEdit *te);
       -LtkTextEdit *ltk_create_text_edit(LtkWindow *window, const char *text);
       +void ltk_text_edit_draw(LtkTextEdit *te);
       +LtkTextEdit *ltk_text_edit_create(LtkWindow *window, const char *text);
        void ltk_text_edit_resize(LtkTextEdit *te, int orig_w, int orig_h);
        void ltk_text_edit_insert_text(LtkTextEdit *te, const char *text);
       -void ltk_destroy_text_edit(LtkTextEdit *te);
       +void ltk_text_edit_destroy(LtkTextEdit *te);
        
        #endif /* _LTK_TEXT_EDIT_H_ */