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 e80afa0ebd0f0fca40a797392db2a210ad466fa4
parent 12a37bf84755943e32b70a7afca27f4928f684af
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:
Mbuffer.c | 31+++++++++++++++++++++++++++++++
Mbuffer.h | 2++
Mkeys_basic.c | 158+++++++++++++++++++++++++++++++++----------------------------------------------
3 files changed, 99 insertions(+), 92 deletions(-)

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