URI: 
       tFinish removing direct 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 e76057dd60a70a13d5ede8274d504494d2ee70a8
   DIR parent e80afa0ebd0f0fca40a797392db2a210ad466fa4
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Wed, 17 Nov 2021 22:39:43 +0100
       
       Finish removing direct usage of pango in keys_basic.c
       
       Diffstat:
         M buffer.c                            |      77 +++++++++++++++++++++++++++++++
         M buffer.h                            |       4 ++++
         M keys_basic.c                        |     111 +++++++++++--------------------
       
       3 files changed, 121 insertions(+), 71 deletions(-)
       ---
   DIR diff --git a/buffer.c b/buffer.c
       t@@ -1284,6 +1284,83 @@ ledit_buffer_get_softline_bounds(
                *end_byte_ret = pl->start_index + pl->length;
        }
        
       +int
       +ledit_buffer_get_softline_count(ledit_buffer *buffer, int line) {
       +        assert(line >= 0 && line < buffer->lines_num);
       +        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       +        return pango_layout_get_line_count(ll->layout);
       +}
       +
       +int
       +ledit_buffer_pos_to_softline(ledit_buffer *buffer, int line, int pos) {
       +        assert(line >= 0 && line < buffer->lines_num);
       +        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       +        assert(pos >= 0 && pos <= ll->len);
       +        int x, sli;
       +        pango_layout_index_to_line_x(ll->layout, pos, 0, &sli, &x);
       +        return sli;
       +}
       +
       +void
       +ledit_buffer_get_cursor_pixel_pos(ledit_buffer *buffer, int line, int pos, int *x_ret, int *y_ret, int *h_ret) {
       +        assert(line >= 0 && line < buffer->lines_num);
       +        ledit_line *ll = ledit_buffer_get_line(buffer, line);
       +        assert(pos >= 0 && pos <= ll->len);
       +        PangoRectangle strong, weak;
       +        pango_layout_get_cursor_pos(ll->layout, 0, &strong, &weak);
       +        *x_ret = strong.x / PANGO_SCALE;
       +        *y_ret = strong.y / PANGO_SCALE;
       +        *h_ret = strong.height / PANGO_SCALE;
       +}
       +
       +/* prev_index_ret is used instead of just calling get_legal_normal_pos
       +   because weird things happen otherwise
       +   -> in certain cases, this is still weird because prev_index_ret sometimes
       +      is not at the end of the line, but this is the best I could come up
       +      with for now */
       +int
       +ledit_buffer_move_cursor_visually(ledit_buffer *buffer, int line, int pos, int movement, int *prev_index_ret) {
       +        /* FIXME: trailing */
       +        int trailing = 0, tmp_index;
       +        ledit_line *cur_line = ledit_buffer_get_line(buffer, line);
       +        int new_index = pos, last_index = pos;
       +        int dir = 1;
       +        int num = movement;
       +        if (movement < 0) {
       +                dir = -1;
       +                num = -movement;
       +        }
       +        while (num > 0) {
       +                tmp_index = new_index;
       +                pango_layout_move_cursor_visually(
       +                    cur_line->layout, TRUE,
       +                    new_index, trailing, dir,
       +                    &new_index, &trailing
       +                );
       +                /* for some reason, this is necessary */
       +                if (new_index < 0)
       +                        new_index = 0;
       +                else if (new_index > cur_line->len)
       +                        new_index = cur_line->len;
       +                num--;
       +                if (tmp_index != new_index)
       +                        last_index = tmp_index;
       +        }
       +        /* FIXME: Allow cursor to be at end of soft line */
       +        /* we don't currently support a difference between the cursor being at
       +           the end of a soft line and the beginning of the next line */
       +        /* FIXME: spaces at end of softlines are weird in normal mode */
       +        while (trailing > 0) {
       +                trailing--;
       +                new_index = ledit_line_next_utf8(cur_line, new_index);
       +        }
       +        if (new_index < 0)
       +                new_index = 0;
       +        if (prev_index_ret)
       +                *prev_index_ret = last_index;
       +        return new_index;
       +}
       +
        /* FIXME: implement */
        /*
        int
   DIR diff --git a/buffer.h b/buffer.h
       t@@ -77,6 +77,7 @@ int ledit_line_next_utf8(ledit_line *line, int index);
        int ledit_line_prev_utf8(ledit_line *line, int index);
        int ledit_buffer_next_cursor_pos(ledit_buffer *buffer, int line, int byte, int num);
        int ledit_buffer_prev_cursor_pos(ledit_buffer *buffer, int line, int byte, int num);
       +int ledit_buffer_move_cursor_visually(ledit_buffer *buffer, int line, int pos, int movement, int *prev_index_ret);
        
        void ledit_buffer_next_word(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
        void ledit_buffer_next_word_end(ledit_buffer *buffer, int line, int byte, int num_repeat, int *line_ret, int *byte_ret, int *real_byte_ret);
       t@@ -86,6 +87,9 @@ void ledit_buffer_prev_word(ledit_buffer *buffer, int line, int byte, int num_re
        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);
       +int ledit_buffer_get_softline_count(ledit_buffer *buffer, int line);
       +int ledit_buffer_pos_to_softline(ledit_buffer *buffer, int line, int pos);
       +void ledit_buffer_get_cursor_pixel_pos(ledit_buffer *buffer, int line, int pos, int *x_ret, int *y_ret, int *h_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@@ -1,3 +1,4 @@
       +/* FIXME: I guess hard_line_based should be updated for all buffers/windows when that gets supported */
        /* FIXME: cursor isn't shown on spaces at end of softlines */
        /* FIXME: selection is sometimes not reset when it is "clicked away" */
        /* FIXME: use weak cursor */
       t@@ -19,7 +20,6 @@
        #include <X11/XF86keysym.h>
        #include <X11/cursorfont.h>
        
       -#include "pango-compat.h"
        #include "memory.h"
        #include "common.h"
        #include "txtbuf.h"
       t@@ -338,11 +338,9 @@ get_new_line_softline(
                                *new_line_ret = buffer->lines_num - 1;
                        *new_softline_ret = 0;
                } else {
       -                ledit_line *line = ledit_buffer_get_line(buffer, cur_line);
       -                int x, softline;
       -                pango_layout_index_to_line_x(line->layout, cur_index, 0, &softline, &x);
       +                int softline = ledit_buffer_pos_to_softline(buffer, cur_line, cur_index);
                        if (movement > 0) {
       -                        int softlines = pango_layout_get_line_count(line->layout);
       +                        int softlines = ledit_buffer_get_softline_count(buffer, cur_line);
                                if (softlines - softline > movement) {
                                        *new_line_ret = cur_line;
                                        *new_softline_ret = softline + movement;
       t@@ -350,8 +348,7 @@ get_new_line_softline(
                                        movement -= (softlines - softline - 1);
                                        int endline = cur_line + 1;
                                        while (movement > 0 && endline < buffer->lines_num) {
       -                                        line = ledit_buffer_get_line(buffer, endline);
       -                                        softlines = pango_layout_get_line_count(line->layout);
       +                                        softlines = ledit_buffer_get_softline_count(buffer, endline);
                                                movement -= softlines;
                                                endline++;
                                        }
       t@@ -372,8 +369,7 @@ get_new_line_softline(
                                        movement += softline;
                                        int endline = cur_line - 1;
                                        while (movement < 0 && endline >= 0) {
       -                                        line = ledit_buffer_get_line(buffer, endline);
       -                                        softlines = pango_layout_get_line_count(line->layout);
       +                                        softlines = ledit_buffer_get_softline_count(buffer, endline);
                                                movement += softlines;
                                                endline--;
                                        }
       t@@ -610,7 +606,6 @@ append_after_eol(ledit_buffer *buffer, char *text, int len) {
                return (struct action){ACTION_NONE, NULL};
        }
        
       -/* FIXME: allow motion callback! */
        static struct action
        move_to_line(ledit_buffer *buffer, char *text, int len) {
                (void)text;
       t@@ -631,13 +626,13 @@ move_to_line(ledit_buffer *buffer, char *text, int len) {
                        buffer->cur_line = line - 1;
                        buffer->cur_index = 0;
                        int text_w, text_h;
       -                PangoRectangle strong, weak;
                        ledit_window_get_textview_size(buffer->window, &text_w, &text_h);
                        ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -                pango_layout_get_cursor_pos(ll->layout, 0, &strong, &weak);
       +                int x, y, h;
       +                ledit_buffer_get_cursor_pixel_pos(buffer, buffer->cur_line, 0, &x, &y, &h);
                        /* if cursor is not on screen anymore, move to middle of screen */
                        if (ll->y_offset < buffer->display_offset ||
       -                    ll->y_offset + strong.height / PANGO_SCALE > buffer->display_offset + text_h) {
       +                    ll->y_offset + h > buffer->display_offset + text_h) {
                                ledit_buffer_scroll(buffer, ll->y_offset - text_h / 2);
                        }
                        ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
       t@@ -647,30 +642,34 @@ move_to_line(ledit_buffer *buffer, char *text, int len) {
        }
        
        /* FIXME: should these scrolling functions change behavior when hard_line_based == 1? */
       +/* FIXME: preserve x position on these scrolling functions */
        static void
        scroll_lines(ledit_buffer *buffer, int lines, int dir) {
                int final_lines;
                int text_w, text_h;
       -        PangoRectangle strong, weak;
                ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        pango_layout_get_cursor_pos(ll->layout, buffer->cur_index, &strong, &weak);
       -        long abs_pos = ll->y_offset + strong.y / PANGO_SCALE;
       +        int x, y, h;
       +        ledit_buffer_get_cursor_pixel_pos(buffer, buffer->cur_line, buffer->cur_index, &x, &y, &h);
       +        long abs_pos = ll->y_offset + y;
                ledit_window_get_textview_size(buffer->window, &text_w, &text_h);
                if (lines > 0)
                        final_lines = last_lines_scrolled = lines;
                else if (last_lines_scrolled > 0)
                        final_lines = last_lines_scrolled;
                else
       -                final_lines = text_h / (strong.height / PANGO_SCALE);
       +                final_lines = text_h / h / 2;
                ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line);
       +        int sli; /* FIXME: set proper cursor position */
                get_new_line_softline(
                    buffer, buffer->cur_line, buffer->cur_index,
                    dir < 0 ? -final_lines : final_lines,
       -            &buffer->cur_line, &buffer->cur_index
       +            &buffer->cur_line, &sli
                );
       -        ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        pango_layout_get_cursor_pos(ll->layout, buffer->cur_index, &strong, &weak);
       -        long new_abs_pos = ll->y_offset + strong.y / PANGO_SCALE;
       +        int start, end;
       +        ledit_buffer_get_softline_bounds(buffer, buffer->cur_line, sli, &start, &end);
       +        buffer->cur_index = start;
       +        ledit_buffer_get_cursor_pixel_pos(buffer, buffer->cur_line, buffer->cur_index, &x, &y, &h);
       +        long new_abs_pos = ll->y_offset + y;
                ledit_buffer_scroll(buffer, buffer->display_offset + (new_abs_pos - abs_pos));
                ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index);
        }
       t@@ -703,10 +702,9 @@ scroll_lines_down(ledit_buffer *buffer, char *text, int len) {
        
        static void
        scroll_with_cursor(ledit_buffer *buffer, int movement) {
       -        PangoRectangle strong, weak;
       -        ledit_line *ll = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        pango_layout_get_cursor_pos(ll->layout, buffer->cur_index, &strong, &weak);
       -        int pix_movement = movement * (strong.height / PANGO_SCALE);
       +        int x, y, h;
       +        ledit_buffer_get_cursor_pixel_pos(buffer, buffer->cur_line, buffer->cur_index, &x, &y, &h);
       +        int pix_movement = movement * h;
                ledit_buffer_scroll(buffer, buffer->display_offset + pix_movement);
                int old_line = buffer->cur_line;
                int old_index = buffer->cur_index;
       t@@ -1461,36 +1459,12 @@ move_cursor_left_right(ledit_buffer *buffer, int dir, int allow_illegal_index) {
                if (num == 0)
                        num = 1;
        
       -        /* FIXME: trailing */
       -        int trailing = 0, tmp_index;
                ledit_line *cur_line = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        int new_index = buffer->cur_index, last_index = buffer->cur_index;
       -        while (num > 0) {
       -                tmp_index = new_index;
       -                pango_layout_move_cursor_visually(
       -                    cur_line->layout, TRUE,
       -                    new_index, trailing, dir,
       -                    &new_index, &trailing
       -                );
       -                /* for some reason, this is necessary */
       -                if (new_index < 0)
       -                        new_index = 0;
       -                else if (new_index > cur_line->len)
       -                        new_index = cur_line->len;
       -                num--;
       -                if (tmp_index != new_index)
       -                        last_index = tmp_index;
       -        }
       -        /* FIXME: Allow cursor to be at end of soft line */
       -        /* we don't currently support a difference between the cursor being at
       -           the end of a soft line and the beginning of the next line */
       -        /* FIXME: spaces at end of softlines are weird in normal mode */
       -        while (trailing > 0) {
       -                trailing--;
       -                new_index = ledit_line_next_utf8(cur_line, new_index);
       -        }
       -        if (new_index < 0)
       -                new_index = 0;
       +        /* FIXME: standardize interface - num * dir or separately? */
       +        int last_index;
       +        int new_index = ledit_buffer_move_cursor_visually(
       +            buffer, buffer->cur_line, buffer->cur_index, num * dir, &last_index
       +        );
                /* when in normal mode, the cursor cannot be at the very end
                   of the line because it's always covering a character */
                if (new_index >= cur_line->len) {
       t@@ -1553,26 +1527,21 @@ return_key(ledit_buffer *buffer, char *text, int len) {
                return (struct action){ACTION_NONE, NULL};
        }
        
       -/* FIXME: just just ledit_buffer_prev_cursor_pos */
        static void
        move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index) {
       -        PangoDirection dir = PANGO_DIRECTION_LTR;
       -        int tmp_index = buffer->cur_index;
       -        ledit_line *cur_line = ledit_buffer_get_line(buffer, buffer->cur_line);
       -        if (buffer->cur_index >= cur_line->len)
       -                tmp_index--;
       -        if (tmp_index >= 0)
       -                dir = pango_layout_get_direction(cur_line->layout, tmp_index);
       -        if (dir == PANGO_DIRECTION_RTL || dir == PANGO_DIRECTION_WEAK_RTL) {
       -                if (movement_dir < 0)
       -                        move_cursor_left_right(buffer, 1, allow_illegal_index);
       -                else
       -                        move_cursor_left_right(buffer, -1, allow_illegal_index);
       +        if (movement_dir < 0) {
       +                buffer->cur_index = ledit_buffer_prev_cursor_pos(
       +                    buffer, buffer->cur_line, buffer->cur_index, 1
       +                );
                } else {
       -                if (movement_dir < 0)
       -                        move_cursor_left_right(buffer, -1, allow_illegal_index);
       -                else
       -                        move_cursor_left_right(buffer, 1, allow_illegal_index);
       +                buffer->cur_index = ledit_buffer_next_cursor_pos(
       +                    buffer, buffer->cur_line, buffer->cur_index, 1
       +                );
       +        }
       +        if (!allow_illegal_index) {
       +                buffer->cur_index = ledit_buffer_get_legal_normal_pos(
       +                    buffer, buffer->cur_line, buffer->cur_index
       +                );
                }
        }