Fixed menus on Windows to avoid pointers moving underfoot.
This commit is contained in:
parent
60a5931207
commit
83f936a637
|
@ -1,8 +1,7 @@
|
||||||
// 24 april 2015
|
// 24 april 2015
|
||||||
#include "uipriv_windows.h"
|
#include "uipriv_windows.h"
|
||||||
|
|
||||||
// TODO turn this into struct menu **
|
static struct menu **menus = NULL;
|
||||||
static struct menu *menus = NULL;
|
|
||||||
static uintmax_t len = 0;
|
static uintmax_t len = 0;
|
||||||
static uintmax_t cap = 0;
|
static uintmax_t cap = 0;
|
||||||
static BOOL menusFinalized = FALSE;
|
static BOOL menusFinalized = FALSE;
|
||||||
|
@ -14,8 +13,7 @@ static BOOL hasAbout = FALSE;
|
||||||
struct menu {
|
struct menu {
|
||||||
uiMenu m;
|
uiMenu m;
|
||||||
WCHAR *name;
|
WCHAR *name;
|
||||||
// TODO turn into struct menuItem **
|
struct menuItem **items;
|
||||||
struct menuItem *items;
|
|
||||||
uintmax_t len;
|
uintmax_t len;
|
||||||
uintmax_t cap;
|
uintmax_t cap;
|
||||||
};
|
};
|
||||||
|
@ -120,9 +118,11 @@ static uiMenuItem *newItem(struct menu *m, int type, const char *name)
|
||||||
|
|
||||||
if (m->len >= m->cap) {
|
if (m->len >= m->cap) {
|
||||||
m->cap += grow;
|
m->cap += grow;
|
||||||
m->items = (struct menuItem *) uiRealloc(m->items, m->cap * sizeof (struct menuItem), "struct menuItem[]");
|
m->items = (struct menuItem **) uiRealloc(m->items, m->cap * sizeof (struct menuItem *), "struct menuItem *[]");
|
||||||
}
|
}
|
||||||
item = &(m->items[m->len]);
|
|
||||||
|
item = uiNew(struct menuItem);
|
||||||
|
m->items[m->len] = item;
|
||||||
m->len++;
|
m->len++;
|
||||||
|
|
||||||
item->type = type;
|
item->type = type;
|
||||||
|
@ -137,8 +137,6 @@ static uiMenuItem *newItem(struct menu *m, int type, const char *name)
|
||||||
item->name = toUTF16("About");
|
item->name = toUTF16("About");
|
||||||
break;
|
break;
|
||||||
case typeSeparator:
|
case typeSeparator:
|
||||||
// TODO this shouldn't be necessary, but uiRealloc() doesn't yet zero out new bytes
|
|
||||||
item->name = NULL;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
item->name = toUTF16(name);
|
item->name = toUTF16(name);
|
||||||
|
@ -149,19 +147,9 @@ static uiMenuItem *newItem(struct menu *m, int type, const char *name)
|
||||||
item->id = curID;
|
item->id = curID;
|
||||||
curID++;
|
curID++;
|
||||||
}
|
}
|
||||||
// TODO this shouldn't be necessary, but uiRealloc() doesn't yet zero out new bytes
|
|
||||||
else
|
|
||||||
item->id = 0;
|
|
||||||
|
|
||||||
item->onClicked = defaultOnClicked;
|
item->onClicked = defaultOnClicked;
|
||||||
|
|
||||||
// TODO this shouldn't be necessary, but uiRealloc() doesn't yet zero out new bytes
|
|
||||||
item->disabled = FALSE;
|
|
||||||
item->checked = FALSE;
|
|
||||||
item->hmenus = NULL;
|
|
||||||
item->len = 0;
|
|
||||||
item->cap = 0;
|
|
||||||
|
|
||||||
uiMenuItem(item)->Enable = menuItemEnable;
|
uiMenuItem(item)->Enable = menuItemEnable;
|
||||||
uiMenuItem(item)->Disable = menuItemDisable;
|
uiMenuItem(item)->Disable = menuItemDisable;
|
||||||
uiMenuItem(item)->OnClicked = menuItemOnClicked;
|
uiMenuItem(item)->OnClicked = menuItemOnClicked;
|
||||||
|
@ -221,18 +209,15 @@ uiMenu *uiNewMenu(const char *name)
|
||||||
complain("attempt to create a new menu after menus have been finalized");
|
complain("attempt to create a new menu after menus have been finalized");
|
||||||
if (len >= cap) {
|
if (len >= cap) {
|
||||||
cap += grow;
|
cap += grow;
|
||||||
menus = (struct menu *) uiRealloc(menus, cap * sizeof (struct menu), "struct menu[]");
|
menus = (struct menu **) uiRealloc(menus, cap * sizeof (struct menu *), "struct menu *[]");
|
||||||
}
|
}
|
||||||
m = &menus[len];
|
|
||||||
|
m = uiNew(struct menu);
|
||||||
|
menus[len] = m;
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
m->name = toUTF16(name);
|
m->name = toUTF16(name);
|
||||||
|
|
||||||
// TODO this shouldn't be necessary, but uiRealloc() doesn't yet zero out new bytes
|
|
||||||
m->items = NULL;
|
|
||||||
m->len = 0;
|
|
||||||
m->cap = 0;
|
|
||||||
|
|
||||||
uiMenu(m)->AppendItem = menuAppendItem;
|
uiMenu(m)->AppendItem = menuAppendItem;
|
||||||
uiMenu(m)->AppendCheckItem = menuAppendCheckItem;
|
uiMenu(m)->AppendCheckItem = menuAppendCheckItem;
|
||||||
uiMenu(m)->AppendQuitItem = menuAppendQuitItem;
|
uiMenu(m)->AppendQuitItem = menuAppendQuitItem;
|
||||||
|
@ -275,7 +260,7 @@ static HMENU makeMenu(struct menu *m)
|
||||||
if (menu == NULL)
|
if (menu == NULL)
|
||||||
logLastError("error creating menu in makeMenu()");
|
logLastError("error creating menu in makeMenu()");
|
||||||
for (i = 0; i < m->len; i++)
|
for (i = 0; i < m->len; i++)
|
||||||
appendMenuItem(menu, &(m->items[i]));
|
appendMenuItem(menu, m->items[i]);
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,8 +278,8 @@ HMENU makeMenubar(void)
|
||||||
logLastError("error creating menubar in makeMenubar()");
|
logLastError("error creating menubar in makeMenubar()");
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
menu = makeMenu(&menus[i]);
|
menu = makeMenu(menus[i]);
|
||||||
if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i].name) == 0)
|
if (AppendMenuW(menubar, MF_POPUP | MF_STRING, (UINT_PTR) menu, menus[i]->name) == 0)
|
||||||
logLastError("error appending menu to menubar in makeMenubar()");
|
logLastError("error appending menu to menubar in makeMenubar()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,9 +295,9 @@ void runMenuEvent(WORD id, uiWindow *w)
|
||||||
|
|
||||||
// TODO optimize this somehow?
|
// TODO optimize this somehow?
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
m = &menus[i];
|
m = menus[i];
|
||||||
for (j = 0; j < m->len; j++) {
|
for (j = 0; j < m->len; j++) {
|
||||||
item = &(m->items[j]);
|
item = m->items[j];
|
||||||
if (item->id == id)
|
if (item->id == id)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
@ -339,7 +324,7 @@ static void freeMenu(struct menu *m, HMENU submenu)
|
||||||
uintmax_t j;
|
uintmax_t j;
|
||||||
|
|
||||||
for (i = 0; i < m->len; i++) {
|
for (i = 0; i < m->len; i++) {
|
||||||
item = &m->items[i];
|
item = m->items[i];
|
||||||
for (j = 0; j < item->len; j++)
|
for (j = 0; j < item->len; j++)
|
||||||
if (item->hmenus[j] == submenu)
|
if (item->hmenus[j] == submenu)
|
||||||
break;
|
break;
|
||||||
|
@ -363,7 +348,7 @@ void freeMenubar(HMENU menubar)
|
||||||
mi.fMask = MIIM_SUBMENU;
|
mi.fMask = MIIM_SUBMENU;
|
||||||
if (GetMenuItemInfoW(menubar, i, TRUE, &mi) == 0)
|
if (GetMenuItemInfoW(menubar, i, TRUE, &mi) == 0)
|
||||||
logLastError("error getting menu to delete item references from in freeMenubar()");
|
logLastError("error getting menu to delete item references from in freeMenubar()");
|
||||||
freeMenu(&menus[i], mi.hSubMenu);
|
freeMenu(menus[i], mi.hSubMenu);
|
||||||
}
|
}
|
||||||
// no need to worry about destroying any menus; destruction of the window they're in will do it for us
|
// no need to worry about destroying any menus; destruction of the window they're in will do it for us
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue