aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiley Beckett <rbeckettvt@gmail.com>2025-10-26 19:55:26 -0400
committerRiley Beckett <rbeckettvt@gmail.com>2025-10-26 19:55:26 -0400
commit500cd948a40a9ad2ee8e123254d66259c46464d6 (patch)
tree8a0d1a8364fbf11d02e7df40ceb4b8081644e903
parent8003084ccf17b26e932b565cfc0bb30302af3dd7 (diff)
refactor keybinds
-rw-r--r--array.h16
-rw-r--r--graphics.c2
-rw-r--r--input_field.c136
-rw-r--r--input_field.h5
-rw-r--r--keybind.c122
-rw-r--r--keybind.h34
6 files changed, 202 insertions, 113 deletions
diff --git a/array.h b/array.h
index 852461c..37c2cc8 100644
--- a/array.h
+++ b/array.h
@@ -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 { \
diff --git a/graphics.c b/graphics.c
index f462402..ba841dd 100644
--- a/graphics.c
+++ b/graphics.c
@@ -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_