mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-19 17:58:09 +02:00
323 lines
7.8 KiB
C++
323 lines
7.8 KiB
C++
|
|
/***********************************************************
|
||
|
|
* Copyright (C) 1997, Be Inc. All rights reserved.
|
||
|
|
*
|
||
|
|
* FILE: glutMenu.cpp
|
||
|
|
*
|
||
|
|
* DESCRIPTION: code for popup menu handling
|
||
|
|
***********************************************************/
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* Headers
|
||
|
|
***********************************************************/
|
||
|
|
#include <GL/glut.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include "glutint.h"
|
||
|
|
#include "glutState.h"
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* Private variables
|
||
|
|
***********************************************************/
|
||
|
|
static GlutMenu **menuList = 0;
|
||
|
|
static int menuListSize = 0;
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: getUnusedMenuSlot
|
||
|
|
*
|
||
|
|
* DESCRIPTION: helper function to get a new menu slot
|
||
|
|
***********************************************************/
|
||
|
|
GlutMenu *__glutGetMenuByNum(int menunum)
|
||
|
|
{
|
||
|
|
if (menunum < 1 || menunum > menuListSize) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
return menuList[menunum - 1];
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: getUnusedMenuSlot
|
||
|
|
*
|
||
|
|
* DESCRIPTION: helper function to get a new menu slot
|
||
|
|
***********************************************************/
|
||
|
|
static int
|
||
|
|
getUnusedMenuSlot(void)
|
||
|
|
{
|
||
|
|
int i;
|
||
|
|
|
||
|
|
/* Look for allocated, unused slot. */
|
||
|
|
for (i = 0; i < menuListSize; i++) {
|
||
|
|
if (!menuList[i]) {
|
||
|
|
return i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/* Allocate a new slot. */
|
||
|
|
menuListSize++;
|
||
|
|
menuList = (GlutMenu **)
|
||
|
|
realloc(menuList, menuListSize * sizeof(GlutMenu *));
|
||
|
|
if (!menuList)
|
||
|
|
__glutFatalError("out of memory.");
|
||
|
|
menuList[menuListSize - 1] = NULL;
|
||
|
|
return menuListSize - 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutCreateMenu (6.1)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: create a new menu
|
||
|
|
***********************************************************/
|
||
|
|
int APIENTRY
|
||
|
|
glutCreateMenu(GLUTselectCB selectFunc)
|
||
|
|
{
|
||
|
|
GlutMenu *menu;
|
||
|
|
int menuid;
|
||
|
|
|
||
|
|
menuid = getUnusedMenuSlot();
|
||
|
|
menu = new GlutMenu(menuid, selectFunc); // constructor sets up members
|
||
|
|
menuList[menuid] = menu;
|
||
|
|
gState.currentMenu = menu;
|
||
|
|
return menuid + 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutSetMenu (6.2)
|
||
|
|
* glutGetMenu
|
||
|
|
*
|
||
|
|
* DESCRIPTION: set and get the current menu
|
||
|
|
***********************************************************/
|
||
|
|
int APIENTRY
|
||
|
|
glutGetMenu(void)
|
||
|
|
{
|
||
|
|
if (gState.currentMenu) {
|
||
|
|
return gState.currentMenu->id + 1;
|
||
|
|
} else {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void APIENTRY
|
||
|
|
glutSetMenu(int menuid)
|
||
|
|
{
|
||
|
|
GlutMenu *menu;
|
||
|
|
|
||
|
|
if (menuid < 1 || menuid > menuListSize) {
|
||
|
|
__glutWarning("glutSetMenu attempted on bogus menu.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
menu = menuList[menuid - 1];
|
||
|
|
if (!menu) {
|
||
|
|
__glutWarning("glutSetMenu attempted on bogus menu.");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
gState.currentMenu = menu;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutDestroyMenu (6.3)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: destroy the specified menu
|
||
|
|
***********************************************************/
|
||
|
|
void APIENTRY
|
||
|
|
glutDestroyMenu(int menunum)
|
||
|
|
{
|
||
|
|
GlutMenu *menu = __glutGetMenuByNum(menunum);
|
||
|
|
menuList[menunum - 1] = 0;
|
||
|
|
if (gState.currentMenu == menu) {
|
||
|
|
gState.currentMenu = 0;
|
||
|
|
}
|
||
|
|
delete menu;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutAddMenuEntry (6.4)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: add a new menu item
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutAddMenuEntry(const char *label, int value)
|
||
|
|
{
|
||
|
|
new GlutMenuItem(gState.currentMenu, false, value, label);
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutAddSubMenu (6.5)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: add a new submenu
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutAddSubMenu(const char *label, int menu)
|
||
|
|
{
|
||
|
|
new GlutMenuItem(gState.currentMenu, true, menu-1, label);
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutChangeToMenuEntry (6.6)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: change menuitem into a menu entry
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutChangeToMenuEntry(int num, const char *label, int value)
|
||
|
|
{
|
||
|
|
GlutMenuItem *item;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
i = gState.currentMenu->num;
|
||
|
|
item = gState.currentMenu->list;
|
||
|
|
while (item) {
|
||
|
|
if (i == num) {
|
||
|
|
free(item->label);
|
||
|
|
item->label = strdup(label);
|
||
|
|
item->isTrigger = false;
|
||
|
|
item->value = value;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
i--;
|
||
|
|
item = item->next;
|
||
|
|
}
|
||
|
|
__glutWarning("Current menu has no %d item.", num);
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutChangeToSubMenu (6.7)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: change menuitem into a submenu
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutChangeToSubMenu(int num, const char *label, int menu)
|
||
|
|
{
|
||
|
|
GlutMenuItem *item;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
i = gState.currentMenu->num;
|
||
|
|
item = gState.currentMenu->list;
|
||
|
|
while (item) {
|
||
|
|
if (i == num) {
|
||
|
|
free(item->label);
|
||
|
|
item->label = strdup(label);
|
||
|
|
item->isTrigger = true;
|
||
|
|
item->value = menu-1;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
i--;
|
||
|
|
item = item->next;
|
||
|
|
}
|
||
|
|
__glutWarning("Current menu has no %d item.", num);
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutRemoveMenuItem (6.8)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: remove a menu item
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutRemoveMenuItem(int num)
|
||
|
|
{
|
||
|
|
GlutMenuItem *item, **prev;
|
||
|
|
int i;
|
||
|
|
|
||
|
|
i = gState.currentMenu->num;
|
||
|
|
prev = &gState.currentMenu->list;
|
||
|
|
item = gState.currentMenu->list;
|
||
|
|
|
||
|
|
while (item) {
|
||
|
|
if (i == num) {
|
||
|
|
gState.currentMenu->num--;
|
||
|
|
|
||
|
|
/* Patch up menu's item list. */
|
||
|
|
*prev = item->next;
|
||
|
|
|
||
|
|
free(item->label);
|
||
|
|
delete item;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
i--;
|
||
|
|
prev = &item->next;
|
||
|
|
item = item->next;
|
||
|
|
}
|
||
|
|
__glutWarning("Current menu has no %d item.", num);
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* FUNCTION: glutAttachMenu (6.9)
|
||
|
|
* glutDetachMenu
|
||
|
|
*
|
||
|
|
* DESCRIPTION: attach and detach menu from view
|
||
|
|
***********************************************************/
|
||
|
|
void
|
||
|
|
glutAttachMenu(int button)
|
||
|
|
{
|
||
|
|
gState.currentWindow->menu[button] = gState.currentMenu->id + 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
glutDetachMenu(int button)
|
||
|
|
{
|
||
|
|
gState.currentWindow->menu[button] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* CLASS: GlutMenu
|
||
|
|
*
|
||
|
|
* FUNCTION: CreateBMenu
|
||
|
|
*
|
||
|
|
* DESCRIPTION: construct a BPopupMenu for this menu
|
||
|
|
***********************************************************/
|
||
|
|
BMenu *GlutMenu::CreateBMenu(bool toplevel) {
|
||
|
|
BMenu *bpopup;
|
||
|
|
if(toplevel) {
|
||
|
|
bpopup = new GlutPopUp(id+1);
|
||
|
|
} else {
|
||
|
|
bpopup = new BMenu("");
|
||
|
|
}
|
||
|
|
GlutMenuItem *item = list;
|
||
|
|
while (item) {
|
||
|
|
GlutBMenuItem *bitem;
|
||
|
|
if(item->isTrigger) {
|
||
|
|
// recursively call CreateBMenu
|
||
|
|
bitem = new GlutBMenuItem(menuList[item->value]->CreateBMenu(false));
|
||
|
|
bitem->SetLabel(item->label);
|
||
|
|
bitem->menu = 0; // real menu items start at 1
|
||
|
|
bitem->value = 0;
|
||
|
|
} else {
|
||
|
|
bitem = new GlutBMenuItem(item->label);
|
||
|
|
bitem->menu = id + 1;
|
||
|
|
bitem->value = item->value;
|
||
|
|
}
|
||
|
|
bpopup->AddItem(bitem, 0);
|
||
|
|
item = item->next;
|
||
|
|
}
|
||
|
|
return bpopup;
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* CLASS: GlutMenu
|
||
|
|
*
|
||
|
|
* FUNCTION: (destructor)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: destroy the menu and its items (but not submenus!)
|
||
|
|
***********************************************************/
|
||
|
|
GlutMenu::~GlutMenu() {
|
||
|
|
while (list) {
|
||
|
|
GlutMenuItem *next = list->next;
|
||
|
|
delete list;
|
||
|
|
list = next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************
|
||
|
|
* CLASS: GlutMenuItem
|
||
|
|
*
|
||
|
|
* FUNCTION: (constructor)
|
||
|
|
*
|
||
|
|
* DESCRIPTION: construct the new menu item and add to parent
|
||
|
|
***********************************************************/
|
||
|
|
GlutMenuItem::GlutMenuItem(GlutMenu *n_menu, bool n_trig, int n_value, const char *n_label)
|
||
|
|
{
|
||
|
|
menu = n_menu;
|
||
|
|
isTrigger = n_trig;
|
||
|
|
value = n_value;
|
||
|
|
label = strdup(n_label);
|
||
|
|
next = menu->list;
|
||
|
|
menu->list = this;
|
||
|
|
menu->num++;
|
||
|
|
}
|