added OS/2 includes
[mesa.git] / src / glut / glx / glut_menu2.c
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 #include "layerutil.h"
29
30 /* CENTRY */
31 /* DEPRICATED, use glutMenuStatusFunc instead. */
32 void APIENTRY
33 glutMenuStateFunc(GLUTmenuStateCB menuStateFunc)
34 {
35 __glutMenuStatusFunc = (GLUTmenuStatusCB) menuStateFunc;
36 }
37
38 void APIENTRY
39 glutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc)
40 {
41 __glutMenuStatusFunc = menuStatusFunc;
42 }
43
44 void APIENTRY
45 glutDestroyMenu(int menunum)
46 {
47 GLUTmenu *menu = __glutGetMenuByNum(menunum);
48 GLUTmenuItem *item, *next;
49
50 if (__glutMappedMenu)
51 __glutMenuModificationError();
52 assert(menu->id == menunum - 1);
53 XDestroySubwindows(__glutDisplay, menu->win);
54 XDestroyWindow(__glutDisplay, menu->win);
55 __glutMenuList[menunum - 1] = NULL;
56 /* free all menu entries */
57 item = menu->list;
58 while (item) {
59 assert(item->menu == menu);
60 next = item->next;
61 free(item->label);
62 free(item);
63 item = next;
64 }
65 if (__glutCurrentMenu == menu) {
66 __glutCurrentMenu = NULL;
67 }
68 free(menu);
69 }
70
71 void APIENTRY
72 glutChangeToMenuEntry(int num, const char *label, int value)
73 {
74 GLUTmenuItem *item;
75 int i;
76
77 if (__glutMappedMenu)
78 __glutMenuModificationError();
79 i = __glutCurrentMenu->num;
80 item = __glutCurrentMenu->list;
81 while (item) {
82 if (i == num) {
83 if (item->isTrigger) {
84 /* If changing a submenu trigger to a menu entry, we
85 need to account for submenus. */
86 item->menu->submenus--;
87 }
88 free(item->label);
89 __glutSetMenuItem(item, label, value, False);
90 return;
91 }
92 i--;
93 item = item->next;
94 }
95 __glutWarning("Current menu has no %d item.", num);
96 }
97
98 void APIENTRY
99 glutChangeToSubMenu(int num, const char *label, int menu)
100 {
101 GLUTmenuItem *item;
102 int i;
103
104 if (__glutMappedMenu)
105 __glutMenuModificationError();
106 i = __glutCurrentMenu->num;
107 item = __glutCurrentMenu->list;
108 while (item) {
109 if (i == num) {
110 if (!item->isTrigger) {
111 /* If changing a menu entry to as submenu trigger, we
112 need to account for submenus. */
113 item->menu->submenus++;
114 }
115 free(item->label);
116 __glutSetMenuItem(item, label, /* base 0 */ menu - 1, True);
117 return;
118 }
119 i--;
120 item = item->next;
121 }
122 __glutWarning("Current menu has no %d item.", num);
123 }
124
125 void APIENTRY
126 glutRemoveMenuItem(int num)
127 {
128 GLUTmenuItem *item, **prev, *remaining;
129 int pixwidth, i;
130
131 if (__glutMappedMenu)
132 __glutMenuModificationError();
133 i = __glutCurrentMenu->num;
134 prev = &__glutCurrentMenu->list;
135 item = __glutCurrentMenu->list;
136 /* If menu item is removed, the menu's pixwidth may need to
137 be recomputed. */
138 pixwidth = 1;
139 while (item) {
140 if (i == num) {
141 /* If this menu item's pixwidth is as wide as the menu's
142 pixwidth, removing this menu item will necessitate
143 shrinking the menu's pixwidth. */
144 if (item->pixwidth >= __glutCurrentMenu->pixwidth) {
145 /* Continue recalculating menu pixwidth, first skipping
146 the removed item. */
147 remaining = item->next;
148 while (remaining) {
149 if (remaining->pixwidth > pixwidth) {
150 pixwidth = remaining->pixwidth;
151 }
152 remaining = remaining->next;
153 }
154 __glutCurrentMenu->pixwidth = pixwidth;
155 }
156 __glutCurrentMenu->num--;
157 __glutCurrentMenu->managed = False;
158
159 /* Patch up menu's item list. */
160 *prev = item->next;
161
162 free(item->label);
163 free(item);
164 return;
165 }
166 if (item->pixwidth > pixwidth) {
167 pixwidth = item->pixwidth;
168 }
169 i--;
170 prev = &item->next;
171 item = item->next;
172 }
173 __glutWarning("Current menu has no %d item.", num);
174 }
175
176 void APIENTRY
177 glutDetachMenu(int button)
178 {
179 if (__glutMappedMenu)
180 __glutMenuModificationError();
181 if (__glutCurrentWindow->menu[button] > 0) {
182 __glutCurrentWindow->buttonUses--;
183 __glutChangeWindowEventMask(ButtonPressMask | ButtonReleaseMask,
184 __glutCurrentWindow->buttonUses > 0);
185 __glutCurrentWindow->menu[button] = 0;
186 }
187 }
188
189 /* ENDCENTRY */