URI: 
       tAdd basic support for RTL text to line entry - ltk - Socket-based GUI for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 59e4368e073cc9c2a99bfb26f928e120502c5ce5
   DIR parent 8ba1124273be1373b9afbfcefbf2a4df2d6fec24
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Fri, 25 Aug 2023 14:56:01 +0200
       
       Add basic support for RTL text to line entry
       
       Diffstat:
         M src/entry.c                         |      28 +++++++++++++++++++++-------
       
       1 file changed, 21 insertions(+), 7 deletions(-)
       ---
   DIR diff --git a/src/entry.c b/src/entry.c
       t@@ -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>
       t@@ -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);
       t@@ -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;
       t@@ -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])) {
       t@@ -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;
       t@@ -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;
       t@@ -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