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 271d268ba17415be9808bb1da36389036b4eb95d
parent e5841801447358ed8f2f57e3dc0adc2873fb500e
Author: lumidify <nobody@lumidify.org>
Date:   Mon,  1 Nov 2021 13:17:15 +0100

Implement pasting (well, sort of)

Diffstat:
Mkeys_basic.c | 121++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mkeys_basic_config.h | 2++
2 files changed, 97 insertions(+), 26 deletions(-)

diff --git a/keys_basic.c b/keys_basic.c @@ -25,7 +25,8 @@ #include "keys_command.h" #include "keys_basic_config.h" -/* this is supposed to be global for all buffers */ +/* note: this is supposed to be global for all buffers */ +int paste_buffer_line_based = 0; static txtbuf *paste_buffer = NULL; static int last_lines_scrolled = -1; @@ -91,7 +92,7 @@ static struct key_stack_elem *peek_key_stack(void); static struct key_stack_elem *pop_key_stack(void); void clear_key_stack(void); -static void move_cursor_left_right(ledit_buffer *buffer, int dir); +static void move_cursor_left_right(ledit_buffer *buffer, int dir, int allow_illegal_index); static void move_cursor_up_down(ledit_buffer *buffer, int dir); static void push_num(int num); static void key_d_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type); @@ -99,6 +100,7 @@ static void get_new_line_softline( ledit_buffer *buffer, int cur_line, int cur_index, int movement, int *new_line_ret, int *new_softline_ret ); +static void move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index); /* FIXME: move to common */ static void @@ -304,7 +306,7 @@ delete_range( } static void -insert_text(ledit_buffer *buffer, int line, int index, char *text, int len, int start_group) { +insert_text(ledit_buffer *buffer, int line, int index, char *text, int len, int new_line, int new_index, int start_group) { if (len < 0) len = strlen(text); /* FIXME: this is kind of hacky... */ @@ -314,14 +316,22 @@ insert_text(ledit_buffer *buffer, int line, int index, char *text, int len, int cur_range.byte1 = buffer->cur_index; del_range.line1 = line; del_range.byte1 = index; + int cur_line, cur_index; ledit_buffer_insert_text_with_newlines( buffer, line, index, text, len, - &buffer->cur_line, &buffer->cur_index + &cur_line, &cur_index ); - cur_range.line2 = buffer->cur_line; - cur_range.byte2 = buffer->cur_index; - del_range.line2 = buffer->cur_line; - del_range.byte2 = buffer->cur_index; + /* this is mainly for pasting, where the new line and index + should not be at the end of the pasted text */ + if (new_line >= 0 && new_index >= 0) { + cur_range.line2 = buffer->cur_line = new_line; + cur_range.byte2 = buffer->cur_index = new_index; + } else { + cur_range.line2 = buffer->cur_line = cur_line; + cur_range.byte2 = buffer->cur_index = cur_index; + } + del_range.line2 = cur_line; + del_range.byte2 = cur_index; ledit_push_undo_insert( buffer->undo, &ins_buf, del_range, cur_range, start_group, buffer->common->mode ); @@ -335,6 +345,7 @@ delete_selection(ledit_buffer *buffer) { buffer->sel.line1, buffer->sel.byte1, buffer->sel.line2, buffer->sel.byte2 ); + paste_buffer_line_based = 0; /* FIXME: maybe just set this to the current cursor pos? */ buffer->sel.line1 = buffer->sel.line2 = -1; buffer->sel.byte1 = buffer->sel.byte2 = -1; @@ -629,8 +640,53 @@ key_d_cb(ledit_buffer *buffer, int line, int char_pos, enum key_type type) { buffer->cur_line, buffer->cur_index, line, char_pos ); + paste_buffer_line_based = line_based; + ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); + finalize_repetition_stack(); +} + +/* FIXME: don't use the pango functions directly so normalize_and_set_pango_text is + always called properly */ +static struct action +paste_normal(ledit_buffer *buffer, char *text, int len) { + (void)text; + (void)len; + if (!paste_buffer) { + ledit_window_show_message(buffer->window, "Nothing to paste", -1); + discard_repetition_stack(); + 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); + pango_layout_index_to_line_x(ll->layout, buffer->cur_index, 0, &softline, &x); + PangoLayoutLine *sl = pango_layout_get_line_readonly(ll->layout, softline); + insert_text( + buffer, buffer->cur_line, sl->start_index + sl->length, + "\n", -1, buffer->cur_line, buffer->cur_index, 1 + ); + /* remove trailing newline if it exists - this may be hacky */ + int text_len = paste_buffer->len; + if (paste_buffer->text[paste_buffer->len-1] == '\n') { + text_len--; + paste_buffer->text[paste_buffer->len-1] = '\0'; + } + insert_text( + buffer, buffer->cur_line + 1, 0, + paste_buffer->text, text_len, buffer->cur_line + 1, 0, 0 + ); + } else { + /* must allow illegal index so text can be pasted at end of line */ + move_cursor_logically(buffer, 1, 1); + insert_text( + buffer, buffer->cur_line, buffer->cur_index, + paste_buffer->text, paste_buffer->len, buffer->cur_line, buffer->cur_index, 1 + ); + } ledit_buffer_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_index); finalize_repetition_stack(); + return (struct action){ACTION_NONE, NULL}; } static struct action @@ -794,7 +850,7 @@ delete_key(ledit_buffer *buffer, char *text, int len) { } static void -move_cursor_left_right(ledit_buffer *buffer, int dir) { +move_cursor_left_right(ledit_buffer *buffer, int dir, int allow_illegal_index) { int num = 1; struct key_stack_elem *e = pop_key_stack(); if (e != NULL) { @@ -839,7 +895,9 @@ move_cursor_left_right(ledit_buffer *buffer, int dir) { /* 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) { - if (buffer->common->mode == NORMAL && (e == NULL || e->motion_cb == NULL)) { + if (!allow_illegal_index && + buffer->common->mode == NORMAL && + (e == NULL || e->motion_cb == NULL)) { new_index = last_index; } else { /* FIXME: I guess this is unnecessary */ @@ -868,7 +926,7 @@ static struct action cursor_left(ledit_buffer *buffer, char *text, int len) { (void)text; (void)len; - move_cursor_left_right(buffer, -1); + move_cursor_left_right(buffer, -1, 0); return (struct action){ACTION_NONE, NULL}; } @@ -876,7 +934,7 @@ static struct action cursor_right(ledit_buffer *buffer, char *text, int len) { (void)text; (void)len; - move_cursor_left_right(buffer, 1); + move_cursor_left_right(buffer, 1, 0); return (struct action){ACTION_NONE, NULL}; } @@ -887,7 +945,7 @@ return_key(ledit_buffer *buffer, char *text, int len) { int start_group = 1; if (delete_selection(buffer)) start_group = 0; - insert_text(buffer, buffer->cur_line, buffer->cur_index, "\n", -1, start_group); + insert_text(buffer, buffer->cur_line, buffer->cur_index, "\n", -1, -1, -1, start_group); /* FIXME: these aren't needed, right? This only works in insert mode * anyways, so there's nothing to wipe */ /* ledit_buffer_wipe_line_cursor_attrs(buffer, buffer->cur_line); @@ -954,6 +1012,28 @@ pango_layout_get_direction(PangoLayout *layout, int index) { } #endif +static void +move_cursor_logically(ledit_buffer *buffer, int movement_dir, int allow_illegal_index) { + PangoDirection dir = PANGO_DIRECTION_RTL; + 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); + } else { + if (movement_dir < 0) + move_cursor_left_right(buffer, -1, allow_illegal_index); + else + move_cursor_left_right(buffer, 1, allow_illegal_index); + } +} + static struct action escape_key(ledit_buffer *buffer, char *text, int len) { (void)text; @@ -968,18 +1048,7 @@ escape_key(ledit_buffer *buffer, char *text, int len) { } else { ledit_buffer_set_mode(buffer, NORMAL); clear_key_stack(); - PangoDirection dir = PANGO_DIRECTION_RTL; - 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) { - cursor_right(buffer, NULL, 0); - } else { - cursor_left(buffer, NULL, 0); - } + move_cursor_logically(buffer, -1, 0); if (buffer->sel.line1 != buffer->sel.line2) { int min = buffer->sel.line1 < buffer->sel.line2 ? buffer->sel.line1 : buffer->sel.line2; int max = buffer->sel.line1 > buffer->sel.line2 ? buffer->sel.line1 : buffer->sel.line2; @@ -1217,7 +1286,7 @@ redo(ledit_buffer *buffer, char *text, int len) { static struct action insert_mode_insert_text(ledit_buffer *buffer, char *text, int len) { delete_selection(buffer); - insert_text(buffer, buffer->cur_line, buffer->cur_index, text, len, 1); + insert_text(buffer, buffer->cur_line, buffer->cur_index, text, len, -1, -1, 1); return (struct action){ACTION_NONE, NULL}; } diff --git a/keys_basic_config.h b/keys_basic_config.h @@ -64,6 +64,7 @@ static struct action scroll_with_cursor_down(ledit_buffer *buffer, char *text, i static struct action scroll_lines_up(ledit_buffer *buffer, char *text, int len); static struct action scroll_lines_down(ledit_buffer *buffer, char *text, int len); static struct action move_to_line(ledit_buffer *buffer, char *text, int len); +static struct action paste_normal(ledit_buffer *buffer, char *text, int len); /* FIXME: maybe sort these and use binary search -> but that would mess with the catch-all keys */ @@ -121,6 +122,7 @@ static struct key keys_en[] = { {"d", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_lines_down}, {"u", ControlMask, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &scroll_lines_up}, {"G", 0, 0, NORMAL, KEY_ANY, KEY_NUMBERALLOWED, &move_to_line}, + {"p", 0, 0, NORMAL, KEY_ANY, KEY_ANY, &paste_normal}, {"", 0, 0, INSERT, KEY_ANY, KEY_ANY, &insert_mode_insert_text} };