From 6c47cf7892d0f212b04e7b798e53c120f51022d7 Mon Sep 17 00:00:00 2001 From: Phil Jones Date: Tue, 20 Dec 2022 23:53:20 +0000 Subject: Add text cursor support. This turned out to be much more complex than anticipated, and the potential for bugs is therefore quite high. --- src/input.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 87 insertions(+), 22 deletions(-) (limited to 'src/input.c') diff --git a/src/input.c b/src/input.c index 9be16e9..be65e24 100644 --- a/src/input.c +++ b/src/input.c @@ -16,6 +16,8 @@ static void clear_input(struct tofi *tofi); static void paste(struct tofi *tofi); static void select_previous_result(struct tofi *tofi); static void select_next_result(struct tofi *tofi); +static void next_cursor_or_result(struct tofi *tofi); +static void previous_cursor_or_result(struct tofi *tofi); static void reset_selection(struct tofi *tofi); void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) @@ -62,6 +64,10 @@ void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) ) { paste(tofi); + } else if (sym == XKB_KEY_Left) { + previous_cursor_or_result(tofi); + } else if (sym == XKB_KEY_Right) { + next_cursor_or_result(tofi); } else if (sym == XKB_KEY_Up || sym == XKB_KEY_Left || sym == XKB_KEY_ISO_Left_Tab || (key == KEY_K && xkb_state_mod_name_is_active( @@ -122,24 +128,38 @@ void add_character(struct tofi *tofi, xkb_keycode_t keycode) keycode, buf, sizeof(buf)); - entry->input_utf32[entry->input_utf32_length] = utf8_to_utf32(buf); - entry->input_utf32_length++; - entry->input_utf32[entry->input_utf32_length] = U'\0'; - memcpy(&entry->input_utf8[entry->input_utf8_length], - buf, - N_ELEM(buf)); - entry->input_utf8_length += len; - if (entry->drun) { - struct string_ref_vec results = desktop_vec_filter(&entry->apps, entry->input_utf8, tofi->fuzzy_match); - string_ref_vec_destroy(&entry->results); - entry->results = results; + if (entry->cursor_position == entry->input_utf32_length) { + entry->input_utf32[entry->input_utf32_length] = utf8_to_utf32(buf); + entry->input_utf32_length++; + entry->input_utf32[entry->input_utf32_length] = U'\0'; + memcpy(&entry->input_utf8[entry->input_utf8_length], + buf, + N_ELEM(buf)); + entry->input_utf8_length += len; + + if (entry->drun) { + struct string_ref_vec results = desktop_vec_filter(&entry->apps, entry->input_utf8, tofi->fuzzy_match); + string_ref_vec_destroy(&entry->results); + entry->results = results; + } else { + struct string_ref_vec tmp = entry->results; + entry->results = string_ref_vec_filter(&entry->results, entry->input_utf8, tofi->fuzzy_match); + string_ref_vec_destroy(&tmp); + } + + reset_selection(tofi); } else { - struct string_ref_vec tmp = entry->results; - entry->results = string_ref_vec_filter(&entry->results, entry->input_utf8, tofi->fuzzy_match); - string_ref_vec_destroy(&tmp); + for (size_t i = entry->input_utf32_length; i > entry->cursor_position; i--) { + entry->input_utf32[i] = entry->input_utf32[i - 1]; + } + entry->input_utf32[entry->cursor_position] = utf8_to_utf32(buf); + entry->input_utf32_length++; + entry->input_utf32[entry->input_utf32_length] = U'\0'; + + input_refresh_results(tofi); } - reset_selection(tofi); + entry->cursor_position++; } void input_refresh_results(struct tofi *tofi) @@ -173,8 +193,20 @@ void delete_character(struct tofi *tofi) return; } - entry->input_utf32_length--; - entry->input_utf32[entry->input_utf32_length] = U'\0'; + if (entry->cursor_position == 0) { + return; + } else if (entry->cursor_position == entry->input_utf32_length) { + entry->cursor_position--; + entry->input_utf32_length--; + entry->input_utf32[entry->input_utf32_length] = U'\0'; + } else { + for (size_t i = entry->cursor_position - 1; i < entry->input_utf32_length - 1; i++) { + entry->input_utf32[i] = entry->input_utf32[i + 1]; + } + entry->cursor_position--; + entry->input_utf32_length--; + entry->input_utf32[entry->input_utf32_length] = U'\0'; + } input_refresh_results(tofi); } @@ -183,19 +215,26 @@ void delete_word(struct tofi *tofi) { struct entry *entry = &tofi->window.entry; - if (entry->input_utf32_length == 0) { + if (entry->cursor_position == 0) { /* No input to delete. */ return; } - while (entry->input_utf32_length > 0 && utf32_isspace(entry->input_utf32[entry->input_utf32_length - 1])) { - entry->input_utf32_length--; + uint32_t new_cursor_pos = entry->cursor_position; + while (new_cursor_pos > 0 && utf32_isspace(entry->input_utf32[new_cursor_pos - 1])) { + new_cursor_pos--; } - while (entry->input_utf32_length > 0 && !utf32_isspace(entry->input_utf32[entry->input_utf32_length - 1])) { - entry->input_utf32_length--; + while (new_cursor_pos > 0 && !utf32_isspace(entry->input_utf32[new_cursor_pos - 1])) { + new_cursor_pos--; + } + uint32_t new_length = entry->input_utf32_length - (entry->cursor_position - new_cursor_pos); + for (size_t i = 0; i < new_length; i++) { + entry->input_utf32[new_cursor_pos + i] = entry->input_utf32[entry->cursor_position + i]; } + entry->input_utf32_length = new_length; entry->input_utf32[entry->input_utf32_length] = U'\0'; + entry->cursor_position = new_cursor_pos; input_refresh_results(tofi); } @@ -203,6 +242,7 @@ void clear_input(struct tofi *tofi) { struct entry *entry = &tofi->window.entry; + entry->cursor_position = 0; entry->input_utf32_length = 0; entry->input_utf32[0] = U'\0'; @@ -270,3 +310,28 @@ void select_next_result(struct tofi *tofi) entry->last_num_results_drawn = entry->num_results_drawn; } } + +void previous_cursor_or_result(struct tofi *tofi) +{ + struct entry *entry = &tofi->window.entry; + + if (entry->cursor_theme.show + && entry->selection == 0 + && entry->cursor_position > 0) { + entry->cursor_position--; + } else { + select_previous_result(tofi); + } +} + +void next_cursor_or_result(struct tofi *tofi) +{ + struct entry *entry = &tofi->window.entry; + + if (entry->cursor_theme.show + && entry->cursor_position < entry->input_utf32_length) { + entry->cursor_position++; + } else { + select_next_result(tofi); + } +} -- cgit v1.2.3