From 615e53ecabc66c8a5f9a74ed74415d4600bfabc5 Mon Sep 17 00:00:00 2001 From: cancel Date: Mon, 6 Jan 2020 01:11:39 +0900 Subject: [PATCH] Clean up more user id handling logic in Qmenu items --- term_util.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/term_util.c b/term_util.c index 4c1cdb7..d16b78b 100644 --- a/term_util.c +++ b/term_util.c @@ -69,6 +69,7 @@ struct Qmsg { }; struct Qmenu_item_extra { + int user_id; U8 owns_string : 1; U8 is_spacer : 1; }; @@ -93,11 +94,6 @@ struct Qform { 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 @@ Qmenu* qmenu_create(int id) { 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 @@ qmenu_allocitems(Qmenu* qm, Usz count, ITEM*** out_items, // 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 @@ qmenu_item_extras_ptr(Qmenu* qm) { 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 @@ void qmenu_free(Qmenu* qm) { } 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 @@ bool qmenu_drive(Qmenu* qm, int key, Qmenu_action* out_action) { 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 @@ bool qmenu_drive(Qmenu* qm, int key, Qmenu_action* out_action) { 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 @@ bool qmenu_drive(Qmenu* qm, int key, Qmenu_action* out_action) { 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); }