ref: 07469015a833ea56db430aed28f004e205549360
dir: /menu.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <mouse.h>
#include <keyboard.h>
#include <cursor.h>
#include "dat.h"
#include "fns.h"
extern Mousectl *mc;
extern Cursor targetcursor;
/* FIXME: safer: Menu struct with menu state: default, build, etc. */
Tile *selected;
int (*selectfn)(Tile *);
Menuptr menufn;
typedef struct Gmenu Gmenu;
struct Gmenu{
char *name;
int (*checkfn)(Tile*);
Menuptr (*initfn)(Tile*);
int (*selectfn)(Tile*);
};
enum{
Gmenubuild,
Gmenuend,
};
static Gmenu actions[Gmenuend] = {
[Gmenubuild] {"build", isbuildable, buildmenu},
};
static Gmenu *favail[nelem(actions)];
static int navail;
extern Rectangle scrwin;
void
gsetcursor(int curs)
{
Cursor *c;
switch(curs){
case Curstarget: c = &targetcursor; break;
case Cursdef: /* wet floor */
default: c = nil; break;
}
setcursor(mc, c);
}
static char *
genmenu(int n)
{
return n < navail ? favail[n]->name : nil;
}
static Menu menu = {0, genmenu};
static Menuptr
setmenu(Tile *t)
{
int n;
Gmenu *f;
memset(favail, 0, sizeof favail);
navail = 0;
for(f=actions; f<actions+nelem(actions); f++)
if(f->checkfn == nil || f->checkfn(t))
favail[navail++] = f;
if(navail == 0)
return nil;
if((n = menuhit(3, mc, &menu, nil)) < 0)
return nil;
return favail[n]->initfn(t);
}
void
actionmenu(Point p)
{
Tile *t;
t = p2t(p);
assert(t != nil);
selected = t;
if(menufn == nil){
menufn = setmenu(t);
if(menufn == nil)
deselect();
}else if(menufn(t) < 0)
deselect();
}
void
mouseselect(Point p)
{
selected = p2t(p);
if(selectfn != nil && selectfn(selected) < 0)
deselect();
}
void
deselect(void)
{
selected = nil;
menufn = nil;
mapdrawfn = nil;
selectfn = nil;
gsetcursor(Cursdef);
repaint = 1;
}