commit 201782e6c6df60ab9082852042d210b5d809f797
parent ba0e522da0cb698021de15f24971b8c661d3941f
Author: lumidify <nobody@lumidify.org>
Date:   Thu, 21 May 2020 19:42:00 +0200
Somewhat handle resize for text edit
Diffstat:
4 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/grid.c b/grid.c
@@ -174,7 +174,7 @@ void ltk_recalculate_grid(LtkGrid *grid)
 			}
 			if (orig_width != ptr->rect.w || orig_height != ptr->rect.h) {
 				if (ptr->resize) {
-					ptr->resize(ptr);
+					ptr->resize(ptr, orig_width, orig_height);
 				}
 			}
 
diff --git a/ltk.h b/ltk.h
@@ -65,7 +65,7 @@ typedef struct LtkWidget {
 	void (*mouse_release) (void *, XEvent event);
 	void (*motion_notify) (void *, XEvent event);
 
-	void (*resize) (void *);
+	void (*resize) (void *, int, int);
 	void (*draw) (void *);
 	void (*destroy) (void *);
 
diff --git a/text_buffer.c b/text_buffer.c
@@ -126,7 +126,8 @@ ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
 				glyph = &cur->glyphs[i];
 				int cur_w = sl->w + cur_start - glyph->x_abs;
 				if (cur_w > max_width) {
-					/* FIXME: fix behavior when line isn't wide enough for single char */
+					/* 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 (j == cur->num_glyphs - 1 &&
@@ -210,7 +211,12 @@ ltk_text_line_wrap(struct ltk_text_line *tl, int max_width) {
 		cur = par_is_rtl ? cur->last : cur->next;
 	}
 	ltk_text_line_cleanup_soft_lines(tl->soft_lines, old_len);
-	tl->w_wrapped = max_width;
+	/* if it fits on one line, don't waste all the space to the end of
+	   the line, just use the actual width of the text */
+	if (tl->soft_lines->len == 1)
+		tl->w_wrapped = tl->soft_lines->buf[0]->w;
+	else
+		tl->w_wrapped = max_width;
 	tl->h_wrapped = tl->soft_lines->len * tl->h;
 
 	gettimeofday(&t2, NULL);
@@ -246,7 +252,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)
+			if (y + i >= img->height || x + j >= img->width || y < 0 || x < 0)
 				continue;
 			b = (y + i) * img->bytes_per_line + (x + j) * 4;
 			a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0;
diff --git a/text_edit.c b/text_edit.c
@@ -41,15 +41,35 @@ extern Ltk *ltk_global;
 
 void
 ltk_draw_text_edit(LtkTextEdit *te) {
+	/* FIXME: this requires img to be non-null */
+	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;
+	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(
+	    ltk_global->display,
+	    window->xwindow,
+	    window->gc,
+	    te->tl->img,
+	    0, 0,
+	    x, rect.y,
+	    te->tl->w_wrapped, te->tl->h_wrapped
+	);
+}
+
+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)
+		return;
 	XColor fg = ltk_global->theme->window->fg;
 	XColor bg = ltk_global->theme->window->bg;
-	LtkRect rect = te->widget.rect;
 	LtkWindow *window = te->widget.window;
-	/* FIXME: need special "resize" function called by grid, etc.
-	   to avoid recalculating everything when it really only has to drawn */
-	ltk_text_line_wrap(te->tl, rect.w);
+	ltk_text_line_wrap(te->tl, te->widget.rect.w);
 	ltk_text_line_render(te->tl, 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, rect.w, rect.h);
 }
 
 #if 0
@@ -75,8 +95,9 @@ ltk_create_text_edit(LtkWindow *window, const char *text) {
 		ltk_fatal("ERROR: Unable to allocate memory for LtkTextEdit.\n");
 	ltk_fill_widget_defaults(&te->widget, window, <k_draw_text_edit, <k_destroy_text_edit, 1);
 	/*te->widget.mouse_press = <k_text_edit_tmp;*/
+	te->widget.resize = <k_text_edit_resize;
 	te->tl = ltk_text_line_create();
-	ltk_text_line_insert_utf8(te->tl, 0, text);
+	ltk_text_edit_insert_text(te, text);
 	return te;
 }
 
@@ -84,6 +105,7 @@ void
 ltk_text_edit_insert_text(LtkTextEdit *te, const char *text) {
 	/* FIXME */
 	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);
 }