1 /***********************************************************
2 * Copyright (C) 1997, Be Inc. Copyright (C) 1999, Jake Hamby.
4 * This program is freely distributable without licensing fees
5 * and is provided without guarantee or warrantee expressed or
6 * implied. This program is -not- in the public domain.
10 * DESCRIPTION: code for popup menu handling
11 ***********************************************************/
13 /***********************************************************
15 ***********************************************************/
20 #include "glutState.h"
22 /***********************************************************
24 ***********************************************************/
25 static GlutMenu **menuList = 0;
26 static int menuListSize = 0;
28 /***********************************************************
29 * FUNCTION: getUnusedMenuSlot
31 * DESCRIPTION: helper function to get a new menu slot
32 ***********************************************************/
33 GlutMenu *__glutGetMenuByNum(int menunum)
35 if (menunum < 1 || menunum > menuListSize) {
38 return menuList[menunum - 1];
41 /***********************************************************
42 * FUNCTION: getUnusedMenuSlot
44 * DESCRIPTION: helper function to get a new menu slot
45 ***********************************************************/
47 getUnusedMenuSlot(void)
51 /* Look for allocated, unused slot. */
52 for (i = 0; i < menuListSize; i++) {
57 /* Allocate a new slot. */
59 menuList = (GlutMenu **)
60 realloc(menuList, menuListSize * sizeof(GlutMenu *));
62 __glutFatalError("out of memory.");
63 menuList[menuListSize - 1] = NULL;
64 return menuListSize - 1;
67 /***********************************************************
68 * FUNCTION: glutCreateMenu (6.1)
70 * DESCRIPTION: create a new menu
71 ***********************************************************/
73 glutCreateMenu(GLUTselectCB selectFunc)
78 menuid = getUnusedMenuSlot();
79 menu = new GlutMenu(menuid, selectFunc); // constructor sets up members
80 menuList[menuid] = menu;
81 gState.currentMenu = menu;
85 /***********************************************************
86 * FUNCTION: glutSetMenu (6.2)
89 * DESCRIPTION: set and get the current menu
90 ***********************************************************/
94 if (gState.currentMenu) {
95 return gState.currentMenu->id + 1;
102 glutSetMenu(int menuid)
106 if (menuid < 1 || menuid > menuListSize) {
107 __glutWarning("glutSetMenu attempted on bogus menu.");
110 menu = menuList[menuid - 1];
112 __glutWarning("glutSetMenu attempted on bogus menu.");
115 gState.currentMenu = menu;
118 /***********************************************************
119 * FUNCTION: glutDestroyMenu (6.3)
121 * DESCRIPTION: destroy the specified menu
122 ***********************************************************/
124 glutDestroyMenu(int menunum)
126 GlutMenu *menu = __glutGetMenuByNum(menunum);
127 menuList[menunum - 1] = 0;
128 if (gState.currentMenu == menu) {
129 gState.currentMenu = 0;
134 /***********************************************************
135 * FUNCTION: glutAddMenuEntry (6.4)
137 * DESCRIPTION: add a new menu item
138 ***********************************************************/
140 glutAddMenuEntry(const char *label, int value)
142 new GlutMenuItem(gState.currentMenu, false, value, label);
145 /***********************************************************
146 * FUNCTION: glutAddSubMenu (6.5)
148 * DESCRIPTION: add a new submenu
149 ***********************************************************/
151 glutAddSubMenu(const char *label, int menu)
153 new GlutMenuItem(gState.currentMenu, true, menu-1, label);
156 /***********************************************************
157 * FUNCTION: glutChangeToMenuEntry (6.6)
159 * DESCRIPTION: change menuitem into a menu entry
160 ***********************************************************/
162 glutChangeToMenuEntry(int num, const char *label, int value)
167 i = gState.currentMenu->num;
168 item = gState.currentMenu->list;
172 item->label = strdup(label);
173 item->isTrigger = false;
180 __glutWarning("Current menu has no %d item.", num);
183 /***********************************************************
184 * FUNCTION: glutChangeToSubMenu (6.7)
186 * DESCRIPTION: change menuitem into a submenu
187 ***********************************************************/
189 glutChangeToSubMenu(int num, const char *label, int menu)
194 i = gState.currentMenu->num;
195 item = gState.currentMenu->list;
199 item->label = strdup(label);
200 item->isTrigger = true;
201 item->value = menu-1;
207 __glutWarning("Current menu has no %d item.", num);
210 /***********************************************************
211 * FUNCTION: glutRemoveMenuItem (6.8)
213 * DESCRIPTION: remove a menu item
214 ***********************************************************/
216 glutRemoveMenuItem(int num)
218 GlutMenuItem *item, **prev;
221 i = gState.currentMenu->num;
222 prev = &gState.currentMenu->list;
223 item = gState.currentMenu->list;
227 gState.currentMenu->num--;
229 /* Patch up menu's item list. */
240 __glutWarning("Current menu has no %d item.", num);
243 /***********************************************************
244 * FUNCTION: glutAttachMenu (6.9)
247 * DESCRIPTION: attach and detach menu from view
248 ***********************************************************/
250 glutAttachMenu(int button)
252 gState.currentWindow->menu[button] = gState.currentMenu->id + 1;
256 glutDetachMenu(int button)
258 gState.currentWindow->menu[button] = 0;
261 /***********************************************************
264 * FUNCTION: CreateBMenu
266 * DESCRIPTION: construct a BPopupMenu for this menu
267 ***********************************************************/
268 BMenu *GlutMenu::CreateBMenu(bool toplevel) {
271 bpopup = new GlutPopUp(id+1);
273 bpopup = new BMenu("");
275 GlutMenuItem *item = list;
277 GlutBMenuItem *bitem;
278 if(item->isTrigger) {
279 // recursively call CreateBMenu
280 bitem = new GlutBMenuItem(menuList[item->value]->CreateBMenu(false));
281 bitem->SetLabel(item->label);
282 bitem->menu = 0; // real menu items start at 1
285 bitem = new GlutBMenuItem(item->label);
286 bitem->menu = id + 1;
287 bitem->value = item->value;
289 bpopup->AddItem(bitem, 0);
295 /***********************************************************
298 * FUNCTION: (destructor)
300 * DESCRIPTION: destroy the menu and its items (but not submenus!)
301 ***********************************************************/
302 GlutMenu::~GlutMenu() {
304 GlutMenuItem *next = list->next;
310 /***********************************************************
311 * CLASS: GlutMenuItem
313 * FUNCTION: (constructor)
315 * DESCRIPTION: construct the new menu item and add to parent
316 ***********************************************************/
317 GlutMenuItem::GlutMenuItem(GlutMenu *n_menu, bool n_trig, int n_value, const char *n_label)
322 label = strdup(n_label);