Sun, 10 Nov 2024 15:27:44 +0100
implement some missing WinUI functions
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2023 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "menu.h" #include <stdarg.h> #include <string.h> #include <cx/linked_list.h> #include <cx/array_list.h> static UiMenu *menus_begin; static UiMenu *menus_end; static CxList *current; static int menu_item_counter = 0; static void add_menu(UiMenu *menu) { cx_linked_list_add( (void**)&menus_begin, (void**)&menus_end, offsetof(UiMenu, item.prev), offsetof(UiMenu, item.next), menu); } static void add_item(UiMenuItemI *item) { UiMenu *menu = cxListAt(current, 0); cx_linked_list_add( (void**)&menu->items_begin, (void**)&menu->items_end, offsetof(UiMenu, item.prev), offsetof(UiMenu, item.next), item); } static void mitem_set_id(UiMenuItemI *item) { snprintf(item->id, 8, "%x", menu_item_counter++); } static char* nl_strdup(const char* s) { return s ? strdup(s) : NULL; } int* uic_copy_groups(const int* groups, size_t *ngroups) { *ngroups = 0; if (!groups) { return NULL; } size_t n; for (n = 0; groups[n] > -1; n++) { } if (ngroups > 0) { int* newarray = calloc(n, sizeof(int)); memcpy(newarray, groups, n * sizeof(int)); *ngroups = n; return newarray; } return NULL; } void ui_menu_create(const char *label) { if(!current) { current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); } // create menu UiMenu *menu = malloc(sizeof(UiMenu)); mitem_set_id(&menu->item); menu->item.prev = NULL; menu->item.next = NULL; menu->item.type = UI_MENU; menu->label = label; menu->items_begin = NULL; menu->items_end = NULL; menu->parent = NULL; menu->end = 0; if (cxListSize(current) == 0) { add_menu(menu); } else { add_item((UiMenuItemI*)menu); } uic_add_menu_to_stack(menu); } UIEXPORT void ui_menu_end(void) { cxListRemove(current, 0); } void ui_menuitem_create(UiMenuItemArgs args) { if (!current) { return; // error? } UiMenuItem* item = malloc(sizeof(UiMenuItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM; item->label = nl_strdup(args.label); item->stockid = nl_strdup(args.stockid); item->icon = nl_strdup(args.icon); item->userdata = args.onclickdata; item->callback = args.onclick; item->groups = uic_copy_groups(args.groups, &item->ngroups); add_item((UiMenuItemI*)item); } void ui_menuseparator() { if(!current) { return; } UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); item->id[0] = 0; item->prev = NULL; item->next = NULL; item->type = UI_MENU_SEPARATOR; add_item((UiMenuItemI*)item); } void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { if(!current) { return; } UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECK_ITEM; item->label = nl_strdup(args.label); item->stockid = nl_strdup(args.stockid); item->icon = nl_strdup(args.icon); item->varname = nl_strdup(args.varname); item->userdata = args.onchangedata; item->callback = args.onchange; item->groups = uic_copy_groups(args.groups, &item->ngroups); add_item((UiMenuItemI*)item); } void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { if (!current) { return; } UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECK_ITEM; item->label = nl_strdup(args.label); item->stockid = nl_strdup(args.stockid); item->icon = nl_strdup(args.icon); item->varname = nl_strdup(args.varname); item->userdata = args.onchangedata; item->callback = args.onchange; item->groups = uic_copy_groups(args.groups, &item->ngroups); add_item((UiMenuItemI*)item); } void ui_menu_itemlist_create(UiMenuItemListArgs args) { if(!current) { return; } UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM_LIST; item->getvalue = args.getvalue; item->callback = args.onselect; item->userdata = args.onselectdata; item->varname = nl_strdup(args.varname); add_item((UiMenuItemI*)item); } void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { if (!current) { return; } UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECKITEM_LIST; item->callback = args.onselect; item->userdata = args.onselectdata; item->varname = nl_strdup(args.varname); add_item((UiMenuItemI*)item); } void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { if (!current) { return; } UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_RADIOITEM_LIST; item->callback = args.onselect; item->userdata = args.onselectdata; item->varname = nl_strdup(args.varname); add_item((UiMenuItemI*)item); } void uic_add_menu_to_stack(UiMenu* menu) { if (!current) { current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); } cxListInsert(current, 0, menu); } UiMenu* uic_get_menu_list(void) { return menus_begin; } UIEXPORT void ui_menu_close(void) { UiMenu* menu = cxListAt(current, 0); menu->end = 1; } UIEXPORT int ui_menu_is_open(void) { UiMenu* menu = cxListAt(current, 0); if (menu->end) { ui_menu_end(); return 0; } return 1; }