commit 6dd04b169616da62128fa4e952b005d6139c9100
parent 212c90119c1d23d23f18fc5ed5c5ab5af494b79f
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:
7 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/button.c b/button.c
@@ -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));
 	}
@@ -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;
@@ -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, <k_draw_button, <k_destroy_button, 1);
+	ltk_fill_widget_defaults(&button->widget, window, <k_button_draw, <k_button_destroy, 1);
 	button->widget.mouse_release = <k_button_mouse_release;
 
 	button->callback = callback;
@@ -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");
 	}
@@ -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);
 	}
diff --git a/button.h b/button.h
@@ -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);
 
diff --git a/ltk.c b/ltk.c
@@ -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);
 		}
 	}
diff --git a/test1.c b/test1.c
@@ -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);
@@ -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();
diff --git a/text_buffer.c b/text_buffer.c
@@ -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;
@@ -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 {
@@ -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 {
@@ -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;
@@ -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(
diff --git a/text_edit.c b/text_edit.c
@@ -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(
@@ -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;
@@ -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, <k_draw_text_edit, <k_destroy_text_edit, 1);
+	ltk_fill_widget_defaults(&te->widget, window, <k_text_edit_draw, <k_text_edit_destroy, 1);
 	/*te->widget.mouse_press = <k_text_edit_tmp;*/
 	te->widget.resize = <k_text_edit_resize;
 	te->tl = ltk_text_line_create(20);
@@ -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);
diff --git a/text_edit.h b/text_edit.h
@@ -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_ */