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