commit 271d268ba17415be9808bb1da36389036b4eb95d
parent e5841801447358ed8f2f57e3dc0adc2873fb500e
Author: lumidify <nobody@lumidify.org>
Date: Mon, 1 Nov 2021 13:17:15 +0100
Implement pasting (well, sort of)
Diffstat:
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}
};