ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit e76057dd60a70a13d5ede8274d504494d2ee70a8
parent e80afa0ebd0f0fca40a797392db2a210ad466fa4
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:
Mbuffer.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbuffer.h | 4++++
Mkeys_basic.c | 111+++++++++++++++++++++++++++++--------------------------------------------------
3 files changed, 121 insertions(+), 71 deletions(-)

diff --git a/buffer.c b/buffer.c @@ -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 diff --git a/buffer.h b/buffer.h @@ -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); @@ -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); diff --git a/keys_basic.c b/keys_basic.c @@ -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 */ @@ -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" @@ -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; @@ -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++; } @@ -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--; } @@ -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; @@ -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); @@ -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); } @@ -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; @@ -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) { @@ -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 + ); } }