h64390
s 00000/00001/00379
d D 1.4 91/03/08 05:41:47 hopkins 4 3
c removed white space
e
s 00005/00004/00375
d D 1.3 91/03/08 05:40:22 hopkins 3 2
c fixed defaultindex to ask the menu instead of looking at the items
c (the user may haved changed it with the control key)
e
s 00005/00005/00374
d D 1.2 91/03/08 05:20:41 hopkins 2 1
c Fixed /setallcolors and /stealallcolors to take 7 args instead of 5
e
s 00379/00000/00000
d D 1.1 91/03/08 04:40:32 hopkins 1 0
c date and time created 91/03/08 04:40:32 by hopkins
e
u
U
f e 0
t
T
I 1
#include
/********************************************************************
* Parameters
*/
any *list = [null,MCOMMAND];
persist(list);
/********************************************************************
* The tnt menu
*/
typedef struct TNTmenu TNTmenu;
struct TNTmenu {
void setlabel(displayitem);
void appenditem(any *);
void setvisualstate(int,name);
void stealallcolors(object);
void settarget(any);
void setnotifier(name nm);
void setchoicemode(name nm);
void setdefault(int d);
void setitemlist(any *);
void setpinnable(boolean);
void qvalidate();
void open_pinned(canvastype);
void close_pinned();
float width();
float height();
char *itemstring(int i);
};
extern struct {
TNTmenu new(name,canvastype);
} ClassHNMenu;
TNTmenu tntmn = null;
object menutarget = null;
#postscript
/ClassHNCommandMenu ClassCommandMenu []
classbegin
/ExecuteNotifier { % value notifier --
self /notify /target self send send
} def
/itemstring { % i -- str|null
/item self send {
dup isarray? {0 get} {exit} ifelse
} loop dup type /stringtype ne {pop null} if
} def
/width {/size self send pop} def
/height {/size self send exch pop} def
classend def
/ClassHNSettingsMenu ClassSettingsMenu []
classbegin
/ExecuteNotifier { % value notifier --
dup null ne {
self /notify /target self send send
} {
/ExecuteNotifier super send
} ifelse
} def
/itemstring { % i -- str|null
/item self send {
dup isarray? {0 get} {exit} ifelse
} loop dup type /stringtype ne {pop null} if
} def
/width {/size self send pop} def
/height {/size self send exch pop} def
classend def
/ClassHNMenu ClassMenu []
classbegin
/ClassCommandMenu ClassHNCommandMenu def
/ClassSettingsMenu ClassHNSettingsMenu def
/qvalidate {/?validate super send} def
/width {/size self send pop} def
/height {/size self send exch pop} def
/open_pinned { % canvas --
dup /setinvoker self send
PinnedCopy null ne {
/map PinnedCopy send
/totop PinnedCopy send
} if
0 1 /itemcount self send 1 sub {
/item self send dup isarray? {
dup length 2 eq {
1 get dup type /canvastype eq {
2 copy /open_pinned exch send
} if
} if
} if pop
} for pop
} def
/close_pinned {
PinnedCopy null ne {
/unmap PinnedCopy send
} if
0 1 /itemcount self send 1 sub {
/item self send dup isarray? {
dup length 2 eq {
1 get dup type /canvastype eq {
/close_pinned 1 index send
} if
} if
} if pop
} for
} def
D 2
/setallcolors { % c1 c2 c3 c4 c5 --
5 copy /setallcolors super send
E 2
I 2
/setallcolors { % c1 c2 c3 c4 c5 c6 c7 --
7 copy /setallcolors super send
E 2
0 1 /itemcount self send 1 sub {
/item self send dup isarray? {
dup length 2 eq {
1 get dup type /canvastype eq {
D 2
6 copy /setallcolors exch send
E 2
I 2
8 copy /setallcolors exch send
E 2
} if
} if
} if pop
} for
D 2
pop pop pop pop pop
E 2
I 2
pop pop pop pop pop pop pop
E 2
} def
/stealallcolors { % object
D 2
{FG BG0 BG BG2 BG3} exch send /setallcolors self send
E 2
I 2
{2DFG 2DBG FG BG0 BG BG2 BG3} exch send /setallcolors self send
E 2
} def
classend def
currentdict /ClassHNCommandMenu undef
currentdict /ClassHNSettingsMenu undef
#end
/********************************************************************
* Create TNTmenu
*/
int nritems(any *l)
{
return (length(l) - MHLEN) / MFLEN;
}
any *getheader(any *l)
{
return getinterval(l,0,MHLEN);
}
any *getitem(any *l,int i)
{
return getinterval(l,MHLEN + (i * MFLEN),MFLEN);
}
TNTmenu createtntmenu(any *l)
{
int df;
any *d;
TNTmenu m;
int n;
gsave();
setcanvas(framebuffer);
d = getheader(l);
m = ClassHNMenu.new(/Grid,framebuffer);
if ((int)d[MHSTATE] & MEXCLUSIVE)
m.setchoicemode(/Exclusive);
else if ((int)d[MHSTATE] & MNONEXCLUSIVE)
m.setchoicemode(/NonExclusive);
if ((int)d[MHSTATE] & MPIN)
m.setpinnable(true);
m.setlabel(d[MHLABEL]);
m.settarget(soften(self));
m.setnotifier(/MenuAction);
df = -1;
for (n = 0 ; n < nritems(l) ; n++) {
d = getitem(l,n);
switch (truedicttype(d[MFACTION])) {
case /packedarraytype:
case /arraytype:
m.appenditem([d[MFLABEL],
createtntmenu((any *)d[MFACTION])]);
break;
case /nametype:
m.appenditem([d[MFLABEL],d[MFACTION]]);
break;
case /nulltype:
m.appenditem([d[MFLABEL]]);
break;
}
if ((int)d[MFSTATE] & MINACTIVE)
m.setvisualstate(n,/InActive);
if ((int)d[MFSTATE] & MDEFAULT)
df = n;
}
if (df >= 0)
m.setdefault(df);
m.qvalidate();
grestore();
return m;
}
any validate()
{
if (tntmn)
return tntmn;
else
return tntmn = createtntmenu(list);
}
/********************************************************************
* manipulating the menu list
*/
void setmenu(any *l)
{
list = l;
unpromote(/tntmn);
}
#postscript
/DIString /DIString load def
#end
char *itemstring(int i)
{
return DIString(list[(i * MFLEN) + MHLEN]);
}
int defaultindex(any *l)
{
int n, i;
D 3
for (n = 0, i = MHLEN + MFSTATE ; i < length(l) ; n++, i += MFLEN)
if ((int)l[i] & MDEFAULT)
return n;
return -1;
E 3
I 3
D 4
E 4
if ((n = tntmn.default()) == null)
return -1;
else
return (n);
E 3
}
boolean defaultactive()
{
int n = defaultindex(list);
return (n >= 0) && (!((int)list[(n * MFLEN) + MHLEN + MFSTATE] & MINACTIVE));
}
displayitem defaultitem()
{
int n = defaultindex(list);
if (n < 0)
return null;
else
return (displayitem)list[(n * MFLEN) + MHLEN + MFLABEL];
}
/********************************************************************
* Notification
*/
eventtype track_evt = null;
void notify(any i, name message, TNTmenu m)
{
int *a;
switch (type(i)) {
case /arraytype:
case /packedarraytype:
a = (int *)i;
PdBSend([a[1],i,m.itemstring(a[0])],message,menutarget);
case /integertype:
PdBSend([true,i,m.itemstring((int)i)],message,menutarget);
break;
}
}
void execdefault0(any *l, object t)
{
int i = defaultindex(l);
any *d;
if (i >= 0) {
d = getitem(l,i);
switch (truedicttype(d[MFACTION])) {
case /packedarraytype:
case /arraytype:
execdefault0((any *)d[MFACTION],t);
break;
case /nametype:
PdBSend([true,i,DIString(d[MFLABEL])],(name)d[MFACTION],t);
break;
default:
PdBSend([true,i,DIString(d[MFLABEL])],/MenuAction,t);
break;
}
}
}
void execdefault(object t)
{
execdefault0(list,t);
}
/********************************************************************
* show menu
*/
void show_menu_pos(object t,name pos)
{
menutarget = (object)soften(t);
track_evt = (eventtype)currentprocess[/track_evt];
tntmn.stealallcolors(t);
currentprocess[/menumenu] = tntmn;
currentprocess[/menuposname] = pos;
breakpoint();
undef((dicttype)currentprocess,/menumenu);
undef((dicttype)currentprocess,/menuposname);
undef((dicttype)currentprocess,/menuok);
undef((dicttype)currentprocess,/track_evt);
}
void showmenu(object t)
{
if (known((dicttype)currentprocess,/menuok)) {
validate();
show_menu_pos(t,/Default);
}
}
void showmenuS(object t, float X, float Y)
{
if (known((dicttype)currentprocess,/menuok)) {
validate();
mouseevent.XLocation = X - (tntmn.width()/2);
mouseevent.YLocation = Y;
show_menu_pos(t,/NorthWest);
}
}
void showmenuE(object t, float X, float Y)
{
if (known((dicttype)currentprocess,/menuok)) {
validate();
mouseevent.XLocation = X;
mouseevent.YLocation = Y;
setcursorlocation(X,Y);
show_menu_pos(t,/NorthWest);
}
}
void showmenuSE(object t, float X, float Y)
{
if (known((dicttype)currentprocess,/menuok)) {
validate();
mouseevent.XLocation = X;
mouseevent.YLocation = Y;
show_menu_pos(t,/NorthWest);
}
}
/********************************************************************
* owner
*/
void owner_close()
{
if (promoted(/tntmn))
tntmn.close_pinned();
}
void owner_open()
{
if (promoted(/tntmn))
tntmn.open_pinned(cv);
}
E 1