commit 59e4368e073cc9c2a99bfb26f928e120502c5ce5
parent 8ba1124273be1373b9afbfcefbf2a4df2d6fec24
Author: lumidify <nobody@lumidify.org>
Date:   Fri, 25 Aug 2023 14:56:01 +0200
Add basic support for RTL text to line entry
Diffstat:
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/src/entry.c b/src/entry.c
@@ -14,8 +14,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* FIXME: support RTL text! */
 /* FIXME: allow opening text in external program */
+/* FIXME: cursors jump weirdly with bidi text
+   (need to support strong/weak cursors in pango backend) */
+/* FIXME: set imspot - needs to be standardized so widgets don't all do their own thing */
 
 #include <stdio.h>
 #include <ctype.h>
@@ -287,7 +289,10 @@ ltk_entry_redraw_surface(ltk_entry *entry, ltk_surface *s) {
 	int text_w, text_h;
 	ltk_text_line_get_size(entry->tl, &text_w, &text_h);
 	/* FIXME: what if text_h > rect.h? */
-	int text_x = bw + theme.pad;
+	int x_offset = 0;
+	if (text_w < rect.w - 2 * (bw + theme.pad) && ltk_text_line_get_softline_direction(entry->tl, 0) == LTK_TEXT_RTL)
+		x_offset = rect.w - 2 * (bw + theme.pad) - text_w;
+	int text_x = bw + theme.pad + x_offset;
 	int text_y = (rect.h - text_h) / 2;
 	ltk_rect clip_rect = (ltk_rect){text_x, text_y, rect.w - 2 * bw - 2 * theme.pad, text_h};
 	ltk_text_line_draw_clipped(entry->tl, s, &theme.text_color, text_x - entry->cur_offset, text_y, clip_rect);
@@ -300,6 +305,16 @@ ltk_entry_redraw_surface(ltk_entry *entry, ltk_surface *s) {
 	entry->widget.dirty = 0;
 }
 
+static size_t
+xy_to_pos(ltk_entry *e, int x, int y, int snap) {
+	int side = theme.border_width + theme.pad;
+	int text_w, text_h;
+	ltk_text_line_get_size(e->tl, &text_w, &text_h);
+	if (text_w < e->widget.lrect.w - 2 * side && ltk_text_line_get_softline_direction(e->tl, 0) == LTK_TEXT_RTL)
+		x -= e->widget.lrect.w - 2 * side - text_w;
+	return ltk_text_line_xy_to_pos(e->tl, x - side + e->cur_offset, y - side, snap);
+}
+
 static void
 set_selection(ltk_entry *entry, size_t start, size_t end) {
 	entry->sel_start = start;
@@ -604,7 +619,7 @@ ltk_entry_mouse_press(ltk_widget *self, ltk_button_event *event) {
 			   allow a config option to revert to the naive behavior - I hate it
 			   when word boundaries stop at punctuation because it's really
 			   annoying to select URLs, etc. then. */
-			e->pos = ltk_text_line_xy_to_pos(e->tl, event->x - side + e->cur_offset, event->y - side, 0);
+			e->pos = xy_to_pos(e, event->x, event->y, 0);
 			size_t cur = e->pos;
 			size_t left = 0, right = 0;
 			if (isspace(e->text[e->pos])) {
@@ -641,7 +656,7 @@ ltk_entry_mouse_press(ltk_widget *self, ltk_button_event *event) {
 			set_selection(e, left, right);
 			e->sel_side = 0;
 		} else if (event->type == LTK_BUTTONPRESS_EVENT) {
-			e->pos = ltk_text_line_xy_to_pos(e->tl, event->x - side + e->cur_offset, event->y - side, 1);
+			e->pos = xy_to_pos(e, event->x, event->y, 1);
 			set_selection(e, e->pos, e->pos);
 			e->selecting = 1;
 			e->sel_side = 0;
@@ -650,7 +665,7 @@ ltk_entry_mouse_press(ltk_widget *self, ltk_button_event *event) {
 		/* FIXME: configure if this should change the position or paste at the current position
 		   (see behavior in ledit) */
 		wipe_selection(e);
-		e->pos = ltk_text_line_xy_to_pos(e->tl, event->x - side + e->cur_offset, event->y - side, 1);
+		e->pos = xy_to_pos(e, event->x, event->y, 1);
 		paste_primary(e, NULL);
 	}
 	return 0;
@@ -674,8 +689,7 @@ ltk_entry_motion_notify(ltk_widget *self, ltk_motion_event *event) {
 		   is being selected (FIXME: a bit weird) */
 		if (e->sel_start == e->sel_end && e->pos != e->sel_start)
 			e->sel_start = e->sel_end = e->pos;
-		int side = theme.border_width + theme.pad;
-		size_t new = ltk_text_line_xy_to_pos(e->tl, event->x - side + e->cur_offset, event->y - side, 1);
+		size_t new = xy_to_pos(e, event->x, event->y, 1);
 		size_t otherpos = e->sel_side == 1 ? e->sel_start : e->sel_end;
 		e->pos = new;
 		/* this takes care of moving the shown text when the mouse is