1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4
5 #include "menu.h"
6 #include "sar.h"
7 #include "sarmenuop.h"
8
9 void SARMenuSwitchToMenu(sar_core_struct *core_ptr, const char *name);
10 sar_menu_list_struct *SARMenuGetList(
11 sar_menu_struct *m, int skip, int *list_num
12 );
13 sar_menu_spin_struct *SARMenuGetSpin(
14 sar_menu_struct *m, int skip, int *spin_num
15 );
16 sar_menu_list_item_struct *SARMenuListGetSelectedItem(
17 sar_menu_struct *m, int id
18 );
19 char *SARMenuGetCurrentMenuName(sar_core_struct *core_ptr);
20
21
22 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
23 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
24 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
25 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
26
27
28 /*
29 * Switches to the specified menu.
30 *
31 * If no menu is specified (name=NULL) then simulation will
32 * begin.
33 */
SARMenuSwitchToMenu(sar_core_struct * core_ptr,const char * name)34 void SARMenuSwitchToMenu(sar_core_struct *core_ptr, const char *name)
35 {
36 int new_menu_num, old_menu_num;
37 gw_display_struct *display;
38 const sar_option_struct *opt;
39
40 if(core_ptr == NULL)
41 return;
42
43 display = core_ptr->display;
44 opt = &core_ptr->option;
45
46 /* Record previous menu number */
47 old_menu_num = core_ptr->cur_menu;
48
49 /* No specified menu to switch to? */
50 if(name == NULL)
51 {
52 /* This implies we are going out of the menu system and
53 * entering simulation
54 */
55 sar_menu_struct *old_menu = SARIsMenuAllocated(core_ptr, old_menu_num) ?
56 core_ptr->menu[old_menu_num] : NULL;
57
58 /* Unload image on old menu */
59 /* if(opt->prioritize_memory && (old_menu != NULL)) */
60 if(old_menu != NULL)
61 SARMenuUnloadBackgroundImage(old_menu);
62
63 /* Unselect current menu on core structure, indicating that
64 * no menu is selected and that we are not in the menus
65 */
66 core_ptr->cur_menu = -1;
67
68 /* Skip redrawing, since redrawing would be done rather
69 * frequently during the simulation
70 */
71 /* GWPostRedraw(display); */
72
73 return;
74 }
75
76 /* Get the number of the menu that we want to switch to */
77 new_menu_num = SARMatchMenuByName(core_ptr, name);
78 /* Got match and matched menu number is different from the one
79 * currently selected?
80 */
81 if((new_menu_num > -1) && (new_menu_num != core_ptr->cur_menu))
82 {
83 sar_menu_struct *old_menu = SARIsMenuAllocated(core_ptr, old_menu_num) ?
84 core_ptr->menu[old_menu_num] : NULL;
85 sar_menu_struct *new_menu = SARIsMenuAllocated(core_ptr, new_menu_num) ?
86 core_ptr->menu[new_menu_num] : NULL;
87 const char *old_bg_image_path = (old_menu != NULL) ?
88 old_menu->bg_image_path : NULL,
89 *new_bg_image_path = (new_menu != NULL) ?
90 new_menu->bg_image_path : NULL;
91
92 GWSetInputBusy(display);
93
94 /* Reset values on the previous menu */
95 /*
96 if(old_menu != NULL)
97 {
98
99
100
101
102
103 }
104 */
105
106 /* Check if background images are the same on both old and
107 * new menus by comparing the background image paths (if
108 * defined)
109 */
110 if(((old_bg_image_path != NULL) &&
111 (new_bg_image_path != NULL)) ?
112 ((old_menu->bg_image != NULL) ?
113 !strcmp(old_bg_image_path, new_bg_image_path) : False)
114 : False
115 )
116 {
117 /* Image paths are the same, so unload the image on the
118 * new menu and transfer the image from the old menu to
119 * the new menu
120 *
121 * Mark the old menu's image NULL after transfer so
122 * that it dosen't get referenced again
123 *
124 * Note that both new_menu and old_menu are known to be
125 * not NULL from the above check
126 */
127 SARMenuUnloadBackgroundImage(new_menu);
128 if(new_menu->bg_image == NULL)
129 {
130 new_menu->bg_image = old_menu->bg_image;
131 old_menu->bg_image = NULL;
132 }
133 }
134 else
135 {
136 /* Image paths are different, so unload background image
137 * on old menu and load new background image on new menu
138 */
139 /* if(opt->prioritize_memory && (old_menu != NULL)) */
140 if(old_menu != NULL)
141 SARMenuUnloadBackgroundImage(old_menu);
142
143 if(opt->menu_backgrounds &&
144 ((new_menu != NULL) ? (new_menu->bg_image == NULL) : False)
145 )
146 SARMenuLoadBackgroundImage(new_menu);
147 }
148
149 glClearColor(0, 0, 0, 0);
150 glClear(GL_COLOR_BUFFER_BIT);
151 GWSwapBuffer(core_ptr->display);
152 GWFlush(core_ptr->display);
153
154 /* Is the new menu valid? */
155 if(new_menu != NULL)
156 {
157 /* New menu is valid, so switch to it */
158 int n;
159 void *o;
160 sar_menu_button_struct *btn;
161 sar_menu_struct *m = new_menu;
162
163 /* Begin resetting object values on the new menu */
164 for(n = 0; n < m->total_objects; n++)
165 {
166 o = m->object[n];
167 if(o == NULL)
168 continue;
169
170 switch(SAR_MENU_OBJECT_TYPE(o))
171 {
172 case SAR_MENU_OBJECT_TYPE_BUTTON:
173 btn = SAR_MENU_BUTTON(o);
174 btn->state = SAR_MENU_BUTTON_STATE_UNARMED;
175 break;
176
177 case SAR_MENU_OBJECT_TYPE_PROGRESS:
178 SARMenuProgressSet(
179 display, m, n,
180 0.0f, False
181 );
182 break;
183 }
184 }
185
186 /* Select first object on menu */
187 m->selected_object = 0;
188
189 /* Update index number of the current menu */
190 core_ptr->cur_menu = new_menu_num;
191 }
192
193 /* Redraw */
194 GWPostRedraw(display);
195
196 /* Mark input as ready */
197 GWSetInputReady(display);
198 }
199 }
200
201 /*
202 * Returns the pointer to the list object on the menu,
203 * skipping the indicated number of lists.
204 *
205 * Can return NULL for no match.
206 */
SARMenuGetList(sar_menu_struct * m,int skip,int * list_num)207 sar_menu_list_struct *SARMenuGetList(
208 sar_menu_struct *m, int skip, int *list_num
209 )
210 {
211 int i;
212 void *ptr;
213 sar_menu_list_struct *list_ptr;
214
215
216 if(m == NULL)
217 return(NULL);
218
219 if(list_num != NULL)
220 *list_num = -1;
221
222 for(i = 0; i < m->total_objects; i++)
223 {
224 ptr = m->object[i];
225 if(ptr == NULL)
226 continue;
227
228 if(*(int *)ptr != SAR_MENU_OBJECT_TYPE_LIST)
229 continue;
230
231 /* Get pointer to list object. */
232 list_ptr = ptr;
233
234 /* Skip this list object? */
235 if(skip > 0)
236 {
237 skip--;
238 continue;
239 }
240 else
241 {
242 if(list_num != NULL)
243 *list_num = i;
244 return(list_ptr);
245 }
246 }
247
248 return(NULL);
249 }
250
251 /*
252 * Returns the pointer to the spin object on the menu,
253 * skipping the indicated number of spin objects.
254 *
255 * Can return NULL for no match.
256 */
SARMenuGetSpin(sar_menu_struct * m,int skip,int * spin_num)257 sar_menu_spin_struct *SARMenuGetSpin(
258 sar_menu_struct *m, int skip, int *spin_num
259 )
260 {
261 int i;
262 void *ptr;
263 sar_menu_spin_struct *spin_ptr;
264
265
266 if(m == NULL)
267 return(NULL);
268
269 if(spin_num != NULL)
270 *spin_num = -1;
271
272 for(i = 0; i < m->total_objects; i++)
273 {
274 ptr = m->object[i];
275 if(ptr == NULL)
276 continue;
277
278 if(*(int *)ptr != SAR_MENU_OBJECT_TYPE_SPIN)
279 continue;
280
281 /* Get pointer to spin object. */
282 spin_ptr = ptr;
283
284 /* Skip this spin object? */
285 if(skip > 0)
286 {
287 skip--;
288 continue;
289 }
290 else
291 {
292 if(spin_num != NULL)
293 *spin_num = i;
294
295 return(spin_ptr);
296 }
297 }
298
299 return(NULL);
300 }
301
302 /*
303 * Returns the pointer to the selected list item on the list object
304 * on the menu, skipping the indicated number of list objects.
305 */
SARMenuListGetSelectedItem(sar_menu_struct * m,int id)306 sar_menu_list_item_struct *SARMenuListGetSelectedItem(
307 sar_menu_struct *m, int id
308 )
309 {
310 int i;
311 sar_menu_list_struct *list = SAR_MENU_LIST(
312 SARMenuGetObjectByID(m, id, NULL)
313 );
314 if(list == NULL)
315 return(NULL);
316
317 i = list->selected_item;
318 if((i >= 0) && (i < list->total_items))
319 return(list->item[i]);
320 else
321 return(NULL);
322 }
323
324 /*
325 * Returns the pointer to the name of the currently selected
326 * menu or NULL on failure.
327 */
SARMenuGetCurrentMenuName(sar_core_struct * core_ptr)328 char *SARMenuGetCurrentMenuName(sar_core_struct *core_ptr)
329 {
330 int cur_menu;
331 sar_menu_struct *m;
332
333
334 if(core_ptr == NULL)
335 return(NULL);
336
337 cur_menu = core_ptr->cur_menu;
338 if(SARIsMenuAllocated(core_ptr, cur_menu))
339 m = core_ptr->menu[cur_menu];
340 else
341 return(NULL);
342
343 return(m->name);
344 }
345