From 4e9def97e391e0f045b88c979539f633b67061c3 Mon Sep 17 00:00:00 2001 From: player01osu Date: Mon, 4 Nov 2024 13:07:19 -0500 Subject: [PATCH 1/2] Add ctrl-y to copy selected into input --- doc/tofi.1.md | 4 ++++ doc/tofi.1.scd | 3 +++ src/input.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/doc/tofi.1.md b/doc/tofi.1.md index fe6e575..9860a3e 100644 --- a/doc/tofi.1.md +++ b/doc/tofi.1.md @@ -66,6 +66,10 @@ the form **--key=value**. > Delete word. +\-y + +> Copy current selection into input. + \ > Confirm the current selection and quit. diff --git a/doc/tofi.1.scd b/doc/tofi.1.scd index 716421d..705b0b1 100644 --- a/doc/tofi.1.scd +++ b/doc/tofi.1.scd @@ -57,6 +57,9 @@ All config file options described in *tofi*(5) are also accepted, in the form -w | - Delete word. +-y + Copy current selection into input. + Confirm the current selection and quit. diff --git a/src/input.c b/src/input.c index 58154a7..b6cb5aa 100644 --- a/src/input.c +++ b/src/input.c @@ -14,6 +14,7 @@ static void add_character(struct tofi *tofi, xkb_keycode_t keycode); static void delete_character(struct tofi *tofi); static void delete_word(struct tofi *tofi); static void clear_input(struct tofi *tofi); +static void complete_selection(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); @@ -68,6 +69,8 @@ void input_handle_keypress(struct tofi *tofi, xkb_keycode_t keycode) clear_input(tofi); } else if (key == KEY_V && ctrl) { paste(tofi); + } else if (key == KEY_Y && ctrl) { + complete_selection(tofi); } else if (key == KEY_LEFT) { previous_cursor_or_result(tofi); } else if (key == KEY_RIGHT) { @@ -304,6 +307,32 @@ void clear_input(struct tofi *tofi) input_refresh_results(tofi); } +void complete_selection(struct tofi *tofi) +{ + struct entry *entry = &tofi->window.entry; + uint32_t selection = entry->selection + entry->first_result; + char *res = entry->results.buf[selection].string; + uint32_t len = strlen(res); + + if (len + 1 < N_ELEM(entry->input_utf32)) { + for (size_t i = 0; i < len; ++i) { + entry->input_utf32[i] = res[i]; + } + entry->input_utf32[len] = U'\0'; + entry->cursor_position = len; + } else { + for (size_t i = 0; i < N_ELEM(entry->input_utf32); ++i) { + entry->input_utf32[i] = res[i]; + } + entry->input_utf32[N_ELEM(entry->input_utf32) - 1] = U'\0'; + entry->cursor_position = N_ELEM(entry->input_utf32) - 1; + } + entry->input_utf32_length = entry->cursor_position; + + input_refresh_results(tofi); + tofi->window.surface.redraw = true; +} + void paste(struct tofi *tofi) { if (tofi->clipboard.wl_data_offer == NULL || tofi->clipboard.mime_type == NULL) { From 4db80d5b96beb8c66efda2830b3488279c60d782 Mon Sep 17 00:00:00 2001 From: player01osu Date: Mon, 4 Nov 2024 23:36:08 -0500 Subject: [PATCH 2/2] Fix copy selected to work with utf-8 --- src/input.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/input.c b/src/input.c index b6cb5aa..aed8b23 100644 --- a/src/input.c +++ b/src/input.c @@ -312,20 +312,43 @@ void complete_selection(struct tofi *tofi) struct entry *entry = &tofi->window.entry; uint32_t selection = entry->selection + entry->first_result; char *res = entry->results.buf[selection].string; - uint32_t len = strlen(res); + if (!res) { + return; + } + + char buffer[5]; + memset(buffer, 0, N_ELEM(buffer)); + errno = 0; + bool eof = false; + size_t pos = 0; - if (len + 1 < N_ELEM(entry->input_utf32)) { - for (size_t i = 0; i < len; ++i) { - entry->input_utf32[i] = res[i]; + entry->cursor_position = 0; + while (entry->cursor_position < N_ELEM(entry->input_utf32)) { + for (size_t i = 0; i < 4; i++) { + if (!res[pos]) { + eof = true; + break; + } + + buffer[i] = res[pos]; + pos += 1; + uint32_t unichar = utf8_to_utf32_validate(buffer); + if (unichar == (uint32_t)-2) { + /* The current character isn't complete yet. */ + continue; + } else if (unichar == (uint32_t)-1) { + log_error("Invalid UTF-8 character in clipboard: %s\n", buffer); + break; + } else { + entry->input_utf32[entry->cursor_position] = unichar; + entry->cursor_position++; + break; + } } - entry->input_utf32[len] = U'\0'; - entry->cursor_position = len; - } else { - for (size_t i = 0; i < N_ELEM(entry->input_utf32); ++i) { - entry->input_utf32[i] = res[i]; + memset(buffer, 0, N_ELEM(buffer)); + if (eof) { + break; } - entry->input_utf32[N_ELEM(entry->input_utf32) - 1] = U'\0'; - entry->cursor_position = N_ELEM(entry->input_utf32) - 1; } entry->input_utf32_length = entry->cursor_position;