diff options
| author | Riley Beckett <rbeckettvt@gmail.com> | 2025-10-26 19:55:26 -0400 |
|---|---|---|
| committer | Riley Beckett <rbeckettvt@gmail.com> | 2025-10-26 19:55:26 -0400 |
| commit | 500cd948a40a9ad2ee8e123254d66259c46464d6 (patch) | |
| tree | 8a0d1a8364fbf11d02e7df40ceb4b8081644e903 | |
| parent | 8003084ccf17b26e932b565cfc0bb30302af3dd7 (diff) | |
refactor keybinds
| -rw-r--r-- | array.h | 16 | ||||
| -rw-r--r-- | graphics.c | 2 | ||||
| -rw-r--r-- | input_field.c | 136 | ||||
| -rw-r--r-- | input_field.h | 5 | ||||
| -rw-r--r-- | keybind.c | 122 | ||||
| -rw-r--r-- | keybind.h | 34 |
6 files changed, 202 insertions, 113 deletions
@@ -27,12 +27,16 @@ void* array_resize_(void* array, size_t item_size, size_t size); (array) = NULL; \ } while (0) -#define array_erase(array, index) do { \ - if ((index)) { \ - for (int __i = (index) - 1; __i < array_size((array)) - 1; __i++) \ - (array)[__i] = (array)[__i + 1]; \ - ((array_info*)(array))[-1].size--; \ - } \ +#define array_erase(array, index) do { \ + for (int __i = (index); __i < array_size((array)) - 1; __i++) \ + (array)[__i] = (array)[__i + 1]; \ + ((array_info*)(array))[-1].size--; \ +} while(0) + +#define array_erase_range(array, startinc, endinc) do { \ + for (int __i = (startinc); __i < array_size((array)) - ((endinc) - (startinc) + 1); __i++) \ + (array)[__i] = (array)[__i + ((endinc) - (startinc) + 1)]; \ + ((array_info*)(array))[-1].size -= ((endinc) - (startinc) + 1); \ } while(0) #define array_insert(array, index, value) do { \ @@ -203,7 +203,7 @@ void render_frame(client_state *state) { glUniform4f(state->b_color_uniform, cursor_color.r,cursor_color.g,cursor_color.b,cursor_color.a); glUniform2f(state->b_screen_size_uniform, state->width, state->height); glUniform2f(state->b_start_uniform, atlas_get_strwidth_len(state, state->input_buffer, state->cursor_index) + state->horizontal_spacing / 2.0f, input_y); - glUniform2f(state->b_size_uniform, state->cursor_index == array_size(state->input_buffer) ? state->atlas.metrics['M'].bitmap_width : state->atlas.metrics[(int)state->input_buffer[state->cursor_index]].bitmap_width, state->line_height); + glUniform2f(state->b_size_uniform, state->cursor_index == array_size(state->input_buffer) ? state->atlas.metrics['M'].bitmap_width : state->atlas.metrics[(int)state->input_buffer[state->cursor_index]].advance_x, state->line_height); glDrawArrays(GL_TRIANGLES, 0, 6); float start; diff --git a/input_field.c b/input_field.c index f6820d4..981a18b 100644 --- a/input_field.c +++ b/input_field.c @@ -49,108 +49,48 @@ bool type_key(client_state* state, xkb_keysym_t keysym) { bool ctrl = xkb_state_mod_name_is_active(state->xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE); bool alt = xkb_state_mod_name_is_active(state->xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE); - // exit app - if ((keysym == XKB_KEY_c && ctrl) || - (keysym == XKB_KEY_g && ctrl) || - (keysym == XKB_KEY_Escape)) { - - state->running = false; - state->exit_code = EXIT_FAILURE; - return false; - } - - // complete - if ((keysym == XKB_KEY_i && ctrl && alt) || keysym == XKB_KEY_Tab) { - if (state->selected_filtered_item != -1) { - char* selected = state->filtered_items[state->selected_filtered_item].item->text; - size_t len = strlen(selected); - - array_free(state->input_buffer); - state->input_buffer = array_new(char, len); - memcpy(state->input_buffer, selected, len); - state->cursor_index = len; - - update_text_buffer(state); - } - return true; - } - - // select next - if ((keysym == XKB_KEY_n && ctrl) || keysym == XKB_KEY_Right || keysym == XKB_KEY_Down) { - if (state->selected_filtered_item != -1) { - state->selected_filtered_item = MIN(state->selected_filtered_item + 1, (int)array_size(state->filtered_items) - 1); + if (ctrl && alt) { + switch (keysym) { + case XKB_KEY_i: return insert_selected(state); + case XKB_KEY_d: return delete_word(state); } - return true; } + else if (ctrl) { + switch (keysym) { + case XKB_KEY_c: + case XKB_KEY_g: + return quit(state); - // select previous - if ((keysym == XKB_KEY_p && ctrl) || keysym == XKB_KEY_Left || keysym == XKB_KEY_Up) { - if (state->selected_filtered_item != -1) { - state->selected_filtered_item = MAX(state->selected_filtered_item - 1, 0); - } - return true; - } + case XKB_KEY_n: return select_next(state); + case XKB_KEY_p: return select_previous(state); - if (keysym == XKB_KEY_e && ctrl) { - state->cursor_index = array_size(state->input_buffer); - return true; - } + case XKB_KEY_e: return goto_end(state); + case XKB_KEY_a: return goto_begining(state); - if (keysym == XKB_KEY_a && ctrl) { - state->cursor_index = 0; - return true; - } + case XKB_KEY_f: return forward_char(state); + case XKB_KEY_b: return backward_char(state); - if (keysym == XKB_KEY_f && ctrl) { - if (state->cursor_index < array_size(state->input_buffer)) { - state->cursor_index++; + case XKB_KEY_k: return kill_to_end(state); + case XKB_KEY_d: return delete_char(state); + case XKB_KEY_BackSpace: + case XKB_KEY_Delete: + return clear_input(state); } - return true; } - - if (keysym == XKB_KEY_b && ctrl) { - if (state->cursor_index > 0) { - state->cursor_index--; + else if (alt) { + switch (keysym) { + case XKB_KEY_d: return delete_word(state); } - return true; } - - if (keysym == XKB_KEY_k && ctrl) { - array_resize(state->input_buffer, state->cursor_index); - update_text_buffer(state); - return true; - } - - // paste - if (keysym == XKB_KEY_v && ctrl) { - - array_insert_many(state->input_buffer, state->cursor_index, state->clipboard, state->clipboard_size); - state->cursor_index += state->clipboard_size; - - update_text_buffer(state); - - return true; - } - - // submit line - if (keysym == XKB_KEY_Return || keysym == XKB_KEY_KP_Enter) { - submit_line(state); - return false; - } - - // delete - if (keysym == XKB_KEY_BackSpace || keysym == XKB_KEY_Delete) { - if (ctrl) { - array_clear(state->input_buffer); - state->cursor_index = 0; - } else { - if (state->cursor_index) { - array_erase(state->input_buffer, state->cursor_index); - state->cursor_index--; - } - } - update_text_buffer(state); - return true; + switch (keysym) { + case XKB_KEY_Tab: return insert_selected(state); + case XKB_KEY_Escape: return quit(state); + case XKB_KEY_Return: + case XKB_KEY_KP_Enter: + return submit_line(state); + case XKB_KEY_BackSpace: + case XKB_KEY_Delete: + return delete_char_backward(state); } // type char into buffer @@ -168,15 +108,3 @@ bool type_key(client_state* state, xkb_keysym_t keysym) { return false; } -void submit_line(client_state* state) { - if (state->exact_match) { - if (state->selected_filtered_item == -1) return; - printf("%s\n", state->filtered_items[state->selected_filtered_item].item->text); - } - else { - if (state->selected_filtered_item == -1) printf("%.*s\n", (int)array_size(state->input_buffer), state->input_buffer); - else printf("%s\n", state->filtered_items[state->selected_filtered_item].item->text); - } - state->running = false; - state->exit_code = EXIT_SUCCESS; -} diff --git a/input_field.h b/input_field.h index ab583e5..6ec588e 100644 --- a/input_field.h +++ b/input_field.h @@ -2,10 +2,11 @@ #define INPUT_FIELD_H_ #include "state.h" +#include "keybind.h" // returns true if the key should repeat -bool type_key(client_state* state, xkb_keysym_t keysym); +key_repeat_t type_key(client_state* state, xkb_keysym_t keysym); void filter_items(client_state* state); -void submit_line(client_state* state); +void update_text_buffer(client_state* state); #endif diff --git a/keybind.c b/keybind.c new file mode 100644 index 0000000..986ec4c --- /dev/null +++ b/keybind.c @@ -0,0 +1,122 @@ +#include "keybind.h" +#include "array.h" +#include "input_field.h" + +key_repeat_t quit(client_state* state) { + state->running = false; + state->exit_code = EXIT_FAILURE; + return KEY_NO_REPEAT; +} + +key_repeat_t submit_line(client_state* state) { + if (state->exact_match) { + if (state->selected_filtered_item == -1) return false; + printf("%s\n", state->filtered_items[state->selected_filtered_item].item->text); + } + else { + if (state->selected_filtered_item == -1) printf("%.*s\n", (int)array_size(state->input_buffer), state->input_buffer); + else printf("%s\n", state->filtered_items[state->selected_filtered_item].item->text); + } + state->running = false; + state->exit_code = EXIT_SUCCESS; + return KEY_NO_REPEAT; +} + +key_repeat_t insert_selected(client_state* state) { + if (state->selected_filtered_item != -1) { + char* selected = state->filtered_items[state->selected_filtered_item].item->text; + size_t len = strlen(selected); + + array_free(state->input_buffer); + state->input_buffer = array_new(char, len); + memcpy(state->input_buffer, selected, len); + state->cursor_index = len; + + update_text_buffer(state); + } + return KEY_NO_REPEAT; +} + +key_repeat_t select_next(client_state* state) { + if (state->selected_filtered_item != -1) { + state->selected_filtered_item = MIN(state->selected_filtered_item + 1, (int)array_size(state->filtered_items) - 1); + } + return KEY_REPEAT; +} + +key_repeat_t select_previous(client_state* state) { + if (state->selected_filtered_item != -1) { + state->selected_filtered_item = MAX(state->selected_filtered_item - 1, 0); + } + return KEY_REPEAT; +} + +key_repeat_t goto_end(client_state* state) { + state->cursor_index = array_size(state->input_buffer); + return KEY_NO_REPEAT; +} + +key_repeat_t goto_begining(client_state* state) { + state->cursor_index = 0; + return KEY_NO_REPEAT; +} + +key_repeat_t forward_char(client_state* state) { + if (state->cursor_index < array_size(state->input_buffer)) { + state->cursor_index++; + } + return KEY_REPEAT; +} + +key_repeat_t backward_char(client_state* state) { + if (state->cursor_index > 0) { + state->cursor_index--; + } + return KEY_REPEAT; +} + +key_repeat_t kill_to_end(client_state* state) { + array_resize(state->input_buffer, state->cursor_index); + update_text_buffer(state); + return KEY_NO_REPEAT; +} + +key_repeat_t delete_word(client_state* state) { + if (state->cursor_index != array_size(state->input_buffer)) { + size_t endidx = state->cursor_index; + for (; endidx < array_size(state->input_buffer) - 1; endidx++) { + if (state->input_buffer[endidx] == ' ') { + break; + } + } + array_erase_range(state->input_buffer, state->cursor_index, endidx); + update_text_buffer(state); + } + return KEY_REPEAT; +} + +key_repeat_t delete_char(client_state* state) { + if (state->cursor_index != array_size(state->input_buffer)) { + array_erase(state->input_buffer, state->cursor_index); + update_text_buffer(state); + return KEY_NO_REPEAT; + } + return KEY_REPEAT; +} + +key_repeat_t delete_char_backward(client_state* state) { + if (state->cursor_index) { + array_erase(state->input_buffer, state->cursor_index - 1); + state->cursor_index--; + update_text_buffer(state); + return KEY_REPEAT; + } + return KEY_NO_REPEAT; +} + +key_repeat_t clear_input(client_state* state) { + array_clear(state->input_buffer); + state->cursor_index = 0; + update_text_buffer(state); + return KEY_NO_REPEAT; +} diff --git a/keybind.h b/keybind.h new file mode 100644 index 0000000..a574093 --- /dev/null +++ b/keybind.h @@ -0,0 +1,34 @@ +#ifndef KEYBIND_H_ +#define KEYBIND_H_ +#include <stdbool.h> + +#include "state.h" + +typedef bool key_repeat_t; + +#define KEY_REPEAT 1 +#define KEY_NO_REPEAT 0 + +key_repeat_t quit(client_state* state); + +key_repeat_t submit_line(client_state* state); + +key_repeat_t insert_selected(client_state* state); + +key_repeat_t select_next(client_state* state); +key_repeat_t select_previous(client_state* state); + +key_repeat_t goto_end(client_state* state); +key_repeat_t goto_begining(client_state* state); + +key_repeat_t forward_char(client_state* state); +key_repeat_t backward_char(client_state* state); + +key_repeat_t kill_to_end(client_state* state); + +key_repeat_t delete_word(client_state* state); +key_repeat_t delete_char(client_state* state); +key_repeat_t delete_char_backward(client_state* state); + +key_repeat_t clear_input(client_state* state); +#endif // KEYBIND_H_ |
