#include <u.h>
#include <libc.h>
#include <libg.h>
#include "m.h"
extern Mouse mouse;
enum{
Margin=3, /* outside to text */
Border=2, /* outside to selection boxes */
Blackborder=1, /* width of outlining border */
Vspacing=1 /* extra spacing between lines of text */
};
Rectangle menurect(Rectangle, int);
int menusel(Rectangle r, Point p);
extern void cursorset(Point p);
int
mymenuhit(int but, Menu *menu)
{
int i, nitem, maxwid=0, lasti;
Rectangle r, menur;
Point pt;
Bitmap *b;
char *item;
for(nitem=0;
item=menu->item? menu->item[nitem] : (*menu->gen)(nitem);
nitem++){
i=strwidth(font, item);
if(i>maxwid)
maxwid=i;
}
if(menu->lasthit<0 || menu->lasthit>=nitem)
menu->lasthit=0;
r=inset(Rect(0, 0, maxwid, nitem*(font->height+Vspacing)), -Margin);
r=rsubp(r,
Pt(maxwid/2, menu->lasthit*(font->height+Vspacing)+font->height/2));
r=raddp(r, mouse.xy);
pt=Pt(0, 0);
if(r.max.x>screen.r.max.x)
pt.x=screen.r.max.x-r.max.x;
if(r.max.y>screen.r.max.y)
pt.y=screen.r.max.y-r.max.y;
if(r.min.x<screen.r.min.x)
pt.x=screen.r.min.x-r.min.x;
if(r.min.y<screen.r.min.y)
pt.y=screen.r.min.y-r.min.y;
menur=raddp(r, pt);
b=balloc(menur, screen.ldepth);
if(b == 0)
b = &screen;
bitblt(b, menur.min, &screen, menur, S);
bitblt(&screen, menur.min, &screen, menur, 0);
border(&screen, menur, Blackborder, F);
pt=Pt(menur.min.x+menur.max.x, menur.min.y+Margin);
for(i=0; i<nitem; i++, pt.y+=font->height+Vspacing){
item=menu->item? menu->item[i] : (*menu->gen)(i);
string(&screen,
Pt((pt.x-strwidth(font, item))/2, pt.y),
font, item, S);
}
lasti=-1;
r=menurect(menur, menu->lasthit);
cursorset(div(add(r.min, r.max), 2));
bitblt(&screen, r.min, &screen, r, F&~D);
while(mouse.buttons&(1<<(but-1))){
getmouse();
i=menusel(menur, mouse.xy);
if(i==lasti)
continue;
bitblt(&screen, r.min, &screen, r, F&~D);
r=menurect(menur, i);
bitblt(&screen, r.min, &screen, r, F&~D);
lasti=i;
}
bitblt(&screen, menur.min, b, menur, S);
if(b != &screen)
bfree(b);
return menu->lasthit=lasti;
}
Rectangle
menurect(Rectangle r, int i)
{
if(i<0)
return Rect(0, 0, 0, 0);
r=inset(r, Margin);
r.min.y+=(font->height+Vspacing)*i;
r.max.y=r.min.y+font->height+Vspacing;
return inset(r, Border-Margin);
}
int
menusel(Rectangle r, Point p)
{
r=inset(r, Margin);
if(!ptinrect(p, r))
return -1;
return (p.y-r.min.y)/(font->height+Vspacing);
}
|