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