URI: 
       tClean up some usage of pango in keys_basic.c - 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 e80afa0ebd0f0fca40a797392db2a210ad466fa4
   DIR parent 12a37bf84755943e32b70a7afca27f4928f684af
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Wed, 17 Nov 2021 11:19:06 +0100
       
       Clean up some usage of pango in keys_basic.c
       
       Diffstat:
         M buffer.c                            |      31 +++++++++++++++++++++++++++++++
         M buffer.h                            |       2 ++
         M keys_basic.c                        |     158 +++++++++++++------------------
       
       3 files changed, 99 insertions(+), 92 deletions(-)
       ---
   DIR diff --git a/buffer.c b/buffer.c
       t@@ -1256,6 +1256,34 @@ GEN_NEXT_WORD(bigword_end, line_next_bigword_end)
        GEN_PREV_WORD(word, line_prev_word)
        GEN_PREV_WORD(bigword, line_prev_bigword)
        
       +void
       +ledit_buffer_get_pos_softline_bounds(
       +    ledit_buffer *buffer, int line, int pos,
       +    int *start_byte_ret, int *end_byte_ret) {
       +        assert(line >= 0 && line < buffer->lines_num);
       +        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       +        normalize_and_set_pango_text(ll);
       +        assert(pos >= 0 && pos <= ll->len);
       +        int x, sli;
       +        pango_layout_index_to_line_x(ll->layout, pos, 0, &sli, &x);
       +        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, sli);
       +        *start_byte_ret = pl->start_index;
       +        *end_byte_ret = pl->start_index + pl->length;
       +}
       +
       +void
       +ledit_buffer_get_softline_bounds(
       +    ledit_buffer *buffer, int line, int softline,
       +    int *start_byte_ret, int *end_byte_ret) {
       +        assert(line >= 0 && line < buffer->lines_num);
       +        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       +        normalize_and_set_pango_text(ll);
       +        assert(softline < pango_layout_get_line_count(ll->layout));
       +        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, softline);
       +        *start_byte_ret = pl->start_index;
       +        *end_byte_ret = pl->start_index + pl->length;
       +}
       +
        /* FIXME: implement */
        /*
        int
       t@@ -1323,6 +1351,9 @@ ledit_buffer_delete_unicode_char_base(ledit_buffer *buffer, int line_index, int 
                return new_index;
        }
        
       +/* FIXME: normalize_line will generally be called whenever it is not normalized
       +   since text_dirty should be set then, but the naming of this function technically
       +   isn't very good */
        static void
        normalize_and_set_pango_text(ledit_line *line) {
                if (line->text_dirty) {
   DIR diff --git a/buffer.h b/buffer.h
       t@@ -84,6 +84,8 @@ void ledit_buffer_next_bigword(ledit_buffer *buffer, int line, int byte, int num
        void ledit_buffer_next_bigword_end(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
        void ledit_buffer_prev_word(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
        void ledit_buffer_prev_bigword(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
       +void ledit_buffer_get_pos_softline_bounds(ledit_buffer *buffer, int line, int pos, int *start_byte_ret, int *end_byte_ret);
       +void ledit_buffer_get_softline_bounds(ledit_buffer *buffer, int line, int softline, int *start_byte_ret, int *end_byte_ret);
        
        size_t ledit_buffer_textlen(ledit_buffer *buffer, int line1, int byte1, int line2, int byte2);
        void ledit_buffer_copy_text(ledit_buffer *buffer, char *dst, int line1, int byte1, int line2, int byte2);
   DIR diff --git a/keys_basic.c b/keys_basic.c
       t@@ -558,33 +558,28 @@ push_undo_empty_insert(ledit_buffer *buffer, int line, int index, int start_grou
        
        static struct action
        append_line_above(ledit_buffer *buffer, char *text, int len) {
       -        int sli, x;
       +        int start, end;
                /* do this here already so the mode group is the same for the newline insertion */
                enter_insert(buffer, text, len);
       -        ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        /* FIXME: this is more "elegant", but inefficient because this doesn't
       -           actually need to be called when hard_line_based == 1 */
       -        pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -        if (hard_line_based || sli == 0) {
       +        ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
       +        if (hard_line_based || start == 0) {
                        insert_text(buffer, buffer->cur_line, 0, "\n", -1, -1, -1, buffer->cur_line, 0, 1);
                } else {
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                insert_text(buffer, buffer->cur_line, sl->start_index, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
       +                insert_text(buffer, buffer->cur_line, start, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
                }
                return (struct action){ACTION_NONE, NULL};
        }
        
        static struct action
        append_line_below(ledit_buffer *buffer, char *text, int len) {
       -        int sli, x;
       +        int start, end;
                enter_insert(buffer, text, len);
       +        ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -        PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -        if (hard_line_based || sl->start_index + sl->length == ll->len) {
       +        if (hard_line_based || end == ll->len) {
                        insert_text(buffer, buffer->cur_line, ll->len, "\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
                } else {
       -                insert_text(buffer, buffer->cur_line, sl->start_index + sl->length, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
       +                insert_text(buffer, buffer->cur_line, end, "\n\n", -1, -1, -1, buffer->cur_line + 1, 0, 1);
                }
                return (struct action){ACTION_NONE, NULL};
        }
       t@@ -602,18 +597,16 @@ append_after_cursor(ledit_buffer *buffer, char *text, int len) {
        
        static struct action
        append_after_eol(ledit_buffer *buffer, char *text, int len) {
       -        int sli, x;
       +        int start, end;
                enter_insert(buffer, text, len);
       +        ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
                /* make cursor jump back to original position on undo */
                push_undo_empty_insert(buffer, buffer->cur_line, buffer->cur_index, 1);
                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        if (hard_line_based) {
       +        if (hard_line_based)
                        buffer->cur_index = ll->len;
       -        } else {
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                buffer->cur_index = sl->start_index + sl->length;
       -        }
       +        else
       +                buffer->cur_index = end;
                return (struct action){ACTION_NONE, NULL};
        }
        
       t@@ -829,14 +822,12 @@ delete_to_eol(ledit_buffer *buffer, char *text, int len) {
                (void)len;
                if (!key_stack_empty())
                        return err_invalid_key(buffer);
       -        int end, x, sli;
       +        int start, end;
                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
                if (hard_line_based) {
                        end = ll->len;
                } else {
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                end = sl->start_index + sl->length;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
                }
                delete_range(
                    buffer, 0, 0,
       t@@ -858,14 +849,12 @@ change_to_eol(ledit_buffer *buffer, char *text, int len) {
                if (!key_stack_empty())
                        return err_invalid_key(buffer);
                ledit_buffer_set_mode(buffer, INSERT);
       -        int end, x, sli;
       +        int start, end;
                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
                if (hard_line_based) {
                        end = ll->len;
                } else {
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                end = sl->start_index + sl->length;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
                }
                delete_range(
                    buffer, 0, 0,
       t@@ -900,9 +889,9 @@ change(ledit_buffer *buffer, char *text, int len) {
                                    buffer, buffer->cur_line, buffer->cur_index,
                                    lines - 1, &new_line, &new_softline
                                );
       -                        ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
       -                        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, new_softline);
       -                        cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE);
       +                        int start, end;
       +                        ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &start, &end);
       +                        cb(buffer, new_line, start, KEY_MOTION_LINE);
                                clear_key_stack();
                        } else if (cb != NULL) {
                                return err_invalid_key(buffer);
       t@@ -923,16 +912,11 @@ change_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) {
                int line_based = type == KEY_MOTION_LINE ? 1 : 0;
                /* this hackery is needed to avoid deleting the entire last line and
                   instead leave an empty line - this should be made nicer (FIXME) */
       -        int pos1 = buffer->cur_index, pos2 = char_pos, x, sli;
       +        int pos1 = buffer->cur_index, pos2 = char_pos;
                if (line_based && !hard_line_based) {
       -                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                pos1 = sl->start_index;
       -                ll = ledit_buffer_get_line(buffer, line);
       -                pango_layout_index_to_line_x(ll->layout, char_pos, 0, &sli, &x);
       -                sl = pango_layout_get_line_readonly(ll->layout, sli);
       -                pos2 = sl->start_index + sl->length;
       +                int pos1, pos2, tmp;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &pos1, &tmp);
       +                ledit_buffer_get_pos_softline_bounds(buffer, line, char_pos, &tmp, &pos2);
                } else if (line_based && hard_line_based) {
                        pos1 = 0;
                        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       t@@ -983,9 +967,9 @@ yank(ledit_buffer *buffer, char *text, int len) {
                                    buffer, buffer->cur_line, buffer->cur_index,
                                    num - 1, &new_line, &new_softline
                                );
       -                        ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
       -                        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, new_softline);
       -                        cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE);
       +                        int start, end;
       +                        ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &start, &end);
       +                        cb(buffer, new_line, start, KEY_MOTION_LINE);
                                clear_key_stack();
                        } else if (cb == NULL) {
                                struct key_stack_elem *e = push_key_stack();
       t@@ -1014,16 +998,13 @@ yank_lines(ledit_buffer *buffer, char *text, int len) {
                    buffer, buffer->cur_line, buffer->cur_index,
                    num - 1, &new_line, &new_softline
                );
       -        ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
       -        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, new_softline);
       -        yank_cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE);
       +        int start, end;
       +        ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &start, &end);
       +        yank_cb(buffer, new_line, start, KEY_MOTION_LINE);
                clear_key_stack();
                return (struct action){ACTION_NONE, NULL};
        }
        
       -/* FIXME: delete_range and yank put different things in past_buffer - yank doesn't include
       -   extra newlines at the beginning and end (this doesn't really matter because paste
       -   ignores them anyways, but it is a bit weird) */
        static void
        yank_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) {
                int line_based = type == KEY_MOTION_LINE ? 1 : 0;
       t@@ -1035,21 +1016,26 @@ yank_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) {
                        swap(&b1, &b2);
                }
                if (line_based && !hard_line_based) {
       -                int x, sl1, sl2;
       -                ledit_line *ll1 = ledit_buffer_get_line(buffer, l1);
       -                pango_layout_index_to_line_x(ll1->layout, b1, 0, &sl1, &x);
       -                PangoLayoutLine *pl1 = pango_layout_get_line_readonly(ll1->layout, sl1);
       -                ledit_line *ll2 = ledit_buffer_get_line(buffer, l2);
       -                pango_layout_index_to_line_x(ll2->layout, b2, 0, &sl2, &x);
       -                PangoLayoutLine *pl2 = pango_layout_get_line_readonly(ll2->layout, sl2);
       -                assert(pl1 != NULL && pl2 != NULL);
       +                int start1, end2, tmp;
       +                ledit_buffer_get_pos_softline_bounds(buffer, l1, b1, &start1, &tmp);
       +                ledit_buffer_get_pos_softline_bounds(buffer, l2, b2, &tmp, &end2);
       +                ledit_line *ll = ledit_buffer_get_line(buffer, l2);
       +                if (end2 == ll->len && l2 < buffer->lines_num - 1) {
       +                        l2++;
       +                        end2 = 0;
       +                }
                        ledit_buffer_copy_text_to_txtbuf(
       -                    buffer, paste_buffer, l1, pl1->start_index, l2, pl2->start_index + pl2->length
       +                    buffer, paste_buffer, l1, start1, l2, end2
                        );
                } else if (line_based && hard_line_based) {
                        ledit_line *ll = ledit_buffer_get_line(buffer, l2);
       +                int end = ll->len;
       +                if (l2 < buffer->lines_num - 1) {
       +                        l2++;
       +                        end = 0;
       +                }
                        ledit_buffer_copy_text_to_txtbuf(
       -                    buffer, paste_buffer, l1, 0, l2, ll->len
       +                    buffer, paste_buffer, l1, 0, l2, end
                        );
                } else {
                        ledit_buffer_copy_text_to_txtbuf(
       t@@ -1082,9 +1068,9 @@ delete(ledit_buffer *buffer, char *text, int len) {
                                    buffer, buffer->cur_line, buffer->cur_index,
                                    lines - 1, &new_line, &new_softline
                                );
       -                        ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
       -                        PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, new_softline);
       -                        cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE);
       +                        int start, end;
       +                        ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &start, &end);
       +                        cb(buffer, new_line, start, KEY_MOTION_LINE);
                                clear_key_stack();
                        } else if (cb != NULL) {
                                return err_invalid_key(buffer);
       t@@ -1112,8 +1098,6 @@ delete_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) {
                finalize_repetition_stack();
        }
        
       -/* FIXME: don't use the pango functions directly so normalize_and_set_pango_text is
       -   always called properly */
        /* Note that these paste functions are a bit weird when working with softlines -
           they always make sure the pasted text is separated from the surrounding text by
           hard lines, which may be unexpected, but the alternatives I could think of are
       t@@ -1128,16 +1112,14 @@ paste_normal(ledit_buffer *buffer, char *text, int len) {
                        return (struct action){ACTION_NONE, NULL};
                }
                if (paste_buffer_line_based) {
       -                int x, softline;
                        ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
                        ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
                        int brk = 0;
                        if (hard_line_based) {
                                brk = ll->len;
                        } else {
       -                        pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &softline, &x);
       -                        PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, softline);
       -                        brk = sl->start_index + sl->length;
       +                        int tmp;
       +                        ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &tmp, &brk);
                        }
                        insert_text(
                            buffer, buffer->cur_line, brk,
       t@@ -1186,14 +1168,12 @@ paste_normal_backwards(ledit_buffer *buffer, char *text, int len) {
                        return (struct action){ACTION_NONE, NULL};
                }
                if (paste_buffer_line_based) {
       -                int x, softline;
                        ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
                        ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
                        int brk = 0;
                        if (!hard_line_based) {
       -                        pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &softline, &x);
       -                        PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, softline);
       -                        brk = sl->start_index;
       +                        int tmp;
       +                        ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &brk, &tmp);
                        }
                        insert_text(
                            buffer, buffer->cur_line, brk,
       t@@ -1393,8 +1373,8 @@ move_to_eol(ledit_buffer *buffer, char *text, int len) {
                ledit_line *ll = ledit_buffer_get_line(buffer, new_line);
                int end_index = ll->len;
                if (!hard_line_based) {
       -                PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, new_softline);
       -                end_index = sl->start_index + sl->length;
       +                int tmp;
       +                ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &tmp, &end_index);
                }
                if (cb != NULL) {
                        cb(buffer, new_line, end_index, KEY_MOTION_CHAR);
       t@@ -1657,8 +1637,9 @@ move_cursor_up_down(ledit_buffer *buffer, int dir) {
                ledit_line *cur_lline = ledit_buffer_get_line(buffer, buffer->cur_line);
                ledit_line *new_lline = ledit_buffer_get_line(buffer, new_line);
                if (cb != NULL) {
       -                PangoLayoutLine *pl = pango_layout_get_line_readonly(new_lline->layout, new_softline);
       -                cb(buffer, new_line, pl->start_index, KEY_MOTION_LINE);
       +                int start, end;
       +                ledit_buffer_get_softline_bounds(buffer, new_line, new_softline, &start, &end);
       +                cb(buffer, new_line, start, KEY_MOTION_LINE);
                } else {
                        int lineno, x;
                        ledit_pos_to_x_softline(cur_lline, buffer->cur_index, &x, &lineno);
       t@@ -1752,11 +1733,8 @@ insert_at_beginning(ledit_buffer *buffer, char *text, int len) {
                enter_insert(buffer, text, len);
                int new_index = 0;
                if (!hard_line_based) {
       -                int x, sli;
       -                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, sli);
       -                new_index = pl->start_index;
       +                int tmp;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &new_index, &tmp);
                }
                push_undo_empty_insert(buffer, buffer->cur_line, buffer->cur_index, 1);
                buffer->cur_index = new_index;
       t@@ -1777,14 +1755,13 @@ cursor_to_first_non_ws(ledit_buffer *buffer, char *text, int len) {
                if (hard_line_based) {
                        new_index = ledit_line_next_non_whitespace(ll, 0);
                } else {
       -                int x, sli;
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, sli);
       -                new_index = ledit_line_next_non_whitespace(ll, pl->start_index);
       +                int start, end;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start, &end);
       +                new_index = ledit_line_next_non_whitespace(ll, start);
                        /* next non-whitespace might be on next softline */
       -                if (new_index >= pl->start_index + pl->length) {
       +                if (new_index >= end) {
                                new_index = ledit_buffer_prev_cursor_pos(
       -                            buffer, buffer->cur_line, pl->start_index + pl->length, 1
       +                            buffer, buffer->cur_line, end, 1
                                );
                        }
                }
       t@@ -1804,7 +1781,6 @@ static struct action
        cursor_to_beginning(ledit_buffer *buffer, char *text, int len) {
                (void)text;
                (void)len;
       -        int x, sli;
                motion_callback cb;
                int num = get_key_repeat_and_motion_cb(&cb);
                if (num != 0)
       t@@ -1812,10 +1788,8 @@ cursor_to_beginning(ledit_buffer *buffer, char *text, int len) {
                /* FIXME: should anything be done with num? */
                int start_index = 0;
                if (!hard_line_based) {
       -                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -                pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &sli, &x);
       -                PangoLayoutLine *pl = pango_layout_get_line_readonly(ll->layout, sli);
       -                start_index = pl->start_index;
       +                int tmp;
       +                ledit_buffer_get_pos_softline_bounds(buffer, buffer->cur_line, buffer->cur_index, &start_index, &tmp);
                }
                if (cb != NULL) {
                        cb(buffer, buffer->cur_line, start_index, KEY_MOTION_CHAR);