tAdd basic repetition and motion callback support to cursor movement keys - led… | |
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 3895a14f2fb3bcc35ba842e259074a67adddb8a1 | |
parent 52cea73bf0e43483210cb94e5177989bc524a30c | |
Author: lumidify <[email protected]> | |
Date: Thu, 13 May 2021 21:54:24 +0200 | |
Add basic repetition and motion callback support to cursor movement keys | |
Diffstat: | |
M buffer.c | 12 +++++++++--- | |
M ledit.c | 249 ++++++++++++++++++++---------… | |
2 files changed, 171 insertions(+), 90 deletions(-) | |
--- | |
diff --git a/buffer.c b/buffer.c | |
t@@ -494,10 +494,16 @@ ledit_delete_range( | |
} | |
delete_line_section(buffer, line_index1, b1, b2 - b1); | |
*new_line_ret = line_index1; | |
+ ledit_line *ll = ledit_get_line(buffer, line_index1); | |
+ /* FIXME: where should this be done? */ | |
+ /* FIXME: also do this below in the else statement */ | |
+ if (buffer->state->mode == NORMAL && b1 == ll->len && … | |
+ /* FIXME: use grapheme instead of character! */ | |
+ b1 = ll->len - 1; | |
+ while (b1 > 0 && ((ll->text[b1] & 0xC0) == 0x8… | |
+ b1--; | |
+ } | |
*new_byte_ret = b1; | |
- /* FIXME: this needs to be checked by calling code to | |
- move cursor one back if in normal mode and at end | |
- of line */ | |
} else { | |
int l1, l2, b1, b2; | |
if (line_index1 < line_index2) { | |
diff --git a/ledit.c b/ledit.c | |
t@@ -91,9 +91,10 @@ static void resize_window(int w, int h); | |
static void backspace(void); | |
static void delete_key(void); | |
-static void move_cursor(int dir); | |
+static void move_cursor_left_right(int dir); | |
static void cursor_left(void); | |
static void cursor_right(void); | |
+static void move_cursor_up_down(int dir); | |
static void cursor_down(void); | |
static void cursor_up(void); | |
static void cursor_to_beginning(void); | |
t@@ -117,6 +118,67 @@ static void key_d_cb(int line, int char_pos, enum key_typ… | |
static void change_keyboard(char *lang); | |
static void key_press(XEvent event); | |
+static void get_new_line_softline( | |
+ int cur_line, int cur_index, int movement, | |
+ int *new_line_ret, int *new_softline_ret | |
+); | |
+ | |
+static void | |
+get_new_line_softline( | |
+ int cur_line, int cur_index, int movement, | |
+ int *new_line_ret, int *new_softline_ret) { | |
+ ledit_line *line = ledit_get_line(buffer, cur_line); | |
+ int x, softline; | |
+ pango_layout_index_to_line_x(line->layout, cur_index, 0, &softline, &x… | |
+ if (movement > 0) { | |
+ int softlines = pango_layout_get_line_count(line->layout); | |
+ if (softlines - softline > movement) { | |
+ *new_line_ret = cur_line; | |
+ *new_softline_ret = softline + movement; | |
+ } else { | |
+ movement -= (softlines - softline - 1); | |
+ int endline = cur_line + 1; | |
+ while (movement > 0 && endline < buffer->lines_num) { | |
+ line = ledit_get_line(buffer, endline); | |
+ softlines = pango_layout_get_line_count(line->… | |
+ movement -= softlines; | |
+ endline++; | |
+ } | |
+ endline--; | |
+ if (movement <= 0) { | |
+ *new_softline_ret = movement + softlines - 1; | |
+ } else { | |
+ *new_softline_ret = softlines - 1; | |
+ } | |
+ *new_line_ret = endline; | |
+ } | |
+ } else if (movement < 0) { | |
+ int softlines = 0; | |
+ if (softline + movement >= 0) { | |
+ *new_line_ret = cur_line; | |
+ *new_softline_ret = softline + movement; | |
+ } else { | |
+ movement += softline; | |
+ int endline = cur_line - 1; | |
+ while (movement < 0 && endline >= 0) { | |
+ line = ledit_get_line(buffer, endline); | |
+ softlines = pango_layout_get_line_count(line->… | |
+ movement += softlines; | |
+ endline--; | |
+ } | |
+ endline++; | |
+ if (movement >= 0) { | |
+ *new_softline_ret = movement; | |
+ } else { | |
+ *new_softline_ret = 0; | |
+ } | |
+ *new_line_ret = endline; | |
+ } | |
+ } else { | |
+ *new_line_ret = cur_line; | |
+ *new_softline_ret = softline; | |
+ } | |
+} | |
static void | |
key_d(void) { | |
t@@ -132,33 +194,14 @@ key_d(void) { | |
int prevnum = e->count > 0 ? e->count : 1; | |
num = num > 0 ? num : 1; | |
int lines = num * prevnum; | |
- | |
- ledit_line *line = ledit_get_line(buffer, buffer->cur_… | |
- int x, softline; | |
- pango_layout_index_to_line_x(line->layout, buffer->cur… | |
- int softlines = pango_layout_get_line_count(line->layo… | |
- if (softlines - softline >= lines) { | |
- PangoLayoutLine *l = pango_layout_get_line_rea… | |
- e->motion_cb(buffer->cur_line, l->start_index,… | |
- } else { | |
- lines -= (softlines - softline); | |
- int endline = buffer->cur_line + 1; | |
- while (lines > 0 && endline < buffer->lines_nu… | |
- line = ledit_get_line(buffer, endline); | |
- softlines = pango_layout_get_line_coun… | |
- lines -= softlines; | |
- endline++; | |
- } | |
- endline--; | |
- int endsoftline = 0; | |
- if (lines <= 0) { | |
- endsoftline = lines + softlines - 1; | |
- } else { | |
- endsoftline = softlines - 1; | |
- } | |
- PangoLayoutLine *l = pango_layout_get_line_rea… | |
- e->motion_cb(endline, l->start_index, KEY_MOTI… | |
- } | |
+ int new_line, new_softline; | |
+ get_new_line_softline( | |
+ buffer->cur_line, buffer->cur_index, lines - 1, | |
+ &new_line, &new_softline | |
+ ); | |
+ ledit_line *ll = ledit_get_line(buffer, new_line); | |
+ PangoLayoutLine *pl = pango_layout_get_line_readonly(l… | |
+ e->motion_cb(new_line, pl->start_index, KEY_MOTION_LIN… | |
clear_key_stack(); | |
} else if (e != NULL) { | |
clear_key_stack(); | |
t@@ -175,7 +218,6 @@ key_d(void) { | |
/* FIXME: should this get number of lines to remove or actual end line? */ | |
static void | |
key_d_cb(int line, int char_pos, enum key_type type) { | |
- printf("%d, %d\n", line, char_pos); | |
int line_based = type == KEY_MOTION_LINE ? 1 : 0; | |
ledit_delete_range( | |
buffer, line_based, | |
t@@ -819,51 +861,79 @@ delete_key(void) { | |
ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_inde… | |
} | |
-/* FIXME: this comment needs to be implemented still */ | |
-/* num is number of graphemes to move (see pango documentation) - negative | |
- * is left, positive is right */ | |
static void | |
-move_cursor(int dir) { | |
+move_cursor_left_right(int dir) { | |
+ int num = 1; | |
+ struct key_stack_elem *e = pop_key_stack(); | |
+ if (e != NULL) { | |
+ if (e->key & KEY_NUMBER) { | |
+ num = e->count > 0 ? e->count : 0; | |
+ e = pop_key_stack(); | |
+ } | |
+ if (e != NULL) | |
+ num *= (e->count > 0 ? e->count : 1); | |
+ } | |
+ | |
/* FIXME: trailing */ | |
- int trailing, last_index = buffer->cur_index; | |
+ int trailing = 0, tmp_index; | |
ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line); | |
- pango_layout_move_cursor_visually( | |
- cur_line->layout, TRUE, | |
- buffer->cur_index, 0, dir, | |
- &buffer->cur_index, &trailing | |
- ); | |
+ 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--; | |
- buffer->cur_index++; | |
- while (buffer->cur_index < cur_line->len && | |
- ((cur_line->text[buffer->cur_index] & 0xC0) == 0x80)) | |
- buffer->cur_index++; | |
+ new_index++; | |
+ while (new_index < cur_line->len && | |
+ ((cur_line->text[new_index] & 0xC0) == 0x80)) | |
+ new_index++; | |
} | |
- if (buffer->cur_index < 0) | |
- buffer->cur_index = 0; | |
+ if (new_index < 0) | |
+ new_index = 0; | |
/* when in normal mode, the cursor cannot be at the very end | |
of the line because it's always covering a character */ | |
- if (buffer->cur_index >= cur_line->len) { | |
- if (state.mode == NORMAL) | |
- buffer->cur_index = last_index; | |
- else | |
- buffer->cur_index = cur_line->len; | |
+ if (new_index >= cur_line->len) { | |
+ if (state.mode == NORMAL && (e == NULL || e->motion_cb == NULL… | |
+ new_index = last_index; | |
+ } else { | |
+ /* FIXME: I guess this is unnecessary */ | |
+ new_index = cur_line->len; | |
+ } | |
} | |
- ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_inde… | |
+ if (e != NULL & e->motion_cb != NULL) { | |
+ e->motion_cb(buffer->cur_line, new_index, KEY_MOTION_CHAR); | |
+ } else { | |
+ buffer->cur_index = new_index; | |
+ ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->… | |
+ } | |
+ clear_key_stack(); | |
} | |
static void | |
cursor_left(void) { | |
- move_cursor(-1); | |
+ move_cursor_left_right(-1); | |
} | |
static void | |
cursor_right(void) { | |
- move_cursor(1); | |
+ move_cursor_left_right(1); | |
} | |
static void | |
t@@ -901,48 +971,53 @@ enter_insert(void) { | |
ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
} | |
+/* FIXME: Check if previous key allows motion command - or is this checked aut… | |
static void | |
-cursor_down(void) { | |
- int lineno, x; | |
- ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line); | |
- ledit_pos_to_x_softline(cur_line, buffer->cur_index, &x, &lineno); | |
- | |
- int maxlines = pango_layout_get_line_count(cur_line->layout); | |
- if (lineno == maxlines - 1) { | |
- ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
- /* move to the next hard line */ | |
- if (buffer->cur_line < buffer->lines_num - 1) { | |
- buffer->cur_line++; | |
- cur_line = ledit_get_line(buffer, buffer->cur_line); | |
- ledit_x_softline_to_pos(cur_line, x, 0, &buffer->cur_i… | |
+move_cursor_up_down(int dir) { | |
+ int new_line, new_softline; | |
+ | |
+ int num = 1; | |
+ struct key_stack_elem *e = pop_key_stack(); | |
+ if (e != NULL) { | |
+ if (e->key & KEY_NUMBER) { | |
+ num = e->count > 0 ? e->count : 0; | |
+ e = pop_key_stack(); | |
} | |
+ if (e != NULL) | |
+ num *= (e->count > 0 ? e->count : 1); | |
+ } | |
+ num *= dir; | |
+ | |
+ get_new_line_softline( | |
+ buffer->cur_line, buffer->cur_index, num, | |
+ &new_line, &new_softline | |
+ ); | |
+ | |
+ ledit_line *cur_lline = ledit_get_line(buffer, buffer->cur_line); | |
+ ledit_line *new_lline = ledit_get_line(buffer, new_line); | |
+ if (e != NULL && e->motion_cb != NULL) { | |
+ PangoLayoutLine *pl = pango_layout_get_line_readonly(new_lline… | |
+ e->motion_cb(new_line, pl->start_index, KEY_MOTION_LINE); | |
} else { | |
- /* move to the next soft line */ | |
- ledit_x_softline_to_pos(cur_line, x, lineno + 1, &buffer->cur_… | |
+ int lineno, x; | |
+ ledit_pos_to_x_softline(cur_lline, buffer->cur_index, &x, &lin… | |
+ ledit_x_softline_to_pos(new_lline, x, new_softline, &buffer->c… | |
+ if (buffer->cur_line != new_line) | |
+ ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
+ buffer->cur_line = new_line; | |
+ ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->… | |
} | |
- ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_inde… | |
+ clear_key_stack(); | |
+} | |
+ | |
+static void | |
+cursor_down(void) { | |
+ move_cursor_up_down(1); | |
} | |
static void | |
cursor_up(void) { | |
- int lineno, x; | |
- ledit_line *cur_line = ledit_get_line(buffer, buffer->cur_line); | |
- ledit_pos_to_x_softline(cur_line, buffer->cur_index, &x, &lineno); | |
- buffer->trailing = 0; | |
- if (lineno == 0) { | |
- ledit_wipe_line_cursor_attrs(buffer, buffer->cur_line); | |
- /* move to the previous hard line */ | |
- if (buffer->cur_line > 0) { | |
- buffer->cur_line--; | |
- cur_line = ledit_get_line(buffer, buffer->cur_line); | |
- int maxlines = pango_layout_get_line_count(cur_line->l… | |
- ledit_x_softline_to_pos(cur_line, x, maxlines - 1, &bu… | |
- } | |
- } else { | |
- /* move to the previous soft line */ | |
- ledit_x_softline_to_pos(cur_line, x, lineno - 1, &buffer->cur_… | |
- } | |
- ledit_set_line_cursor_attrs(buffer, buffer->cur_line, buffer->cur_inde… | |
+ move_cursor_up_down(-1); | |
} | |
static void |