| |
| /* Copyright (c) Mark J. Kilgard, 1994, 1997. */ |
| |
| /* This program is freely distributable without licensing fees |
| and is provided without guarantee or warrantee expressed or |
| implied. This program is -not- in the public domain. */ |
| |
| /* glut_menu2.c implements the little used GLUT menu calls in |
| a distinct file from glut_menu.c for slim static linking. */ |
| |
| /* The Win32 GLUT file win32_menu.c completely re-implements all |
| the menuing functionality implemented. This file is used only by |
| the X Window System version of GLUT. */ |
| |
| #ifdef __VMS |
| #include <GL/vms_x_fix.h> |
| #endif |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <assert.h> |
| |
| #include <X11/Xlib.h> |
| |
| #include "glutint.h" |
| #include "layerutil.h" |
| |
| /* CENTRY */ |
| /* DEPRICATED, use glutMenuStatusFunc instead. */ |
| void GLUTAPIENTRY |
| glutMenuStateFunc(GLUTmenuStateCB menuStateFunc) |
| { |
| __glutMenuStatusFunc = (GLUTmenuStatusCB) menuStateFunc; |
| } |
| |
| void GLUTAPIENTRY |
| glutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc) |
| { |
| __glutMenuStatusFunc = menuStatusFunc; |
| } |
| |
| void GLUTAPIENTRY |
| glutDestroyMenu(int menunum) |
| { |
| GLUTmenu *menu = __glutGetMenuByNum(menunum); |
| GLUTmenuItem *item, *next; |
| |
| if (__glutMappedMenu) |
| __glutMenuModificationError(); |
| assert(menu->id == menunum - 1); |
| XDestroySubwindows(__glutDisplay, menu->win); |
| XDestroyWindow(__glutDisplay, menu->win); |
| __glutMenuList[menunum - 1] = NULL; |
| /* free all menu entries */ |
| item = menu->list; |
| while (item) { |
| assert(item->menu == menu); |
| next = item->next; |
| free(item->label); |
| free(item); |
| item = next; |
| } |
| if (__glutCurrentMenu == menu) { |
| __glutCurrentMenu = NULL; |
| } |
| free(menu); |
| } |
| |
| void GLUTAPIENTRY |
| glutChangeToMenuEntry(int num, const char *label, int value) |
| { |
| GLUTmenuItem *item; |
| int i; |
| |
| if (__glutMappedMenu) |
| __glutMenuModificationError(); |
| i = __glutCurrentMenu->num; |
| item = __glutCurrentMenu->list; |
| while (item) { |
| if (i == num) { |
| if (item->isTrigger) { |
| /* If changing a submenu trigger to a menu entry, we |
| need to account for submenus. */ |
| item->menu->submenus--; |
| } |
| free(item->label); |
| __glutSetMenuItem(item, label, value, False); |
| return; |
| } |
| i--; |
| item = item->next; |
| } |
| __glutWarning("Current menu has no %d item.", num); |
| } |
| |
| void GLUTAPIENTRY |
| glutChangeToSubMenu(int num, const char *label, int menu) |
| { |
| GLUTmenuItem *item; |
| int i; |
| |
| if (__glutMappedMenu) |
| __glutMenuModificationError(); |
| i = __glutCurrentMenu->num; |
| item = __glutCurrentMenu->list; |
| while (item) { |
| if (i == num) { |
| if (!item->isTrigger) { |
| /* If changing a menu entry to as submenu trigger, we |
| need to account for submenus. */ |
| item->menu->submenus++; |
| } |
| free(item->label); |
| __glutSetMenuItem(item, label, /* base 0 */ menu - 1, True); |
| return; |
| } |
| i--; |
| item = item->next; |
| } |
| __glutWarning("Current menu has no %d item.", num); |
| } |
| |
| void GLUTAPIENTRY |
| glutRemoveMenuItem(int num) |
| { |
| GLUTmenuItem *item, **prev, *remaining; |
| int pixwidth, i; |
| |
| if (__glutMappedMenu) |
| __glutMenuModificationError(); |
| i = __glutCurrentMenu->num; |
| prev = &__glutCurrentMenu->list; |
| item = __glutCurrentMenu->list; |
| /* If menu item is removed, the menu's pixwidth may need to |
| be recomputed. */ |
| pixwidth = 1; |
| while (item) { |
| if (i == num) { |
| /* If this menu item's pixwidth is as wide as the menu's |
| pixwidth, removing this menu item will necessitate |
| shrinking the menu's pixwidth. */ |
| if (item->pixwidth >= __glutCurrentMenu->pixwidth) { |
| /* Continue recalculating menu pixwidth, first skipping |
| the removed item. */ |
| remaining = item->next; |
| while (remaining) { |
| if (remaining->pixwidth > pixwidth) { |
| pixwidth = remaining->pixwidth; |
| } |
| remaining = remaining->next; |
| } |
| __glutCurrentMenu->pixwidth = pixwidth; |
| } |
| __glutCurrentMenu->num--; |
| __glutCurrentMenu->managed = False; |
| |
| /* Patch up menu's item list. */ |
| *prev = item->next; |
| |
| free(item->label); |
| free(item); |
| return; |
| } |
| if (item->pixwidth > pixwidth) { |
| pixwidth = item->pixwidth; |
| } |
| i--; |
| prev = &item->next; |
| item = item->next; |
| } |
| __glutWarning("Current menu has no %d item.", num); |
| } |
| |
| void GLUTAPIENTRY |
| glutDetachMenu(int button) |
| { |
| if (__glutMappedMenu) |
| __glutMenuModificationError(); |
| if (__glutCurrentWindow->menu[button] > 0) { |
| __glutCurrentWindow->buttonUses--; |
| __glutChangeWindowEventMask(ButtonPressMask | ButtonReleaseMask, |
| __glutCurrentWindow->buttonUses > 0); |
| __glutCurrentWindow->menu[button] = 0; |
| } |
| } |
| |
| /* ENDCENTRY */ |