summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--nuklear_ui/blastem_nuklear.c92
-rw-r--r--tern.c54
-rw-r--r--tern.h2
4 files changed, 148 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 65b2da0..667ad84 100644
--- a/Makefile
+++ b/Makefile
@@ -65,8 +65,8 @@ endif #PORTABLE
endif #Windows
ifdef DEBUG
-CFLAGS:=-ggdb $(CFLAGS)
-LDFLAGS:=-ggdb $(LDFLAGS)
+CFLAGS:=-g3 $(CFLAGS)
+LDFLAGS:=-g3 $(LDFLAGS)
else
ifdef NOLTO
CFLAGS:=-O2 $(CFLAGS)
diff --git a/nuklear_ui/blastem_nuklear.c b/nuklear_ui/blastem_nuklear.c
index eba99d0..367893d 100644
--- a/nuklear_ui/blastem_nuklear.c
+++ b/nuklear_ui/blastem_nuklear.c
@@ -235,6 +235,7 @@ void binding_loop(char *key, tern_val val, uint8_t valtype, void *data)
*binding_lookup = tern_insert_ptr(*binding_lookup, val.ptrval, strdup(key));
}
+static int32_t keycode;
static const char *set_binding;
char *set_label;
void binding_group(struct nk_context *context, char *name, const char **binds, const char **bind_names, uint32_t num_binds, tern_node *binding_lookup)
@@ -254,6 +255,7 @@ void binding_group(struct nk_context *context, char *name, const char **binds, c
if (nk_button_label(context, tern_find_ptr_default(binding_lookup, binds[i], "Not Set"))) {
set_binding = binds[i];
set_label = strdup(label);
+ keycode = 0;
}
if (label_alloc) {
free(label_alloc);
@@ -263,6 +265,61 @@ void binding_group(struct nk_context *context, char *name, const char **binds, c
}
}
+static char *get_key_name(int32_t keycode)
+{
+ char *name = NULL;
+ if (keycode > ' ' && keycode < 0x80) {
+ //key corresponds to a printable non-whitespace character
+ name = malloc(2);
+ name[0] = keycode;
+ name[1] = 0;
+ } else {
+ switch (keycode)
+ {
+ case RENDERKEY_UP: name = "up"; break;
+ case RENDERKEY_DOWN: name = "down"; break;
+ case RENDERKEY_LEFT: name = "left"; break;
+ case RENDERKEY_RIGHT: name = "right"; break;
+ case '\r': name = "enter"; break;
+ case ' ': name = "space"; break;
+ case '\t': name = "tab"; break;
+ case '\b': name = "backspace"; break;
+ case RENDERKEY_ESC: name = "esc"; break;
+ case RENDERKEY_DEL: name = "delete"; break;
+ case RENDERKEY_LSHIFT: name = "lshift"; break;
+ case RENDERKEY_RSHIFT: name = "rshift"; break;
+ case RENDERKEY_LCTRL: name = "lctrl"; break;
+ case RENDERKEY_RCTRL: name = "rctrl"; break;
+ case RENDERKEY_LALT: name = "lalt"; break;
+ case RENDERKEY_RALT: name = "ralt"; break;
+ case RENDERKEY_HOME: name = "home"; break;
+ case RENDERKEY_END: name = "end"; break;
+ case RENDERKEY_PAGEUP: name = "pageup"; break;
+ case RENDERKEY_PAGEDOWN: name = "pagedown"; break;
+ case RENDERKEY_F1: name = "f1"; break;
+ case RENDERKEY_F2: name = "f2"; break;
+ case RENDERKEY_F3: name = "f3"; break;
+ case RENDERKEY_F4: name = "f4"; break;
+ case RENDERKEY_F5: name = "f5"; break;
+ case RENDERKEY_F6: name = "f6"; break;
+ case RENDERKEY_F7: name = "f7"; break;
+ case RENDERKEY_F8: name = "f8"; break;
+ case RENDERKEY_F9: name = "f9"; break;
+ case RENDERKEY_F10: name = "f10"; break;
+ case RENDERKEY_F11: name = "f11"; break;
+ case RENDERKEY_F12: name = "f12"; break;
+ case RENDERKEY_SELECT: name = "select"; break;
+ case RENDERKEY_PLAY: name = "play"; break;
+ case RENDERKEY_SEARCH: name = "search"; break;
+ case RENDERKEY_BACK: name = "back"; break;
+ }
+ if (name) {
+ name = strdup(name);
+ }
+ }
+ return name;
+}
+
void view_key_bindings(struct nk_context *context)
{
const char *controller1_binds[] = {
@@ -282,7 +339,7 @@ void view_key_bindings(struct nk_context *context)
"ui.screenshot", "ui.sms_pause", "ui.toggle_keyboard_cpatured", "ui.release_mouse"
};
const char *general_names[] = {
- "Show Menu", "Quick Save", "Toggle Fullscreen", "Soft Reset", "Reload Media"
+ "Show Menu", "Quick Save", "Toggle Fullscreen", "Soft Reset", "Reload Media",
"Internal Screenshot", "SMS Pause", "Capture Keyboard", "Release Mouse"
};
const char *speed_binds[] = {
@@ -331,6 +388,36 @@ void view_key_bindings(struct nk_context *context)
if (nk_button_label(context, "Cancel")) {
free(set_label);
set_binding = set_label = NULL;
+ } else if (keycode) {
+ char *name = get_key_name(keycode);
+ if (name) {
+ uint32_t prefix_len = strlen("bindings") + strlen("keys") + 2;
+ char * old = tern_find_ptr(binding_lookup, set_binding);
+ if (old) {
+ uint32_t suffix_len = strlen(old) + 1;
+ char *old_path = malloc(prefix_len + suffix_len + 1);
+ memcpy(old_path, "bindings\0keys\0", prefix_len);
+ memcpy(old_path + prefix_len, old, suffix_len);
+ old_path[prefix_len + suffix_len] = 0;
+ tern_val old_val;
+ if (tern_delete_path(&config, old_path, &old_val) == TVAL_PTR) {
+ free(old_val.ptrval);
+ }
+ }
+ uint32_t suffix_len = strlen(name) + 1;
+ char *path = malloc(prefix_len + suffix_len + 1);
+ memcpy(path, "bindings\0keys\0", prefix_len);
+ memcpy(path + prefix_len, name, suffix_len);
+ path[prefix_len + suffix_len] = 0;
+
+ config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(set_binding)}, TVAL_PTR);
+ free(path);
+ free(name);
+ tern_free(binding_lookup);
+ binding_lookup = NULL;
+ }
+ free(set_label);
+ set_binding = set_label = NULL;
}
nk_end(context);
}
@@ -753,6 +840,9 @@ void ui_idle_loop(void)
}
static void handle_event(SDL_Event *event)
{
+ if (event->type == SDL_KEYDOWN) {
+ keycode = event->key.keysym.sym;
+ }
nk_sdl_handle_event(event);
}
diff --git a/tern.c b/tern.c
index 7e8e9ac..b4c26d9 100644
--- a/tern.c
+++ b/tern.c
@@ -138,6 +138,39 @@ tern_node *tern_find_node(tern_node *head, char const *key)
return NULL;
}
+uint8_t tern_delete(tern_node **head, char const *key, tern_val *out)
+{
+ tern_node *cur = *head, **last = head;
+ while (cur)
+ {
+ if (cur->el == *key) {
+ if (*key) {
+ last = &cur->straight.next;
+ cur = cur->straight.next;
+ key++;
+ } else {
+ break;
+ }
+ } else if (*key < cur->el) {
+ last = &cur->left;
+ cur = cur->left;
+ } else {
+ last = &cur->right;
+ cur = cur->right;
+ }
+ }
+ if (!cur) {
+ return TVAL_NONE;
+ }
+ *last = cur->right;
+ uint8_t valtype = cur->valtype;
+ if (out) {
+ *out = cur->straight.value;
+ }
+ free(cur);
+ return valtype;
+}
+
tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype)
{
tern_val ret;
@@ -193,6 +226,25 @@ tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint
}
}
+uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out)
+{
+ const char *next_key = key + strlen(key) + 1;
+ if (*next_key) {
+ tern_node *child = tern_find_node(*head, key);
+ if (!child) {
+ return TVAL_NONE;
+ }
+ tern_node *tmp = child;
+ uint8_t valtype = tern_delete_path(&tmp, next_key, out);
+ if (tmp != child) {
+ *head = tern_insert_node(*head, key, tmp);
+ }
+ return valtype;
+ } else {
+ return tern_delete(head, key, out);
+ }
+}
+
uint32_t tern_count(tern_node *head)
{
uint32_t count = 0;
@@ -220,7 +272,7 @@ void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, i
if (head->left) {
tern_foreach_int(head->left, fun, data, keybuf, pos);
}
- if (head->el) {
+ if (head->el && head->straight.next) {
if (pos == MAX_ITER_KEY) {
fatal_error("tern_foreach_int: exceeded maximum key size");
}
diff --git a/tern.h b/tern.h
index 6b239e9..adae44c 100644
--- a/tern.h
+++ b/tern.h
@@ -43,8 +43,10 @@ tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value);
void * tern_find_ptr_default(tern_node * head, char const * key, void * def);
void * tern_find_ptr(tern_node * head, char const * key);
tern_node *tern_find_node(tern_node *head, char const *key);
+uint8_t tern_delete(tern_node **head, char const *key, tern_val *out);
tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype);
tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype);
+uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out);
tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value);
tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value);
tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint8_t valtype);