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