1 /*
2 * GNUjump
3 * =======
4 *
5 * Copyright (C) 2005-2008, Juan Pedro Bolivar Puente
6 *
7 * GNUjump is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * GNUjump is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdarg.h>
22
23 #include "gnujump.h"
24 #include "menu.h"
25 #include "game.h"
26 #include "setup.h"
27 #include "tools.h"
28
29 extern SDL_Surface *screen;
30 extern L_gblOptions gblOps;
31
32 void
initMouse(data_t * gfx,mouse_t * mouse)33 initMouse (data_t * gfx, mouse_t * mouse)
34 {
35 int i;
36
37 for (i = 0; i < M_STATES; i++)
38 {
39 initializeSpriteCtl (&(mouse->sprite[i]), gfx->mouse[i]);
40 }
41 mouse->id = M_IDLE;
42 mouse->clicked = FALSE;
43 }
44
45 void
printMouse(data_t * gfx,mouse_t * mouse)46 printMouse (data_t * gfx, mouse_t * mouse)
47 {
48 SDL_Rect dest;
49 dest.x = mouse->x - gfx->mouseX;
50 dest.y = mouse->y - gfx->mouseY;
51 printSprite (&(mouse->sprite[mouse->id]), NULL, &dest, 0);
52 }
53
54 void
unprintMouse(data_t * gfx,mouse_t * mouse)55 unprintMouse (data_t * gfx, mouse_t * mouse)
56 {
57 SDL_Rect dest;
58 SDL_Rect src;
59 src.x = dest.x = mouse->x - gfx->mouseX;
60 src.y = dest.y = mouse->y - gfx->mouseY;
61 src.w = mouse->sprite[mouse->id].sdata->pic[0]->w;
62 src.h = mouse->sprite[mouse->id].sdata->pic[0]->h;
63 JPB_PrintSurface (gfx->menuBg, &src, &dest);
64 }
65
66 void
setMouseState(mouse_t * mouse,int id)67 setMouseState (mouse_t * mouse, int id)
68 {
69 if (mouse->id != id)
70 {
71 mouse->sprite[id].elpTime = mouse->sprite[id].frame = 0;
72 mouse->id = id;
73 }
74 }
75
76 void
checkMouse(data_t * gfx,mouse_t * mouse,int * sel,int nops,int off)77 checkMouse (data_t * gfx, mouse_t * mouse, int *sel, int nops, int off)
78 {
79 int rx = 0, ry = 0;
80 int no = MIN (gfx->mMaxOps, nops);
81
82 mouse->clicked = SDL_GetMouseState (&(mouse->x), &(mouse->y));
83
84 if (mouse->x >= gfx->menuX
85 && mouse->x < gfx->menuX + gfx->menuW
86 && mouse->y >= gfx->menuY
87 && mouse->y < gfx->menuY + SFont_TextHeight (gfx->menufont) * no)
88 {
89
90 if (((mouse->clicked = SDL_GetRelativeMouseState (&rx, &ry)) || rx != 0
91 || ry != 0))
92 *sel =
93 (mouse->y - gfx->menuY) / SFont_TextHeight (gfx->menufont) + off;
94
95 if (!mouse->clicked)
96 setMouseState (mouse, M_OVER);
97 else
98 setMouseState (mouse, M_DOWN);
99 }
100 else
101 {
102 if (!mouse->clicked)
103 setMouseState (mouse, M_IDLE);
104 else
105 setMouseState (mouse, M_DOWN);
106 }
107 }
108
109 /*
110 * NEW MENU SYSTEM =============================================================
111 */
112
113 void
initMenuT(menu_t * menu)114 initMenuT (menu_t * menu)
115 {
116 menu->nops = 0;
117 menu->opt = NULL;
118 }
119
120 /*
121 Arguments are:
122 - menu: pointer to the menu where the option should be included.
123 - caption/tip: caption and tip of the option (these won't be freed)
124 - flags: some flags defining what kind of option this is
125 - data: depends on our option flags.
126 + (*int) for MB_CHOOSE
127 + (**char) for MB_INPUT
128 + (*SDLKey) for MB_KEYDEF
129 - nops: NONE if no flags are chosen; 0, if flags != MB_CHOOSE, etc..
130 - ...: char* to the name of the different options (if nops>0 :-))
131 */
132 void
addMenuTOption(menu_t * menu,char * caption,char * tip,int flags,void * data,int nops,...)133 addMenuTOption (menu_t * menu, char *caption, char *tip, int flags,
134 void *data, int nops, ...)
135 {
136 va_list p;
137 opt_t *opt = NULL;
138 int i = 0;
139
140 menu->nops++;
141 menu->opt = realloc (menu->opt, sizeof (opt_t) * menu->nops);
142
143 opt = &menu->opt[menu->nops - 1];
144 opt->caption = opt->tip = NULL;
145 opt->caption = caption;
146 opt->tip = tip;
147
148 opt->flags = flags;
149 opt->nops = nops;
150 opt->data = data;
151 opt->opcap = NULL;
152
153 if (nops > 0)
154 {
155 va_start (p, nops);
156 opt->opcap = malloc (sizeof (char *) * nops);
157 for (i = 0; i < nops; i++)
158 {
159 opt->opcap[i] = va_arg (p, char *);
160 }
161 va_end (p);
162 }
163 else
164 {
165 opt->flags |= MB_RETURN;
166 }
167
168 }
169
170 void
freeMenuTOption(opt_t * opt)171 freeMenuTOption (opt_t * opt)
172 {
173 free (opt->opcap);
174 }
175
176 void
freeMenuT(menu_t * menu)177 freeMenuT (menu_t * menu)
178 {
179 int i;
180 for (i = 0; i < menu->nops; i++)
181 {
182 freeMenuTOption (&menu->opt[i]);
183 }
184 free (menu->opt);
185 }
186
187 int
playMenuT(data_t * gfx,menu_t * menu)188 playMenuT (data_t * gfx, menu_t * menu)
189 {
190 int done = FALSE;
191 int prevselect = 0, select = 0;
192 fader_t *mfaders;
193 fader_t afaders[ARROWS];
194 char *tmpstr = NULL;
195 SDL_Event event;
196 L_timer timer;
197 mouse_t mouse;
198 int offset = 0, maxops = MIN (menu->nops, gfx->mMaxOps), maxoffset =
199 menu->nops - gfx->mMaxOps;
200 int i;
201
202 if (menu->nops == 0)
203 {
204 if (gfx->mback)
205 Mix_PlayChannel (-1, gfx->mback, 0);
206 return NONE;
207 }
208
209 initMouse (gfx, &mouse);
210 initTimer (&timer, getFps ());
211 mfaders = malloc (sizeof (fader_t) * menu->nops);
212 setFader (&mfaders[select], 0, gfx->hlalpha, 1, FALSE);
213 for (i = select + 1; i < menu->nops; i++)
214 setFader (&mfaders[i], 0, 0, 1, FALSE);
215 for (i = 0; i < ARROWS; i++)
216 setFader (&afaders[i], 0, 0, 1, FALSE);
217 drawMenuT (gfx, menu, offset);
218 if (menu->opt[select].tip != NULL)
219 drawTip (gfx, menu->opt[select].tip);
220 FlipScreen ();
221
222 while (!done)
223 {
224 updateTimer (&timer);
225 for (i = 0; i < menu->nops; i++)
226 {
227 updateFader (&mfaders[i], timer.ms);
228 }
229 for (i = 0; i < ARROWS; i++)
230 {
231 updateFader (&afaders[i], timer.ms);
232 }
233 unprintMouse (gfx, &mouse);
234 undrawTip (gfx);
235 checkMouse (gfx, &mouse, &select, menu->nops, offset);
236 switch (checkMenuKeys (&mouse))
237 {
238 case KMENTER:
239 if (mouse.id != M_OVER)
240 break;
241 case KENTER:
242 if (menu->opt[select].nops > 0)
243 {
244 (*((int *) menu->opt[select].data))++;
245 if (*((int *) menu->opt[select].data) >= menu->opt[select].nops)
246 {
247 *((int *) menu->opt[select].data) = 0;
248 }
249 }
250 if ((menu->opt[select].flags & MB_INPUT) == MB_INPUT)
251 {
252 tmpstr =
253 inputMenu (gfx, menu->opt[select].tip,
254 *((char **) menu->opt[select].data), MAX_CHAR - 1);
255 if (tmpstr != NULL)
256 {
257 free (*((char **) menu->opt[select].data));
258 *((char **) menu->opt[select].data) = tmpstr;
259 }
260 }
261 if ((menu->opt[select].flags & MB_KEYDEF) == MB_KEYDEF)
262 {
263 for (;;)
264 {
265 SDL_WaitEvent (NULL);
266 if (SDL_PollEvent (&event) && event.type == SDL_KEYDOWN)
267 {
268 *((SDLKey *) menu->opt[select].data) =
269 event.key.keysym.sym;
270 break;
271 }
272 }
273 }
274 if ((menu->opt[select].flags & MB_VOLSET) == MB_VOLSET)
275 resetVolumes ();
276 if ((menu->opt[select].flags & MB_RETURN) == MB_RETURN)
277 done = TRUE;
278
279 if (gfx->mclick)
280 Mix_PlayChannel (-1, gfx->mclick, 0);
281
282 break;
283
284 case KUP:
285 select--;
286 if (select < 0)
287 {
288 select = menu->nops - 1;
289 }
290 break;
291
292 case KDOWN:
293 select++;
294 if (select >= menu->nops)
295 select = 0;
296 break;
297
298 case KBACK:
299 select = NONE;
300 done = TRUE;
301
302 if (gfx->mback)
303 Mix_PlayChannel (-1, gfx->mback, 0);
304 continue;
305
306 case KLEFT:
307 if ((menu->opt[select].flags & MB_CHOOSE) == MB_CHOOSE
308 && menu->opt[select].nops > 0)
309 {
310 (*((int *) menu->opt[select].data))--;
311 if (*((int *) menu->opt[select].data) < 0)
312 *((int *) menu->opt[select].data) =
313 menu->opt[select].nops - 1;
314 }
315 if ((menu->opt[select].flags & MB_VOLSET) == MB_VOLSET)
316 resetVolumes ();
317 if ((menu->opt[select].flags & MB_RETURN) == MB_RETURN)
318 done = TRUE;
319
320 if (gfx->mclick)
321 Mix_PlayChannel (-1, gfx->mclick, 0);
322
323 break;
324
325 case KRIGHT:
326 if ((menu->opt[select].flags & MB_CHOOSE) == MB_CHOOSE
327 && menu->opt[select].nops > 0)
328 {
329 (*((int *) menu->opt[select].data))++;
330 if (*((int *) menu->opt[select].data) >= menu->opt[select].nops)
331 *((int *) menu->opt[select].data) = 0;
332 }
333 if ((menu->opt[select].flags & MB_VOLSET) == MB_VOLSET)
334 resetVolumes ();
335 if ((menu->opt[select].flags & MB_RETURN) == MB_RETURN)
336 done = TRUE;
337
338 if (gfx->mclick)
339 Mix_PlayChannel (-1, gfx->mclick, 0);
340
341 break;
342 case KMUP:
343 if (mouse.id == M_OVER && offset < maxoffset)
344 offset++;
345 break;
346 case KMDOWN:
347 if (mouse.id == M_OVER && offset > 0)
348 offset--;
349 break;
350 default:
351 break;
352 }
353 if (select != prevselect)
354 {
355 setFader (&mfaders[prevselect], mfaders[prevselect].value, 0,
356 MENUFADE, FALSE);
357 setFader (&mfaders[select], gfx->hlalpha, gfx->hlalpha, MENUFADE,
358 FALSE);
359 prevselect = select;
360 if (select >= maxops + offset)
361 {
362 offset = select - maxops + 1;
363 }
364 else if (select < offset)
365 {
366 offset = select;
367 }
368 }
369 if (offset < maxoffset)
370 setFader (&afaders[A_DOWN], afaders[A_DOWN].value, SDL_ALPHA_OPAQUE,
371 ABLINKTIME * gblOps.useGL + 1, FALSE);
372 else
373 setFader (&afaders[A_DOWN], afaders[A_DOWN].value,
374 SDL_ALPHA_TRANSPARENT, ABLINKTIME * gblOps.useGL + 1,
375 FALSE);
376 if (offset > 0)
377 setFader (&afaders[A_UP], afaders[A_UP].value, SDL_ALPHA_OPAQUE,
378 ABLINKTIME * gblOps.useGL + 1, FALSE);
379 else
380 setFader (&afaders[A_UP], afaders[A_UP].value, SDL_ALPHA_TRANSPARENT,
381 ABLINKTIME * gblOps.useGL + 1, FALSE);
382
383 for (i = offset; i < offset + maxops; i++)
384 {
385 updateFader (&mfaders[i], timer.ms);
386 drawMenuTOption (gfx, i, offset, &menu->opt[i], mfaders[i].value);
387 }
388 if (menu->opt[select].tip != NULL)
389 drawTip (gfx, menu->opt[select].tip);
390 drawMenuTArrows (gfx, afaders[A_UP].value, afaders[A_DOWN].value);
391 animateSprite (&(mouse.sprite[mouse.id]), timer.ms);
392 printMouse (gfx, &mouse);
393
394 FlipScreen ();
395 }
396
397 free (mfaders);
398 return select;
399 }
400
401 void
undrawTip(data_t * gfx)402 undrawTip (data_t * gfx)
403 {
404 SDL_Rect dest;
405 dest.x = gfx->tipX;
406 dest.y = gfx->tipY;
407 dest.w = gfx->tipW;
408 dest.h = gfx->tipH;
409 JPB_PrintSurface (gfx->menuBg, &dest, &dest);
410 }
411
412 void
drawMenuTArrows(data_t * gfx,int alphaUp,int alphaDown)413 drawMenuTArrows (data_t * gfx, int alphaUp, int alphaDown)
414 {
415 SDL_Rect dest;
416 gfx->upArrow->alpha = alphaUp;
417 gfx->dwArrow->alpha = alphaDown;
418 dest.x = gfx->mUpArrowX;
419 dest.y = gfx->mUpArrowY;
420 dest.w = gfx->upArrow->w;
421 dest.h = gfx->upArrow->h;
422 JPB_PrintSurface (gfx->menuBg, &dest, &dest);
423 dest.x = gfx->mDwArrowX;
424 dest.y = gfx->mDwArrowY;
425 dest.w = gfx->dwArrow->w;
426 dest.h = gfx->dwArrow->h;
427 JPB_PrintSurface (gfx->menuBg, &dest, &dest);
428 gfx->upArrow->alpha = alphaUp;
429 gfx->dwArrow->alpha = alphaDown;
430 dest.x = gfx->mUpArrowX;
431 dest.y = gfx->mUpArrowY;
432 dest.w = gfx->upArrow->w;
433 dest.h = gfx->upArrow->h;
434 JPB_PrintSurface (gfx->upArrow, NULL, &dest);
435 dest.x = gfx->mDwArrowX;
436 dest.y = gfx->mDwArrowY;
437 dest.w = gfx->dwArrow->w;
438 dest.h = gfx->dwArrow->h;
439 JPB_PrintSurface (gfx->dwArrow, NULL, &dest);
440 }
441
442 void
drawMenuT(data_t * gfx,menu_t * menu,int offset)443 drawMenuT (data_t * gfx, menu_t * menu, int offset)
444 {
445 int i;
446
447 JPB_PrintSurface (gfx->menuBg, NULL, NULL);
448
449 for (i = offset; i < offset + MIN (menu->nops, gfx->mMaxOps); i++)
450 {
451 drawMenuTOption (gfx, i, offset, &menu->opt[i], 0);
452 }
453 }
454
455 void
drawMenuTOption(data_t * gfx,int opt,int offset,opt_t * option,int alpha)456 drawMenuTOption (data_t * gfx, int opt, int offset, opt_t * option, int alpha)
457 {
458 SDL_Rect rect;
459 int capwidth;
460
461 rect.x = gfx->menuX;
462 rect.y = gfx->menuY + (opt - offset) * SFont_TextHeight (gfx->menufont);
463 rect.w = gfx->menuW;
464 rect.h = SFont_TextHeight (gfx->menufont);
465
466 JPB_PrintSurface (gfx->menuBg, &rect, &rect);
467 JPB_drawSquare (gfx->hlcolor, alpha, rect.x, rect.y, rect.w, rect.h);
468
469 if (option->flags == MB_RETURN)
470 SFont_WriteMaxWidth (gfx->menufont, rect.x + gfx->mMargin, rect.y,
471 rect.w - gfx->mMargin, gfx->mAlign, "...",
472 option->caption);
473 else
474 {
475 SFont_WriteMaxWidth (gfx->menufont, rect.x + gfx->mMargin, rect.y,
476 rect.w - gfx->mMargin, ALEFT, "...",
477 option->caption);
478 capwidth =
479 SFont_TextWidth (gfx->menufont, option->caption) + gfx->mMargin;
480 if ((option->flags & MB_INPUT) == MB_INPUT)
481 SFont_WriteMaxWidth (gfx->menufont, rect.x + capwidth, rect.y,
482 rect.w - gfx->mMargin - capwidth, ARIGHT, "...",
483 *((char **) (option->data)));
484 else if ((option->flags & MB_KEYDEF) == MB_KEYDEF)
485 SFont_WriteMaxWidth (gfx->menufont, rect.x + capwidth, rect.y,
486 rect.w - gfx->mMargin - capwidth, ARIGHT, "...",
487 SDL_GetKeyName (*((SDLKey *) option->data)));
488 else if ((option->flags & MB_CHOOSE) == MB_CHOOSE)
489 SFont_WriteMaxWidth (gfx->menufont, rect.x + capwidth, rect.y,
490 rect.w - gfx->mMargin - capwidth, ARIGHT, "...",
491 option->opcap[*((int *) option->data)]);
492 }
493 }
494
495 void
drawTip(data_t * gfx,char * tip)496 drawTip (data_t * gfx, char *tip)
497 {
498 SFont_WriteAligned (gfx->tipfont, gfx->tipX, gfx->tipY, gfx->tipW, 0,
499 gfx->tAlign, tip);
500 }
501
502 char *
inputMenu(data_t * gfx,char * tip,char * inittext,int maxWidth)503 inputMenu (data_t * gfx, char *tip, char *inittext, int maxWidth)
504 {
505 SDL_Event event;
506 SDL_Rect rect;
507 char ch = '\0';
508 char text[MAX_CHAR];
509 char *retText = NULL;
510 int len;
511 int prevUnic;
512
513 drawMenu (gfx, 0, NULL);
514
515 if (tip != NULL)
516 drawTip (gfx, tip);
517
518 sprintf (text, "%s", inittext);
519 len = strlen (text);
520 text[len] = '|';
521 text[len + 1] = '\0';
522
523 rect.x = gfx->menuX;
524 rect.y = gfx->menuY;
525 rect.w = gfx->menuW;
526 rect.h = SFont_AlignedHeight (gfx->menufont, gfx->menuW, 0, text);
527
528 //JPB_drawSquare(gfx->hlcolor, gfx->hlalpha, rect.x, rect.y, rect.w,rect.h);
529 SFont_WriteAligned (gfx->menufont, rect.x + gfx->mMargin, rect.y,
530 gfx->menuW - gfx->mMargin, 0, ACENTER, text);
531 FlipScreen ();
532
533 prevUnic = SDL_EnableUNICODE (TRUE);
534 while (ch != SDLK_RETURN)
535 {
536 while (SDL_PollEvent (&event))
537 {
538 if (event.type == SDL_KEYDOWN)
539 {
540 ch = event.key.keysym.unicode;
541
542 rect.h =
543 SFont_AlignedHeight (gfx->menufont, gfx->menuW - gfx->mMargin,
544 0, text);
545 JPB_PrintSurface (gfx->menuBg, &rect, &rect);
546
547 if ((ch > 31) || (ch == '\b'))
548 {
549 if ((ch == '\b') && (strlen (text) > 0))
550 {
551 len = strlen (text);
552 text[strlen (text) - 2] = '|';
553 text[strlen (text) - 1] = '\0';
554 }
555 else
556 {
557 len = strlen (text);
558 text[len - 1] = ch;
559 text[len] = '|';
560 text[len + 1] = '\0';
561 }
562 }
563 if (strlen (text) > maxWidth)
564 text[maxWidth] = '\0';
565
566 //JPB_drawSquare(gfx->hlcolor, gfx->hlalpha, rect.x, rect.y, rect.w,rect.h);
567 SFont_WriteAligned (gfx->menufont, rect.x + gfx->mMargin,
568 rect.y, gfx->menuW - gfx->mMargin, 0,
569 ACENTER, text);
570 FlipScreen ();
571 }
572 }
573 SDL_WaitEvent (NULL);
574 }
575 SDL_EnableUNICODE (prevUnic);
576 text[strlen (text) - 1] = '\0';
577 if ((retText = malloc (sizeof (char) * (strlen (text) + 1))) == NULL)
578 return NULL;
579 strcpy (retText, text);
580
581 return retText;
582 }
583
584 /*
585 * OLD MENU SYSTEM. (Still usefull ) ===========================================
586 */
587
588 /* These four functions are still used by the new menu system */
589
590 void
drawMenu(data_t * gfx,int nops,char ** ops)591 drawMenu (data_t * gfx, int nops, char **ops)
592 {
593 int i;
594
595 JPB_PrintSurface (gfx->menuBg, NULL, NULL);
596
597 for (i = 0; i < nops; i++)
598 {
599 drawOption (gfx, i, ops[i], 0);
600 }
601 }
602
603 void
drawOption(data_t * gfx,int opt,char * option,int alpha)604 drawOption (data_t * gfx, int opt, char *option, int alpha)
605 {
606 SDL_Rect rect;
607
608 rect.x = gfx->menuX;
609 rect.y = gfx->menuY + opt * SFont_TextHeight (gfx->menufont);
610 rect.w = gfx->menuW;
611 rect.h = SFont_TextHeight (gfx->menufont);
612
613 JPB_PrintSurface (gfx->menuBg, &rect, &rect);
614 JPB_drawSquare (gfx->hlcolor, alpha, rect.x, rect.y, rect.w, rect.h);
615
616 //SFont_Write(gfx->menufont, x, y, option);
617 SFont_WriteMaxWidth (gfx->menufont, rect.x + gfx->mMargin, rect.y,
618 rect.w - gfx->mMargin, gfx->mAlign, "...", option);
619
620 }
621
622 int
checkMenuKeys(mouse_t * mouse)623 checkMenuKeys (mouse_t * mouse)
624 {
625 SDL_Event event;
626 int ret = KIDLE;
627
628 while (SDL_PollEvent (&event))
629 {
630 switch (event.type)
631 {
632 /* A key is pressed */
633 case SDL_KEYDOWN:
634 switch (event.key.keysym.sym)
635 {
636 case SDLK_RETURN:
637 ret = KENTER;
638 break;
639 case SDLK_ESCAPE:
640 ret = KBACK;
641 break;
642 case SDLK_UP:
643 ret = KUP;
644 break;
645 case SDLK_DOWN:
646 ret = KDOWN;
647 break;
648 case SDLK_LEFT:
649 ret = KLEFT;
650 break;
651 case SDLK_RIGHT:
652 ret = KRIGHT;
653 break;
654 default:
655 break;
656 }
657 break;
658 /* A key UP. */
659 case SDL_MOUSEBUTTONDOWN:
660 switch (event.button.button)
661 {
662 case SDL_BUTTON_LEFT:
663 ret = KMENTER;
664 break;
665 case SDL_BUTTON_RIGHT:
666 ret = KBACK;
667 break;
668 case SDL_BUTTON_WHEELDOWN:
669 ret = KMUP;
670 break;
671 case SDL_BUTTON_WHEELUP:
672 ret = KMDOWN;
673 break;
674 default:
675 break;
676 }
677 break;
678 case SDL_MOUSEBUTTONUP:
679 mouse->clicked--;
680 break;
681 case SDL_KEYUP:
682 break;
683 /* Quit: */
684 case SDL_QUIT:
685 break;
686 /* Default */
687 default:
688 break;
689 }
690 }
691
692 return ret;
693 }
694
695
696 /*
697 * This has been converted to a wrapper to the new menu system so I don't have to
698 * debug and add features to two pieces of almost identical code.
699 */
700
701 /*
702 * Usage:
703 * The first value must be the number of options passed. If, additionally, you
704 * want an explanatory text appearing on top of the menu, turn this value to
705 * negative.
706 * Examples: playMenu (3, "option1", "option2", "option3");
707 * playMenu (-2, "option1", "explanation1", "option2", "explanation2");
708 */
709
710 int
playMenu(data_t * gfx,int nops,...)711 playMenu (data_t * gfx, int nops, ...)
712 {
713 va_list p;
714 char **options = NULL;
715 char **tips = NULL;
716 int i;
717 int select = 0;
718
719 va_start (p, nops);
720
721 options = malloc (sizeof (char *) * abs (nops));
722 if (nops < 0)
723 tips = malloc (sizeof (char *) * abs (nops));
724
725 for (i = 0; i < abs (nops); i++)
726 {
727 options[i] = va_arg (p, char *);
728 if (nops < 0)
729 tips[i] = va_arg (p, char *);
730 }
731 va_end (p);
732
733 select = playMenuTab (gfx, nops, options, tips);
734 free (options);
735 free (tips);
736 return select;
737 }
738
739 int
playMenuTab(data_t * gfx,int nops,char ** options,char ** tips)740 playMenuTab (data_t * gfx, int nops, char **options, char **tips)
741 {
742 menu_t menu;
743 int ret;
744 int i;
745
746 initMenuT (&menu);
747
748 for (i = 0; i < abs (nops); i++)
749 {
750 if (nops < 0)
751 addMenuTOption (&menu, options[i], tips[i], 0, NULL, NONE);
752 else
753 addMenuTOption (&menu, options[i], NULL, 0, NULL, NONE);
754 }
755
756 ret = playMenuT (gfx, &menu);
757
758 freeMenuT (&menu);
759 return ret;
760 }
761