/*
* IceBreaker
* Copyright (c) 2000-2020 Matthew Miller <mattdm@mattdm.org> and
* Enrico Tassi <gareuselesinge@infinito.it>
*
* <http://www.mattdm.org/icebreaker/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <SDL.h>
#include <stdio.h>
#include <string.h>
#include "icebreaker.h"
#include "globals.h"
#include "text.h"
#include "laundry.h"
#include "dialog.h"
#include "menu.h"
#include "sound.h"
#include "hiscore.h"
#include "options.h"
#include "fullscreen.h"
#include "themes.h"
#include "grid.h"
#include "status.h"
#include "level.h"
#include "event.h"
// fix -- this file is too big; we should split the menu stuff out
// and put it in menu.c
static PopupReturnType menuhandler(SDL_Rect menurect, int menulength, char ** menuitems, PopupReturnType (**menufunctions)(char *, int), int menuvaluetextwidth );
static void drawmenu(SDL_Rect menurect, int menulength, char ** menuitems, PopupReturnType (**menufunctions)(char *, int), int menuvaluetextwidth, int highlighted);
static PopupReturnType menuitem_newgame(char * notused, int alsonotused);
static PopupReturnType menuitem_options(char * notused, int alsonotused);
static PopupReturnType menuitem_highscores(char * notused, int alsonotused);
static PopupReturnType menuitem_help(char * notused, int alsonotused);
static PopupReturnType menuitem_quit(char * notused, int alsonotused);
static PopupReturnType menuitem_sound(char * val, int mbutton);
static PopupReturnType menuitem_autopause(char * val, int mbutton);
static PopupReturnType menuitem_fullscreen(char * val, int mbutton);
static PopupReturnType menuitem_difficulty(char * val, int mbutton);
static PopupReturnType menuitem_theme(char * val, int mbutton);
// puting this here is ugly, but it's less ugly than many of the
// alternatives -- it's very hard to switch themes on the fly
static SDL_Surface * optionsmenusave;
#define MAXMENUITEMS 10
#define MAXMENUVALUELENGTH 10
#define MAINMENULENGTH 5
PopupReturnType popuplevelmenu()
{
SDL_Rect menurect, menubuttonrect;
PopupReturnType rc;
SDL_Surface * levelmenusave;
char * mainmenu[MAINMENULENGTH] = { "NEW GAME", "OPTIONS", "HIGH SCORES", "HELP","QUIT" };
PopupReturnType (*mainmenufunctions[MAINMENULENGTH])(char *,int) = { &menuitem_newgame, &menuitem_options, &menuitem_highscores, &menuitem_help, &menuitem_quit };
menurect.w=128;
menurect.h=7+(MAINMENULENGTH*(CHARHEIGHT*2+3));
menurect.x=BORDERRIGHT-menurect.w+5;
menurect.y=BORDERBOTTOM-menurect.h+9;
menubuttonrect.x=WIDTH-(CHARWIDTH*2*4)-MARGINRIGHT-4;
menubuttonrect.y=BOTTOMSTATUSY;
menubuttonrect.w=CHARWIDTH*2*4+3;
menubuttonrect.h=CHARHEIGHT*2+3;
levelmenusave = SDL_CreateRGBSurface(SDL_SWSURFACE,menurect.w,menurect.h,screen->format->BitsPerPixel,0,0,0,0);
SDL_BlitSurface(screen, &menurect, levelmenusave, NULL);
rc=menuhandler(menurect, MAINMENULENGTH, mainmenu, mainmenufunctions, 0);
if (rc != POPUPQUITGAME)
{
if (gameflags.themechanged)
{
if (!strcmp(options.theme,"random") && rc != POPUPNEWGAME)
settheme("random");
redrawwholelevel();
drawmenubutton(&menubuttonrect,true);
gameflags.themechanged=false;
updateall();
}
else
{
SDL_BlitSurface(levelmenusave, NULL, screen, &menurect);
soil(menurect);
}
}
SDL_FreeSurface(levelmenusave);
return rc;
}
PopupReturnType menuitem_newgame(char * notused, int alsonotused)
{
return POPUPNEWGAME;
}
PopupReturnType menuitem_options(char * notused, int alsonotused)
{
SDL_Event event;
int x, y;
PopupReturnType rc=popupoptionsmenu();
if (rc!=POPUPEXITMENU)
{
return rc;
}
else
{
// add a fake event so "Options" gets un-highlighted if need be.
SDL_GetMouseState(&x,&y);
event.motion.x = x;
event.motion.y = y;
event.type = SDL_MOUSEMOTION;
SDL_PushEvent(&event);
return POPUPDONOTHING;
}
}
PopupReturnType menuitem_highscores(char * notused, int alsonotused)
{
PopupReturnType rc;
SDL_Event event;
rc=popuphighscores();
int x, y;
// add a fake event so menuitem gets un-highlighted if need be.
SDL_GetMouseState(&x,&y);
event.motion.x = x;
event.motion.y = y;
event.type = SDL_MOUSEMOTION;
SDL_PushEvent(&event);
return rc;
}
PopupReturnType menuitem_help(char * notused, int alsonotused)
{
PopupReturnType rc;
SDL_Event event;
rc=popuphelp();
int x, y;
// add a fake event so menuitem gets un-highlighted if need be.
SDL_GetMouseState(&x,&y);
event.motion.x = x;
event.motion.y = y;
event.type = SDL_MOUSEMOTION;
SDL_PushEvent(&event);
return rc;
}
PopupReturnType menuitem_quit(char * notused, int alsonotused)
{
return POPUPQUITGAME;
}
#define OPTIONSMENULENGTH 5
PopupReturnType popupoptionsmenu()
{
SDL_Rect menurect;
GameDifficultyType originaldifficulty=options.difficulty;
char originaltheme[MAXTHEMENAMELENGTH+11];
PopupReturnType rc;
int originalthemecl=false;
int recallme=false;
char * optionsmenu[OPTIONSMENULENGTH] = { "SOUND", "AUTO PAUSE", "FULL SCREEN", "DIFFICULTY", "THEME" };
PopupReturnType (*optionsmenufunctions[OPTIONSMENULENGTH])(char *,int) = { &menuitem_sound, &menuitem_autopause, &menuitem_fullscreen, &menuitem_difficulty, &menuitem_theme };
// truncation is on purpose
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
if (strlen(commandline.theme)>0)
{
snprintf(originaltheme,MAXTHEMENAMELENGTH+1,"%s",commandline.theme);
originalthemecl=true;
}
else
{
snprintf(originaltheme,MAXTHEMENAMELENGTH+1,"%s",options.theme);
originalthemecl=false;
}
#pragma GCC diagnostic pop
menurect.w=229;
menurect.h=7+(OPTIONSMENULENGTH*(CHARHEIGHT*2+3));
menurect.x=BORDERRIGHT-menurect.w+10;
menurect.y=BORDERBOTTOM-menurect.h+9-((CHARHEIGHT*2+4)*4)-2;
optionsmenusave = SDL_CreateRGBSurface(SDL_SWSURFACE,menurect.w,menurect.h,screen->format->BitsPerPixel,0,0,0,0);
SDL_BlitSurface(screen, &menurect, optionsmenusave, NULL);
rc=menuhandler(menurect, OPTIONSMENULENGTH, optionsmenu, optionsmenufunctions, 84);
if (rc==POPUPEXITMENU)
{
if ((originalthemecl && strcmp(commandline.theme, originaltheme)) ||
(!originalthemecl && strcmp(options.theme, originaltheme)) )
{
gameflags.themechanged=true;
}
}
if (rc==POPUPEXITMENU && options.difficulty != originaldifficulty)
{
if (checkiflevelatstart())
{
rc=POPUPNEWGAME;
}
else
{
switch (yesnodialog("Changing difficulty","requires restart.","End this game?"))
{
case POPUPQUITGAME:
rc=POPUPQUITGAME;
break;
case POPUPYES:
rc=POPUPNEWGAME;
break;
case POPUPNO:
options.difficulty=originaldifficulty; // put things back. :)
recallme=true;
break;
default:
fprintf(stderr,"Internal weirdness: yes/no dialog box returned something other than yes or no.\n"
"That shouldn't ever happen.\n");
break;
}
}
}
//writeoptions(); // probably no need to do this until exit
// and restore the background
if (rc != POPUPQUITGAME)
{
SDL_BlitSurface(optionsmenusave, NULL, screen, &menurect);
soil(menurect);
}
SDL_FreeSurface(optionsmenusave);
if (recallme) rc=popupoptionsmenu(); // this is a bit sick.
return rc;
}
PopupReturnType menuitem_sound(char * val, int mbutton)
{
if (strlen(val)==0)
{
if (gameflags.soundsystemworks)
{
if (options.sound==SOUNDON)
strncpy(val,"on",MAXMENUVALUELENGTH);
else
strncpy(val,"off",MAXMENUVALUELENGTH);
}
else
{
strncpy(val,"n/a",MAXMENUVALUELENGTH);
}
return POPUPDONOTHING;
}
else
{
if (!gameflags.soundsystemworks) return POPUPDONOTHING;
if (options.sound==SOUNDON)
{
options.sound=SOUNDOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
}
else
{
options.sound=SOUNDON;
strncpy(val,"on",MAXMENUVALUELENGTH);
}
return POPUPREDRAWME;
}
}
PopupReturnType menuitem_autopause(char * val, int mbutton)
{
if (strlen(val)==0)
{
if (options.autopause==AUTOPAUSEON)
strncpy(val,"on",MAXMENUVALUELENGTH);
else
strncpy(val,"off",MAXMENUVALUELENGTH);
return POPUPDONOTHING;
}
else
{
if (options.autopause==AUTOPAUSEON)
{
options.autopause=AUTOPAUSEOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
}
else
{
options.autopause=AUTOPAUSEON;
strncpy(val,"on",MAXMENUVALUELENGTH);
}
return POPUPREDRAWME;
}
}
PopupReturnType menuitem_fullscreen(char * val, int mbutton)
{
// fix -- cope with failure to switch
if (strlen(val)==0)
{
switch (options.fullscreen)
{
case FULLSCREENOFF:
strncpy(val,"off",MAXMENUVALUELENGTH);
break;
case FULLSCREENON:
strncpy(val,"on",MAXMENUVALUELENGTH);
break;
case FULLSCREENALWAYS:
strncpy(val,"always",MAXMENUVALUELENGTH);
break;
case FULLSCREENUNKNOWN: // this should never happen!
strncpy(val,"???",MAXMENUVALUELENGTH);
break;
}
return POPUPDONOTHING;
}
else
{
if (mbutton==1 || mbutton==4) // left or scroll forwards
{
switch (options.fullscreen)
{
case FULLSCREENOFF:
options.fullscreen=FULLSCREENON;
strncpy(val,"on",MAXMENUVALUELENGTH);
makefullscreen();
break;
case FULLSCREENON:
options.fullscreen=FULLSCREENALWAYS;
strncpy(val,"always",MAXMENUVALUELENGTH);
break;
case FULLSCREENALWAYS:
options.fullscreen=FULLSCREENOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
makewindowed();
break;
case FULLSCREENUNKNOWN: // this should never happen!
options.fullscreen=FULLSCREENOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
makewindowed();
break;
}
}
else // right or middle or scroll back
{
switch (options.fullscreen)
{
case FULLSCREENOFF:
options.fullscreen=FULLSCREENALWAYS;
strncpy(val,"always",MAXMENUVALUELENGTH);
makefullscreen();
break;
case FULLSCREENON:
options.fullscreen=FULLSCREENOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
makewindowed();
break;
case FULLSCREENALWAYS:
options.fullscreen=FULLSCREENON;
strncpy(val,"on",MAXMENUVALUELENGTH);
break;
case FULLSCREENUNKNOWN: // this should never happen!
options.fullscreen=FULLSCREENOFF;
strncpy(val,"off",MAXMENUVALUELENGTH);
makewindowed();
break;
}
}
return POPUPREDRAWME;
}
}
PopupReturnType menuitem_difficulty(char * val, int mbutton)
{
if (strlen(val)==0)
{
switch (options.difficulty)
{
case NORMAL:
strncpy(val,"normal",MAXMENUVALUELENGTH);
break;
case EASY:
strncpy(val,"easy",MAXMENUVALUELENGTH);
break;
case HARD:
strncpy(val,"hard",MAXMENUVALUELENGTH);
break;
}
return POPUPDONOTHING;
}
else
{
if (mbutton==1 || mbutton==4) // left or scroll forwards
{
switch (options.difficulty)
{
case NORMAL:
options.difficulty=EASY;
strncpy(val,"easy",MAXMENUVALUELENGTH);
break;
case EASY:
options.difficulty=HARD;
strncpy(val,"hard",MAXMENUVALUELENGTH);
break;
case HARD:
options.difficulty=NORMAL;
strncpy(val,"normal",MAXMENUVALUELENGTH);
break;
}
}
else // right or middle or scroll back
{
switch (options.difficulty)
{
case NORMAL:
options.difficulty=HARD;
strncpy(val,"hard",MAXMENUVALUELENGTH);
break;
case EASY:
options.difficulty=NORMAL;
strncpy(val,"normal",MAXMENUVALUELENGTH);
break;
case HARD:
options.difficulty=EASY;
strncpy(val,"easy",MAXMENUVALUELENGTH);
break;
}
}
return POPUPREDRAWME;
}
}
PopupReturnType menuitem_theme(char * val, int mbutton)
{
char** themelist;
int t;
int themecount;
SDL_Rect tmprect;
// FIX -- this is kind of kludgy -- why define this twice?
char * mainmenu[MAINMENULENGTH] = { "NEW GAME", "OPTIONS", "HIGH SCORES", "HELP","QUIT" };
// fix -- all of these are also stupidly duplicated
SDL_Rect mainmenurect;
SDL_Rect optionsmenurect;
SDL_Rect menubuttonrect;
mainmenurect.w=128;
mainmenurect.h=7+(MAINMENULENGTH*(CHARHEIGHT*2+3));
mainmenurect.x=BORDERRIGHT-mainmenurect.w+5;
mainmenurect.y=BORDERBOTTOM-mainmenurect.h+9;
optionsmenurect.w=229;
optionsmenurect.h=7+(OPTIONSMENULENGTH*(CHARHEIGHT*2+3));
optionsmenurect.x=BORDERRIGHT-optionsmenurect.w+10;
optionsmenurect.y=BORDERBOTTOM-optionsmenurect.h+9-((CHARHEIGHT*2+4)*4)-2;
menubuttonrect.x=WIDTH-(CHARWIDTH*2*4)-MARGINRIGHT-4;
menubuttonrect.y=BOTTOMSTATUSY;
menubuttonrect.w=CHARWIDTH*2*4+3;
menubuttonrect.h=CHARHEIGHT*2+3;
if (strlen(val)==0)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-truncation"
if (strlen(commandline.theme)>0)
strncpy(val,commandline.theme,MAXMENUVALUELENGTH);
else
strncpy(val,options.theme,MAXMENUVALUELENGTH);
return POPUPDONOTHING;
#pragma GCC diagnostic pop
}
else
{
themecount=getthemenames(&themelist);
if (strlen(commandline.theme)>0)
{
t=getthemenumber(themelist,themecount,commandline.theme);
// once we've changed the theme, there's no going back
*(commandline.theme)='\0'; // makes this ""
}
else
{
t=getthemenumber(themelist,themecount,options.theme);
}
if (((mbutton==1 || mbutton==4) && t==themecount-1) || ((mbutton!=1 && mbutton!=4) && t==0))
{ // "random", at the end/beginning of the list
strncpy(val,"random",MAXMENUVALUELENGTH);
snprintf(options.theme,MAXMENUVALUELENGTH,"random");
settheme("linux"); // just for pretty
redrawwholelevel();
drawmenu(mainmenurect, MAINMENULENGTH, mainmenu, NULL, 0, 1);
drawmenubutton(&menubuttonrect,true);
puttext((WIDTH-gettextwidth(10,"?"))/2,(HEIGHT-CHARHEIGHT*10)/2,10,color.gameovertext,"?");
gameflags.themechanged=true;
}
else
{
if (mbutton==1 || mbutton==4) // left click or scroll forwards
{
strncpy(val,themelist[(t+1)%themecount],MAXMENUVALUELENGTH);
snprintf(options.theme,MAXMENUVALUELENGTH,"%s",themelist[(t+1)%themecount]);
}
else // right or middle or scroll back
{
if (t<0) t=themecount;
strncpy(val,themelist[(t-1)%themecount],MAXMENUVALUELENGTH);
snprintf(options.theme,MAXMENUVALUELENGTH,"%s",themelist[(t-1)%themecount]);
}
settheme(options.theme);
redrawwholelevel();
drawmenu(mainmenurect, MAINMENULENGTH, mainmenu, NULL, 0, 1);
drawmenubutton(&menubuttonrect,true);
}
SDL_BlitSurface(screen, &optionsmenurect, optionsmenusave, NULL);
freethemenames(&themelist,themecount);
tmprect.w=WIDTH; tmprect.h=HEIGHT;
tmprect.x=0;tmprect.y=0;
soil(tmprect);
return POPUPDONOTHING;
}
}
/* displays a menu; takes a rect for position and size, the length of the
* menu, an array of menu items, an array of pointers to functions for
* each menu item (functions should return type MenuReturnType
* indicating what to do when the item is clicked) and a flag telling whether
* menu items are option/value pairs.
*/
PopupReturnType menuhandler(SDL_Rect menurect, int menulength, char ** menuitems, PopupReturnType (**menufunctions)(char *, int), int menuvaluetextwidth)
{
SDL_Rect insiderect;
SDL_Rect menuitemrect[MAXMENUITEMS];
char menuvalues[MAXMENUITEMS][MAXMENUVALUELENGTH];
int menuitemglow=-1;
int menuitempressed=false;
SDL_Event event;
PopupReturnType rc=POPUPDONOTHING;
int redrawmenuflag=false;
int domenuitemflag=false;
Uint8 domenuitembutton=0;
int i;
int tmpx, tmpy;
SDL_EnableKeyRepeat(500,90);
insiderect.w=menurect.w-2;
insiderect.h=menurect.h-2;
insiderect.x=menurect.x+1;
insiderect.y=menurect.y+1;
// fix -- use drawmenu() here?
SDL_FillRect(screen,&menurect,color.gridline);
SDL_FillRect(screen,&insiderect,color.background);
// find current option values
for (i=0;i<menulength;i++)
{
menuitemrect[i].x=insiderect.x;
menuitemrect[i].y=insiderect.y+2+(i*(CHARHEIGHT*2+3));
menuitemrect[i].w=insiderect.w;
menuitemrect[i].h=(CHARHEIGHT*2)+3;
puttext(menuitemrect[i].x+5,menuitemrect[i].y+3,2,color.normaltext,menuitems[i]);
strncpy(menuvalues[i],"",MAXMENUVALUELENGTH);
if (menuvaluetextwidth)
{
if (menufunctions!=NULL && menufunctions[i]!=NULL)
(*menufunctions[i])(menuvalues[i],0);
puttext(menuitemrect[i].x+menuitemrect[i].w-menuvaluetextwidth,menuitemrect[i].y+3,2,color.normaltext,menuvalues[i]);
}
}
soil(menurect);
clean(); // fix -- any point in not doing this first thing in the
// loop and removing the clean at the bottom of the loop?
do
{
SDL_WaitEvent(NULL); // no new CPU cooler needed. :)
while (pollevent(&event))
{
if (event.type == SDL_QUIT)
{
rc=POPUPQUITGAME;
}
else if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.x>menurect.x &&
event.button.y>menurect.y &&
event.button.x<menurect.x + menurect.w &&
event.button.y<menurect.y + menurect.h)
{
if (event.button.button == 1 || menuvaluetextwidth) // we only care about right clicks on items with options
{
if (event.button.y-menurect.y>=3)
if (menuitemglow!=(event.button.y-(menurect.y+3))/(CHARHEIGHT*2+3))
{
menuitemglow=(event.button.y-(menurect.y+3))/(CHARHEIGHT*2+3);
redrawmenuflag=true;
}
if (menuitemglow>=menulength)
menuitemglow=-1;
else
menuitempressed=true;
}
}
else
{
rc=POPUPEXITMENU;
}
}
else if (event.type == SDL_MOUSEBUTTONUP)
{
if (menuitempressed && (event.button.button == 1 || menuvaluetextwidth)) // again, we only care about right clicks on items with options
{
// in area, button was down
if (event.motion.x>menurect.x &&
event.motion.y>(menurect.y + 2) &&
event.motion.x<menurect.x + menurect.w &&
event.motion.y<menurect.y + menurect.h - 2)
{
if (menufunctions!=NULL && menufunctions[menuitemglow]!=NULL)
{
domenuitemflag=true;
domenuitembutton=event.button.button;
}
}
menuitempressed=false;
}
}
else if (event.type == SDL_MOUSEMOTION)
{
// are we in the menu area?
if (event.motion.x>menurect.x &&
event.motion.y>(menurect.y + 2) &&
event.motion.x<menurect.x + menurect.w &&
event.motion.y<menurect.y + menurect.h - 2)
{
menuitemglow=(event.motion.y-(menurect.y+3))/(CHARHEIGHT*2+3);
if (menuitemglow>=menulength) menuitemglow=-1;
redrawmenuflag=true;
}
else
{
if (menuitemglow != -1 && !menuitempressed)
{
menuitemglow=-1;
redrawmenuflag=true;
}
}
}
else if (event.type==SDL_KEYDOWN)
{
switch(translatekeyevent(&event))
{
case KEYMENU: // falls through
case KEYCANCEL:
rc=POPUPEXITMENU;
case KEYMOVEUP:
if (!menuitempressed)
{
menuitemglow--;
if (menuitemglow<0) menuitemglow=menulength-1;
redrawmenuflag=true;
}
break;
case KEYMOVEDOWN:
if (!menuitempressed)
{
menuitemglow++;
if (menuitemglow>=menulength) menuitemglow=0;
redrawmenuflag=true;
}
break;
case KEYSTARTLINE:
if (menuitemglow!=-1 && menufunctions!=NULL && menufunctions[menuitemglow]!=NULL)
{
domenuitemflag=true;
domenuitembutton=1;
}
break;
case KEYSWITCHLINE:
if (menuvaluetextwidth && menuitemglow!=-1 && menufunctions!=NULL && menufunctions[menuitemglow]!=NULL)
{
domenuitemflag=true;
domenuitembutton=2;
}
break;
case KEYMOVERIGHT:
if (menuvaluetextwidth && menuitemglow!=-1 && menufunctions!=NULL && menufunctions[menuitemglow]!=NULL)
{
domenuitemflag=true;
domenuitembutton=1;
}
break;
case KEYMOVELEFT:
if (menuvaluetextwidth && menuitemglow!=-1 && menufunctions!=NULL && menufunctions[menuitemglow]!=NULL)
{
domenuitemflag=true;
domenuitembutton=2;
}
break;
default:
break;
}
}
}
if (domenuitemflag)
{
// this calls the menu functions, in case that's not obvious
rc=(*menufunctions[menuitemglow])(menuvalues[menuitemglow],domenuitembutton);
domenuitemflag=false;
redrawmenuflag=true;
}
if (rc==POPUPREDRAWME)
{
rc=POPUPDONOTHING;
redrawmenuflag=true;
}
if (redrawmenuflag)
{
SDL_FillRect(screen,&menurect,color.gridline);
SDL_FillRect(screen,&insiderect,color.background);
for (i=0;i<menulength;i++)
{
if (i == menuitemglow)
{
SDL_FillRect(screen,&menuitemrect[i],color.menuhighlight);
puttext(menuitemrect[i].x+5,menuitemrect[i].y+3,2,color.background,menuitems[i]);
if (menuvaluetextwidth) puttext(menuitemrect[i].x+menuitemrect[i].w-menuvaluetextwidth,menuitemrect[i].y+3,2,color.background,menuvalues[i]);
}
else
{
puttext(menuitemrect[i].x+5,menuitemrect[i].y+3,2,color.normaltext,menuitems[i]);
if (menuvaluetextwidth) puttext(menuitemrect[i].x+menuitemrect[i].w-menuvaluetextwidth,menuitemrect[i].y+3,2,color.normaltext,menuvalues[i]);
}
}
soil(menurect);
redrawmenuflag=false;
}
clean();
} while (rc==POPUPDONOTHING);
// a fake event to update things that depend on mouse position
SDL_GetMouseState(&tmpx,&tmpy);
event.motion.x = tmpx;
event.motion.y = tmpy;
event.type = SDL_MOUSEMOTION;
SDL_PushEvent(&event);
SDL_EnableKeyRepeat(0,0);
return(rc);
}
void drawmenu(SDL_Rect menurect, int menulength, char ** menuitems, PopupReturnType (**menufunctions)(char *, int), int menuvaluetextwidth, int highlighted)
{
SDL_Rect insiderect;
SDL_Rect menuitemrect[MAXMENUITEMS];
char menuvalues[MAXMENUITEMS][MAXMENUVALUELENGTH];
int i;
insiderect.w=menurect.w-2;
insiderect.h=menurect.h-2;
insiderect.x=menurect.x+1;
insiderect.y=menurect.y+1;
SDL_FillRect(screen,&menurect,color.gridline);
SDL_FillRect(screen,&insiderect,color.background);
for (i=0;i<menulength;i++)
{
menuitemrect[i].x=insiderect.x;
menuitemrect[i].y=insiderect.y+2+(i*(CHARHEIGHT*2+3));
menuitemrect[i].w=insiderect.w;
menuitemrect[i].h=(CHARHEIGHT*2)+3;
strncpy(menuvalues[i],"",MAXMENUVALUELENGTH);
if (i == highlighted)
{
SDL_FillRect(screen,&menuitemrect[i],color.menuhighlight);
puttext(menuitemrect[i].x+5,menuitemrect[i].y+3,2,color.background,menuitems[i]);
if (menuvaluetextwidth) // get option value
{
if (menufunctions!=NULL && menufunctions[i]!=NULL)
(*menufunctions[i])(menuvalues[i],0);
puttext(menuitemrect[i].x+menuitemrect[i].w-menuvaluetextwidth,menuitemrect[i].y+3,2,color.background,menuvalues[i]);
}
}
else
{
puttext(menuitemrect[i].x+5,menuitemrect[i].y+3,2,color.normaltext,menuitems[i]);
if (menuvaluetextwidth)
{
if (menufunctions!=NULL && menufunctions[i]!=NULL)
(*menufunctions[i])(menuvalues[i],0);
puttext(menuitemrect[i].x+menuitemrect[i].w-menuvaluetextwidth,menuitemrect[i].y+3,2,color.normaltext,menuvalues[i]);
}
}
}
soil(menurect);
clean();
}
void drawmenubutton(SDL_Rect* mbrect,int highlighted)
{
if (highlighted)
{
SDL_FillRect(screen,mbrect,color.menuhighlight);
puttext(mbrect->x+3,mbrect->y+3,2,color.background,"MENU");
}
else
{
SDL_FillRect(screen,mbrect,color.background);
puttext(mbrect->x+3,mbrect->y+3,2,color.normaltext,"MENU");
}
soil(*mbrect);
}