2
/* Copyright (c) Mark J. Kilgard, 1994, 1997, 1998. */
3
/* Copyright (c) Nate Robins, 1997. */
5
/* This program is freely distributable without licensing fees
6
and is provided without guarantee or warrantee expressed or
7
implied. This program is -not- in the public domain. */
9
/* This file completely re-implements glut_menu.c and glut_menu2.c
10
for Win32. Note that neither glut_menu.c nor glut_menu2.c are
11
compiled into Win32 GLUT. */
21
void (GLUTCALLBACK *__glutMenuStatusFunc) (int, int, int);
22
//GLUTmenu *__glutMappedMenu;
23
//GLUTwindow *__glutMenuWindow;
24
GLUTmenuItem *__glutItemSelected;
25
unsigned __glutMenuButton;
27
static GLUTmenu **menuList = NULL;
28
static int menuListSize = 0;
29
static UINT uniqueMenuHandler = 1;
31
/* DEPRICATED, use glutMenuStatusFunc instead. */
33
glutMenuStateFunc(GLUTmenuStateCB menuStateFunc)
35
__glutMenuStatusFunc = (GLUTmenuStatusCB) menuStateFunc;
39
glutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc)
41
__glutMenuStatusFunc = menuStatusFunc;
45
__glutSetMenu(GLUTmenu * menu)
47
__glutCurrentMenu = menu;
51
unmapMenu(GLUTmenu * menu)
54
unmapMenu(menu->cascade);
58
menu->highlighted = NULL;
62
__glutFinishMenu(Window win, int x, int y)
65
unmapMenu(__glutMappedMenu);
67
/* XXX Put in a GdiFlush just in case. Probably unnecessary. -mjk */
70
if (__glutMenuStatusFunc) {
71
__glutSetWindow(__glutMenuWindow);
72
__glutSetMenu(__glutMappedMenu);
74
/* Setting __glutMappedMenu to NULL permits operations that
75
change menus or destroy the menu window again. */
76
__glutMappedMenu = NULL;
78
__glutMenuStatusFunc(GLUT_MENU_NOT_IN_USE, x, y);
80
/* Setting __glutMappedMenu to NULL permits operations that
81
change menus or destroy the menu window again. */
82
__glutMappedMenu = NULL;
84
/* If an item is selected and it is not a submenu trigger,
85
generate menu callback. */
86
if (__glutItemSelected && !__glutItemSelected->isTrigger) {
87
__glutSetWindow(__glutMenuWindow);
88
/* When menu callback is triggered, current menu should be
89
set to the callback menu. */
90
__glutSetMenu(__glutItemSelected->menu);
91
__glutItemSelected->menu->select(__glutItemSelected->value);
93
__glutMenuWindow = NULL;
97
mapMenu(GLUTmenu * menu, int x, int y)
100
// TrackPopupMenu((HMENU) menu->win, TPM_LEFTALIGN |
101
// (__glutMenuButton == TPM_RIGHTBUTTON) ? TPM_RIGHTBUTTON : TPM_LEFTBUTTON,
102
// x, y, 0, __glutCurrentWindow->win, NULL);
106
__glutStartMenu(GLUTmenu * menu, GLUTwindow * window,
107
int x, int y, int x_win, int y_win)
109
assert(__glutMappedMenu == NULL);
110
__glutMappedMenu = menu;
111
__glutMenuWindow = window;
112
__glutItemSelected = NULL;
113
if (__glutMenuStatusFunc) {
115
__glutSetWindow(window);
116
__glutMenuStatusFunc(GLUT_MENU_IN_USE, x_win, y_win);
122
__glutGetUniqueMenuItem(GLUTmenu * menu, UINT unique)
130
if (item->unique == unique) {
133
if (item->isTrigger) {
134
GLUTmenuItem *subitem;
135
subitem = __glutGetUniqueMenuItem(menuList[item->value], unique);
147
__glutGetMenuItem(GLUTmenu * menu, Window win, int *which)
155
if (item->win == win) {
159
if (item->isTrigger) {
160
GLUTmenuItem *subitem;
162
subitem = __glutGetMenuItem(menuList[item->value],
175
__glutGetMenu(Window win)
179
menu = __glutMappedMenu;
181
if (win == menu->win) {
184
menu = menu->cascade;
190
__glutGetMenuByNum(int menunum)
192
if (menunum < 1 || menunum > menuListSize) {
195
return menuList[menunum - 1];
199
getUnusedMenuSlot(void)
203
/* Look for allocated, unused slot. */
204
for (i = 0; i < menuListSize; i++) {
209
/* Allocate a new slot. */
212
menuList = (GLUTmenu **)
213
realloc(menuList, menuListSize * sizeof(GLUTmenu *));
215
/* XXX Some realloc's do not correctly perform a malloc
216
when asked to perform a realloc on a NULL pointer,
217
though the ANSI C library spec requires this. */
218
menuList = (GLUTmenu **) malloc(sizeof(GLUTmenu *));
221
__glutFatalError("out of memory.");
223
menuList[menuListSize - 1] = NULL;
224
return menuListSize - 1;
228
menuModificationError(void)
230
/* XXX Remove the warning after GLUT 3.0. */
231
__glutWarning("The following is a new check for GLUT 3.0; update your code.");
232
__glutFatalError("menu manipulation not allowed while menus in use.");
236
glutCreateMenu(GLUTselectCB selectFunc)
241
if (__glutMappedMenu) {
242
menuModificationError();
244
menuid = getUnusedMenuSlot();
245
menu = (GLUTmenu *) malloc(sizeof(GLUTmenu));
247
__glutFatalError("out of memory.");
252
menu->select = selectFunc;
254
menu->cascade = NULL;
255
menu->highlighted = NULL;
258
// menu->win = (HWND) CreatePopupMenu();
259
menuList[menuid] = menu;
266
glutDestroyMenu(int menunum)
268
GLUTmenu *menu = __glutGetMenuByNum(menunum);
269
GLUTmenuItem *item, *next;
271
if (__glutMappedMenu) {
272
menuModificationError();
274
assert(menu->id == menunum - 1);
275
//todo DestroyMenu( (HMENU) menu->win);
276
menuList[menunum - 1] = NULL;
277
/* free all menu entries */
280
assert(item->menu == menu);
286
if (__glutCurrentMenu == menu) {
287
__glutCurrentMenu = NULL;
295
if (__glutCurrentMenu) {
296
return __glutCurrentMenu->id + 1;
303
glutSetMenu(int menuid)
307
if (menuid < 1 || menuid > menuListSize) {
308
__glutWarning("glutSetMenu attempted on bogus menu.");
311
menu = menuList[menuid - 1];
313
__glutWarning("glutSetMenu attempted on bogus menu.");
320
setMenuItem(GLUTmenuItem * item, const char *label,
321
int value, Bool isTrigger)
326
item->label = __glutStrdup(label);
328
__glutFatalError("out of memory.");
330
item->isTrigger = isTrigger;
331
item->len = (int) strlen(label);
333
item->unique = uniqueMenuHandler++;
336
// AppendMenu((HMENU) menu->win, MF_POPUP, (UINT)item->win, label);
338
// AppendMenu((HMENU) menu->win, MF_STRING, item->unique, label);
343
glutAddMenuEntry(const char *label, int value)
347
if (__glutMappedMenu) {
348
menuModificationError();
350
entry = (GLUTmenuItem *) malloc(sizeof(GLUTmenuItem));
352
__glutFatalError("out of memory.");
354
entry->menu = __glutCurrentMenu;
355
setMenuItem(entry, label, value, FALSE);
356
__glutCurrentMenu->num++;
357
entry->next = __glutCurrentMenu->list;
358
__glutCurrentMenu->list = entry;
362
glutAddSubMenu(const char *label, int menu)
364
GLUTmenuItem *submenu;
367
if (__glutMappedMenu) {
368
menuModificationError();
370
submenu = (GLUTmenuItem *) malloc(sizeof(GLUTmenuItem));
372
__glutFatalError("out of memory.");
374
__glutCurrentMenu->submenus++;
375
submenu->menu = __glutCurrentMenu;
376
popupmenu = __glutGetMenuByNum(menu);
378
submenu->win = popupmenu->win;
380
setMenuItem(submenu, label, /* base 0 */ menu - 1, TRUE);
381
__glutCurrentMenu->num++;
382
submenu->next = __glutCurrentMenu->list;
383
__glutCurrentMenu->list = submenu;
387
glutChangeToMenuEntry(int num, const char *label, int value)
392
if (__glutMappedMenu) {
393
menuModificationError();
395
i = __glutCurrentMenu->num;
396
item = __glutCurrentMenu->list;
399
if (item->isTrigger) {
400
/* If changing a submenu trigger to a menu entry, we
401
need to account for submenus. */
402
item->menu->submenus--;
403
/* Nuke the Win32 menu. */
405
// DestroyMenu((HMENU) item->win);
409
item->label = strdup(label);
411
__glutFatalError("out of memory");
412
item->isTrigger = FALSE;
413
item->len = (int) strlen(label);
415
item->unique = uniqueMenuHandler++;
417
// ModifyMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1,
418
// MF_BYPOSITION | MFT_STRING, item->unique, label);
425
__glutWarning("Current menu has no %d item.", num);
429
glutChangeToSubMenu(int num, const char *label, int menu)
435
if (__glutMappedMenu) {
436
menuModificationError();
438
i = __glutCurrentMenu->num;
439
item = __glutCurrentMenu->list;
442
if (!item->isTrigger) {
443
/* If changing a menu entry to as submenu trigger, we
444
need to account for submenus. */
445
item->menu->submenus++;
447
// item->win = (HWND) CreatePopupMenu();
451
item->label = strdup(label);
453
__glutFatalError("out of memory");
454
item->isTrigger = TRUE;
455
item->len = (int) strlen(label);
456
item->value = menu - 1;
457
item->unique = uniqueMenuHandler++;
458
popupmenu = __glutGetMenuByNum(menu);
460
item->win = popupmenu->win;
462
// ModifyMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1,
463
// MF_BYPOSITION | MF_POPUP, (UINT) item->win, label);
469
__glutWarning("Current menu has no %d item.", num);
473
glutRemoveMenuItem(int num)
475
GLUTmenuItem *item, **prev;
478
if (__glutMappedMenu) {
479
menuModificationError();
481
i = __glutCurrentMenu->num;
482
prev = &__glutCurrentMenu->list;
483
item = __glutCurrentMenu->list;
486
/* Found the menu item in list to remove. */
487
__glutCurrentMenu->num--;
489
/* Patch up menu's item list. */
492
// RemoveMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1, MF_BYPOSITION);
502
__glutWarning("Current menu has no %d item.", num);
506
glutAttachMenu(int button)
508
if (__glutCurrentWindow == __glutGameModeWindow) {
509
__glutWarning("cannot attach menus in game mode.");
512
if (__glutMappedMenu) {
513
menuModificationError();
515
if (__glutCurrentWindow->menu[button] < 1) {
516
__glutCurrentWindow->buttonUses++;
518
__glutCurrentWindow->menu[button] = __glutCurrentMenu->id + 1;
522
glutDetachMenu(int button)
524
if (__glutMappedMenu) {
525
menuModificationError();
527
if (__glutCurrentWindow->menu[button] > 0) {
528
__glutCurrentWindow->buttonUses--;
529
__glutCurrentWindow->menu[button] = 0;
b'\\ No newline at end of file'