ref: 615e53ecabc66c8a5f9a74ed74415d4600bfabc5
parent: 44e888f7dad3d813e6bea2b50ed1f1d46eee6796
author: cancel <cancel@cancel.fm>
date: Sun Jan 5 20:11:39 EST 2020
Clean up more user id handling logic in Qmenu items
--- a/term_util.c
+++ b/term_util.c
@@ -69,6 +69,7 @@
};
struct Qmenu_item_extra {
+ int user_id;
U8 owns_string : 1;
U8 is_spacer : 1;
};
@@ -93,11 +94,6 @@
Qnav_stack qnav_stack;
-enum {
- Qmenu_spacer_unique_id = INT_MIN + 1,
- Qmenu_first_valid_user_choice_id,
-};
-
void qnav_init() {
qnav_stack.count = 0;
qnav_stack.stack_changed = false;
@@ -317,7 +313,7 @@
void qmenu_destroy(Qmenu* qm) { qmenu_free(qm); }
int qmenu_id(Qmenu const* qm) { return qm->id; }
static ORCA_FORCE_NO_INLINE void
-qmenu_allocitems(Qmenu* qm, Usz count, ITEM*** out_items,
+qmenu_allocitems(Qmenu* qm, Usz count, Usz* out_idx, ITEM*** out_items,
struct Qmenu_item_extra** out_extras) {
Usz old_count = qm->items_count;
// Add 1 for the extra null terminator guy
@@ -347,6 +343,7 @@
// terminator as required by ncurses.
qm->items_count = old_count + count;
Usz extras_offset = sizeof(ITEM*) * items_cap;
+ *out_idx = old_count;
*out_items = items + old_count;
*out_extras =
(struct Qmenu_item_extra*)((char*)items + extras_offset) + old_count;
@@ -356,36 +353,50 @@
Usz offset = sizeof(ITEM*) * qm->items_cap;
return (struct Qmenu_item_extra*)((char*)qm->ncurses_items + offset);
}
+// Get the curses menu item user pointer out, turn it to an int, and use it as
+// an index into the 'extras' arrays.
+ORCA_FORCE_STATIC_INLINE
+struct Qmenu_item_extra* qmenu_itemextra(struct Qmenu_item_extra* extras,
+ ITEM* item) {
+ return extras + (int)(intptr_t)(item_userptr(item));
+}
void qmenu_set_title(Qmenu* qm, char const* title) {
qblock_set_title(&qm->qblock, title);
}
void qmenu_add_choice(Qmenu* qm, int id, char const* text) {
- assert(id >= Qmenu_first_valid_user_choice_id);
+ assert(id != 0);
+ Usz idx;
ITEM** items;
struct Qmenu_item_extra* extras;
- qmenu_allocitems(qm, 1, &items, &extras);
+ qmenu_allocitems(qm, 1, &idx, &items, &extras);
items[0] = new_item(text, NULL);
- set_item_userptr(items[0], (void*)(intptr_t)(id));
+ set_item_userptr(items[0], (void*)(uintptr_t)idx);
+ extras[0].user_id = id;
extras[0].owns_string = false;
extras[0].is_spacer = false;
}
void qmenu_add_spacer(Qmenu* qm) {
+ Usz idx;
ITEM** items;
struct Qmenu_item_extra* extras;
- qmenu_allocitems(qm, 1, &items, &extras);
+ qmenu_allocitems(qm, 1, &idx, &items, &extras);
items[0] = new_item(" ", NULL);
item_opts_off(items[0], O_SELECTABLE);
- set_item_userptr(items[0], (void*)(intptr_t)Qmenu_spacer_unique_id);
+ set_item_userptr(items[0], (void*)(uintptr_t)idx);
+ extras[0].user_id = 0;
extras[0].owns_string = false;
extras[0].is_spacer = true;
}
void qmenu_set_current_item(Qmenu* qm, int id) {
+ ITEM** items = qm->ncurses_items;
+ struct Qmenu_item_extra* extras = qmenu_item_extras_ptr(qm);
ITEM* found = NULL;
for (Usz i = 0, n = qm->items_count; i < n; i++) {
- if (item_userptr(qm->ncurses_items[i]) != (void*)(intptr_t)id)
- continue;
- found = qm->ncurses_items[i];
- break;
+ ITEM* item = items[i];
+ if (qmenu_itemextra(extras, item)->user_id == id) {
+ found = item;
+ break;
+ }
}
if (!found)
return;
@@ -446,6 +457,7 @@
}
bool qmenu_drive(Qmenu* qm, int key, Qmenu_action* out_action) {
+ struct Qmenu_item_extra* extras = qmenu_item_extras_ptr(qm);
switch (key) {
case 27: {
out_action->any.type = Qmenu_action_type_canceled;
@@ -456,7 +468,7 @@
case KEY_ENTER: {
ITEM* cur = current_item(qm->ncurses_menu);
out_action->picked.type = Qmenu_action_type_picked;
- out_action->picked.id = cur ? (int)(intptr_t)item_userptr(cur) : 0;
+ out_action->picked.id = cur ? qmenu_itemextra(extras, cur)->user_id : 0;
return true;
} break;
case KEY_UP: {
@@ -466,7 +478,7 @@
ITEM* cur = current_item(qm->ncurses_menu);
if (!cur || cur == starting)
break;
- if (item_userptr(cur) != (void*)(intptr_t)Qmenu_spacer_unique_id)
+ if (!qmenu_itemextra(extras, cur)->is_spacer)
break;
menu_driver(qm->ncurses_menu, REQ_UP_ITEM);
}
@@ -479,7 +491,7 @@
ITEM* cur = current_item(qm->ncurses_menu);
if (!cur || cur == starting)
break;
- if (item_userptr(cur) != (void*)(intptr_t)Qmenu_spacer_unique_id)
+ if (!qmenu_itemextra(extras, cur)->is_spacer)
break;
menu_driver(qm->ncurses_menu, REQ_DOWN_ITEM);
}