URI: 
       tSomewhat fix up and down cursor movement - ledit - Text editor (WIP)
  HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 593315dc549190dd7ed38194fce885cae741c216
   DIR parent 824365813f86fcdc01434477f39a8734183a8b18
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Wed, 14 Apr 2021 21:04:32 +0200
       
       Somewhat fix up and down cursor movement
       
       Diffstat:
         A IDEAS                               |       2 ++
         M buffer.c                            |       5 +++--
         M ledit.c                             |     103 ++++++++++++++++++++-----------
       
       3 files changed, 73 insertions(+), 37 deletions(-)
       ---
   DIR diff --git a/IDEAS b/IDEAS
       t@@ -0,0 +1,2 @@
       +* allow editing same file in multiple places at same time (like in acme)
       +* add different (more basic) text backend
   DIR diff --git a/buffer.c b/buffer.c
       t@@ -144,6 +144,7 @@ init_line(ledit_buffer *buffer, ledit_line *line) {
                line->dirty = 1;
                /* FIXME: does this set line height reasonably when no text yet? */
                pango_layout_get_pixel_size(line->layout, &line->w, &line->h);
       +        line->w = buffer->state->w - 10;
                line->y_offset = 0;
        }
        
       t@@ -206,7 +207,7 @@ recalc_single_line_size(ledit_buffer *buffer, int line_index) {
                int w, h;
                ledit_line *line = &buffer->lines[line_index];
                pango_layout_get_pixel_size(line->layout, &w, &h);
       -        line->w = w;
       +        /*line->w = w;*/
                /* if height changed, set height of current line
                 * and adjust offsets of all lines following it */
                if (line->h != h) {
       t@@ -232,7 +233,7 @@ recalc_line_size_absolute(ledit_buffer *buffer) {
                        buffer->lines[i].y_offset = buffer->total_height;
                        pango_layout_get_pixel_size(buffer->lines[i].layout, &w, &h);
                        buffer->total_height += h;
       -                buffer->lines[i].w = w;
       +                /*buffer->lines[i].w = w;*/
                        buffer->lines[i].h = h;
                }
        }
   DIR diff --git a/ledit.c b/ledit.c
       t@@ -1,3 +1,4 @@
       +/* FIXME: Fix cursor movement, especially buffer->trailing and writing at end of line */
        /* FIXME: horizontal scrolling (also need cache to avoid too large pixmaps) */
        /* FIXME: sort out types for indices (currently just int, but that might overflow) */
        #include <math.h>
       t@@ -511,7 +512,7 @@ resize_window(int w, int h) {
                        pango_layout_set_width(line->layout, (w - 10) * PANGO_SCALE);
                        pango_layout_get_pixel_size(line->layout, &tmp_w, &tmp_h);
                        line->h = tmp_h;
       -                line->w = tmp_w;
       +                line->w = w - 10;
                        line->y_offset = buffer->total_height;
                        line->dirty = 1;
                        buffer->total_height += tmp_h;
       t@@ -649,11 +650,23 @@ i_key(void) {
        
        static void
        line_down(void) {
       -        int lineno, x;
       +        int lineno, x, trailing = 0;
                ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line);
                pango_layout_index_to_line_x(
                    cur_line->layout, buffer->cur_index, 0, &lineno, &x
                );
       +        PangoLayoutLine *cur_pango_line =
       +            pango_layout_get_line_readonly(cur_line->layout, lineno);
       +        if (cur_pango_line->resolved_dir == PANGO_DIRECTION_RTL) {
       +                PangoRectangle rect;
       +                pango_layout_line_get_extents(cur_pango_line, NULL, &rect);
       +                x += (cur_line->w * PANGO_SCALE - rect.width);
       +        }
       +        if (state.mode == NORMAL) {
       +                PangoRectangle pos;
       +                pango_layout_index_to_pos(cur_line->layout, buffer->cur_index, &pos);
       +                x += pos.width / 2;
       +        }
                int maxlines = pango_layout_get_line_count(cur_line->layout);
                if (lineno == maxlines - 1) {
                        ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line);
       t@@ -663,40 +676,57 @@ line_down(void) {
                                cur_line = ledit_get_line(buffer, buffer->cur_line);
                                PangoLayoutLine *nextline =
                                    pango_layout_get_line_readonly(cur_line->layout, 0);
       -                        if (pango_layout_line_x_to_index(
       -                            nextline, x, &buffer->cur_index,
       -                            &buffer->trailing) == FALSE) {
       -                                /* set it to *after* the last index of the line */
       -                                buffer->cur_index =
       -                                    nextline->start_index + nextline->length;
       +                        if (nextline->resolved_dir == PANGO_DIRECTION_RTL) {
       +                                PangoRectangle rect;
       +                                pango_layout_line_get_extents(nextline, NULL, &rect);
       +                                x -= (cur_line->w * PANGO_SCALE - rect.width);
                                }
       +                        pango_layout_line_x_to_index(
       +                            nextline, x, &buffer->cur_index, &trailing
       +                        );
       +                        if (state.mode == INSERT)
       +                                buffer->cur_index += trailing;
                        }
                } else {
                        /* move to the next soft line */
                        PangoLayoutLine *nextline =
                            pango_layout_get_line_readonly(cur_line->layout, lineno + 1);
       -                if (pango_layout_line_x_to_index(
       -                    nextline, x, &buffer->cur_index,
       -                    &buffer->trailing) == FALSE) {
       -                        /* set it to *after* the last index of the line */
       -                        buffer->cur_index =
       -                            nextline->start_index + nextline->length;
       +                if (nextline->resolved_dir == PANGO_DIRECTION_RTL) {
       +                        PangoRectangle rect;
       +                        pango_layout_line_get_extents(nextline, NULL, &rect);
       +                        x -= (cur_line->w * PANGO_SCALE - rect.width);
                        }
       +                pango_layout_line_x_to_index(
       +                    nextline, x, &buffer->cur_index, &trailing
       +                );
       +                if (state.mode == INSERT)
       +                        buffer->cur_index += trailing;
                }
       -        if (buffer->cur_index > 0 &&
       -            state.mode == NORMAL &&
       -            buffer->cur_index >= cur_line->len)
       -                cursor_left();
                ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
        }
        
        static void
        line_up(void) {
       -        int lineno, x;
       +        int lineno, x, trailing = 0;
                ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line);
                pango_layout_index_to_line_x(
                    cur_line->layout, buffer->cur_index, 0, &lineno, &x
                );
       +        PangoLayoutLine *cur_pango_line =
       +            pango_layout_get_line_readonly(cur_line->layout, lineno);
       +        /* FIXME: do these lines need to be unref'd? */
       +        if (cur_pango_line->resolved_dir == PANGO_DIRECTION_RTL) {
       +                PangoRectangle rect;
       +                pango_layout_line_get_extents(cur_pango_line, NULL, &rect);
       +                /* FIXME: don't store w in each line because it is now the same for all */
       +                x += (cur_line->w * PANGO_SCALE - rect.width);
       +        }
       +        if (state.mode == NORMAL) {
       +                PangoRectangle pos;
       +                pango_layout_index_to_pos(cur_line->layout, buffer->cur_index, &pos);
       +                x += pos.width / 2;
       +        }
       +        /* FIXME: clean this up (if and else are very similar) */
                if (lineno == 0) {
                        ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line);
                        /* move to the previous hard line */
       t@@ -706,30 +736,33 @@ line_up(void) {
                                int maxlines = pango_layout_get_line_count(cur_line->layout);
                                PangoLayoutLine *prevline =
                                    pango_layout_get_line_readonly(cur_line->layout, maxlines - 1);
       -                        if (pango_layout_line_x_to_index(
       -                            prevline, x, &buffer->cur_index,
       -                            &buffer->trailing) == FALSE) {
       -                                /* set it to *after* the last index of the line */
       -                                buffer->cur_index =
       -                                    prevline->start_index + prevline->length;
       +                        if (prevline->resolved_dir == PANGO_DIRECTION_RTL) {
       +                                PangoRectangle rect;
       +                                pango_layout_line_get_extents(prevline, NULL, &rect);
       +                                x -= (cur_line->w * PANGO_SCALE - rect.width);
                                }
       +                        pango_layout_line_x_to_index(
       +                            prevline, x, &buffer->cur_index, &trailing
       +                        );
       +                        /* FIXME: also in visual? */
       +                        if (state.mode == INSERT)
       +                                buffer->cur_index += trailing;
                        }
                } else {
                        /* move to the previous soft line */
                        PangoLayoutLine *prevline =
                            pango_layout_get_line_readonly(cur_line->layout, lineno - 1);
       -                if (pango_layout_line_x_to_index(
       -                    prevline, x, &buffer->cur_index,
       -                    &buffer->trailing) == FALSE) {
       -                        /* set it to *after* the last index of the line */
       -                        buffer->cur_index =
       -                            prevline->start_index + prevline->length;
       +                if (prevline->resolved_dir == PANGO_DIRECTION_RTL) {
       +                        PangoRectangle rect;
       +                        pango_layout_line_get_extents(prevline, NULL, &rect);
       +                        x -= (cur_line->w * PANGO_SCALE - rect.width);
                        }
       +                pango_layout_line_x_to_index(
       +                    prevline, x, &buffer->cur_index, &trailing
       +                );
       +                if (state.mode == INSERT)
       +                        buffer->cur_index += trailing;
                }
       -        if (buffer->cur_index > 0 &&
       -            state.mode == NORMAL &&
       -            buffer->cur_index >= cur_line->len)
       -                cursor_left();
                ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
        }