1c041511dScube 2c041511dScube/* Copyright (c) Mark J. Kilgard, 1994, 1997. */ 3c041511dScube 4c041511dScube/* This program is freely distributable without licensing fees 5c041511dScube and is provided without guarantee or warrantee expressed or 6c041511dScube implied. This program is -not- in the public domain. */ 7c041511dScube 8c041511dScube/* glut_menu2.c implements the little used GLUT menu calls in 9c041511dScube a distinct file from glut_menu.c for slim static linking. */ 10c041511dScube 11c041511dScube/* The Win32 GLUT file win32_menu.c completely re-implements all 12c041511dScube the menuing functionality implemented. This file is used only by 13c041511dScube the X Window System version of GLUT. */ 14c041511dScube 15c041511dScube#ifdef __VMS 16c041511dScube#include <GL/vms_x_fix.h> 17c041511dScube#endif 18c041511dScube 19c041511dScube#include <stdlib.h> 20c041511dScube#include <string.h> 21c041511dScube#include <stdio.h> 22c041511dScube#include <errno.h> 23c041511dScube#include <assert.h> 24c041511dScube 25c041511dScube#include <X11/Xlib.h> 26c041511dScube 27c041511dScube#include "glutint.h" 28c041511dScube 29c041511dScube/* CENTRY */ 30c041511dScube/* DEPRICATED, use glutMenuStatusFunc instead. */ 31c041511dScubevoid GLUTAPIENTRY 32c041511dScubeglutMenuStateFunc(GLUTmenuStateCB menuStateFunc) 33c041511dScube{ 34c041511dScube __glutMenuStatusFunc = (GLUTmenuStatusCB) menuStateFunc; 35c041511dScube} 36c041511dScube 37c041511dScubevoid GLUTAPIENTRY 38c041511dScubeglutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc) 39c041511dScube{ 40c041511dScube __glutMenuStatusFunc = menuStatusFunc; 41c041511dScube} 42c041511dScube 43c041511dScubevoid GLUTAPIENTRY 44c041511dScubeglutDestroyMenu(int menunum) 45c041511dScube{ 46c041511dScube GLUTmenu *menu = __glutGetMenuByNum(menunum); 47c041511dScube GLUTmenuItem *item, *next; 48c041511dScube 49c041511dScube if (__glutMappedMenu) 50c041511dScube __glutMenuModificationError(); 51c041511dScube assert(menu->id == menunum - 1); 52c041511dScube XDestroySubwindows(__glutDisplay, menu->win); 53c041511dScube XDestroyWindow(__glutDisplay, menu->win); 54c041511dScube __glutMenuList[menunum - 1] = NULL; 55c041511dScube /* free all menu entries */ 56c041511dScube item = menu->list; 57c041511dScube while (item) { 58c041511dScube assert(item->menu == menu); 59c041511dScube next = item->next; 60c041511dScube free(item->label); 61c041511dScube free(item); 62c041511dScube item = next; 63c041511dScube } 64c041511dScube if (__glutCurrentMenu == menu) { 65c041511dScube __glutCurrentMenu = NULL; 66c041511dScube } 67c041511dScube free(menu); 68c041511dScube} 69c041511dScube 70c041511dScubevoid GLUTAPIENTRY 71c041511dScubeglutChangeToMenuEntry(int num, const char *label, int value) 72c041511dScube{ 73c041511dScube GLUTmenuItem *item; 74c041511dScube int i; 75c041511dScube 76c041511dScube if (__glutMappedMenu) 77c041511dScube __glutMenuModificationError(); 78c041511dScube i = __glutCurrentMenu->num; 79c041511dScube item = __glutCurrentMenu->list; 80c041511dScube while (item) { 81c041511dScube if (i == num) { 82c041511dScube if (item->isTrigger) { 83c041511dScube /* If changing a submenu trigger to a menu entry, we 84c041511dScube need to account for submenus. */ 85c041511dScube item->menu->submenus--; 86c041511dScube } 87c041511dScube free(item->label); 88c041511dScube __glutSetMenuItem(item, label, value, False); 89c041511dScube return; 90c041511dScube } 91c041511dScube i--; 92c041511dScube item = item->next; 93c041511dScube } 94c041511dScube __glutWarning("Current menu has no %d item.", num); 95c041511dScube} 96c041511dScube 97c041511dScubevoid GLUTAPIENTRY 98c041511dScubeglutChangeToSubMenu(int num, const char *label, int menu) 99c041511dScube{ 100c041511dScube GLUTmenuItem *item; 101c041511dScube int i; 102c041511dScube 103c041511dScube if (__glutMappedMenu) 104c041511dScube __glutMenuModificationError(); 105c041511dScube i = __glutCurrentMenu->num; 106c041511dScube item = __glutCurrentMenu->list; 107c041511dScube while (item) { 108c041511dScube if (i == num) { 109c041511dScube if (!item->isTrigger) { 110c041511dScube /* If changing a menu entry to as submenu trigger, we 111c041511dScube need to account for submenus. */ 112c041511dScube item->menu->submenus++; 113c041511dScube } 114c041511dScube free(item->label); 115c041511dScube __glutSetMenuItem(item, label, /* base 0 */ menu - 1, True); 116c041511dScube return; 117c041511dScube } 118c041511dScube i--; 119c041511dScube item = item->next; 120c041511dScube } 121c041511dScube __glutWarning("Current menu has no %d item.", num); 122c041511dScube} 123c041511dScube 124c041511dScubevoid GLUTAPIENTRY 125c041511dScubeglutRemoveMenuItem(int num) 126c041511dScube{ 127c041511dScube GLUTmenuItem *item, **prev, *remaining; 128c041511dScube int pixwidth, i; 129c041511dScube 130c041511dScube if (__glutMappedMenu) 131c041511dScube __glutMenuModificationError(); 132c041511dScube i = __glutCurrentMenu->num; 133c041511dScube prev = &__glutCurrentMenu->list; 134c041511dScube item = __glutCurrentMenu->list; 135c041511dScube /* If menu item is removed, the menu's pixwidth may need to 136c041511dScube be recomputed. */ 137c041511dScube pixwidth = 1; 138c041511dScube while (item) { 139c041511dScube if (i == num) { 140c041511dScube /* If this menu item's pixwidth is as wide as the menu's 141c041511dScube pixwidth, removing this menu item will necessitate 142c041511dScube shrinking the menu's pixwidth. */ 143c041511dScube if (item->pixwidth >= __glutCurrentMenu->pixwidth) { 144c041511dScube /* Continue recalculating menu pixwidth, first skipping 145c041511dScube the removed item. */ 146c041511dScube remaining = item->next; 147c041511dScube while (remaining) { 148c041511dScube if (remaining->pixwidth > pixwidth) { 149c041511dScube pixwidth = remaining->pixwidth; 150c041511dScube } 151c041511dScube remaining = remaining->next; 152c041511dScube } 153c041511dScube __glutCurrentMenu->pixwidth = pixwidth; 154c041511dScube } 155c041511dScube __glutCurrentMenu->num--; 156c041511dScube __glutCurrentMenu->managed = False; 157c041511dScube 158c041511dScube /* Patch up menu's item list. */ 159c041511dScube *prev = item->next; 160c041511dScube 161c041511dScube free(item->label); 162c041511dScube free(item); 163c041511dScube return; 164c041511dScube } 165c041511dScube if (item->pixwidth > pixwidth) { 166c041511dScube pixwidth = item->pixwidth; 167c041511dScube } 168c041511dScube i--; 169c041511dScube prev = &item->next; 170c041511dScube item = item->next; 171c041511dScube } 172c041511dScube __glutWarning("Current menu has no %d item.", num); 173c041511dScube} 174c041511dScube 175c041511dScubevoid GLUTAPIENTRY 176c041511dScubeglutDetachMenu(int button) 177c041511dScube{ 178c041511dScube if (__glutMappedMenu) 179c041511dScube __glutMenuModificationError(); 180c041511dScube if (__glutCurrentWindow->menu[button] > 0) { 181c041511dScube __glutCurrentWindow->buttonUses--; 182c041511dScube __glutChangeWindowEventMask(ButtonPressMask | ButtonReleaseMask, 183c041511dScube __glutCurrentWindow->buttonUses > 0); 184c041511dScube __glutCurrentWindow->menu[button] = 0; 185c041511dScube } 186c041511dScube} 187c041511dScube 188c041511dScube/* ENDCENTRY */ 189