/*
 *
 * Calculus een simpel calculatortje
 *
 * bye Simon Bruin
 */

/*	(voor een mooie listning de tab van de editor of printer instellen
	 op 4 spaties in plaats van 8 */

#include "Calc.h"

#define	VERSIE	"3.3"

int do_bit();

#define	pen1	0	/* 0 = donker groen	*/
#define pen2	1	/* 1 = wit			*/
#define pen3	2	/* 2 = groen		*/
#define pen4	3	/* 3 = licht groen	*/
#define NL	NULL

USHORT	chip knop[]={
		0x7FFF,0xF800,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0xC000,0x0C00,
		0x7FFF,0xF800 };

USHORT	chip cknop[]={
		0xFFFF,0xFFC0,
		0xC000,0x00C0,
		0xC000,0x00C0,
		0xFFFF,0xFFC0,
		0xCCCC,0xCCC0,
		0xFFFF,0xFFC0,
		0xCCCC,0xCCC0,
		0xFFFF,0xFFC0,
		0xCCCC,0xCCC0,
		0xFFFF,0xFFC0 };

USHORT	chip knopb[]={
		0x7FFF,0xFFF8,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0xC000,0x000C,
		0x7FFF,0xFFF8 };

struct	Image toets = { -1,-1, 22, 11, 1, knop, 1, 2, NL };

struct	Image toetsb = { -1,-1, 30, 11, 1, knopb, 1, 2, NL };

struct	Image ctoets = { 0, 0, 26, 10, 1, cknop, 1, 2, NL };

struct	Image balk = { 0, 1, 264, 2, 1, NL, 2, 1, NL };

#define	text(x)	{ pen2, pen3, JAM1, 2, 1, NL, (UBYTE *)x, NL }

struct	IntuiText ttxt[35] = {
	text(" 0"), text(" 1"), text(" 2"), text(" 3"),
	text(" 4"), text(" 5"), text(" 6"), text(" 7"),
	text(" 8"), text(" 9"), text(" A"), text(" B"),
	text(" C"), text(" D"), text(" E"), text(" F"),
	text(" ."), text(" *"), text(" /"), text(" %"),
	text(" +"), text(" -"), text("<<"), text(">>"),
	text("+-"), text(" &"), text(" ^"), text(" |"),
	text(" ="), text(" ("), text(" )"), text(" F"),
	text("Gr"), text("CA"), text(" C") };

struct	IntuiText etxt[21] = {
	text("Sin"), text("ArS"), text("HbS"),
	text("Cos"), text("ArC"), text("HbC"),
	text("Tan"), text("ArT"), text("HbT"),
	text("Log"), text("Exp"), text("Pow"),
	text("Sqr"), text(" Pi"), text("Msp"),
	text(">R<"), text("<R>"), text("Min"),
	text(" Mr"), text(" M-"), text(" M+") };

struct IntuiText btxt[3] = {
	text(" <"), text(" >"),{ pen2,pen3,JAM2,2,1,NL," 0",NL } };

struct IntuiText htxt = { pen2,pen3,JAM2,2,1,NL," D",NL };
struct IntuiText ltxt = { pen2,pen3,JAM2,2,1,NL,"Db",NL };

char	hh[]="DHB";
char	ll[]="DbSi";
char	ff[]="FI";
char	gtl[32] =
	"0123456789abcdef.*/%+-<>#&!^=()";

#define	gnum	0
#define	breedte	268
#define	hogte	119
#define x1	8
#define x2	34
#define	x3	60
#define x4	86
#define	x5	112
#define x6	138
#define x7	164
#define x8	198
#define x9	232

#define	y1	13
#define y2	26
#define y3	39
#define y4	52
#define	y5	65
#define y6	78
#define y7	91
#define	y8	104

#define Gn	GADGIMMEDIATE|RELVERIFY,BOOLGADGET
#define	Gt	GADGIMMEDIATE|RELVERIFY|TOGGLESELECT,BOOLGADGET
#define Gg	GADGHCOMP|GADGIMAGE
#define Gd	GADGHCOMP|GADGDISABLED|GADGIMAGE
#define Gs	GADGHCOMP|SELECTED|GADGIMAGE
#define fn	Gg,Gn
#define ft	Gg,Gt
#define fd	Gd,Gn
#define fs	Gs,Gt
#define fu	Gd,Gt

#define gdgt(p,x,y,q,w)	{\
	p,x,y,20,9,q,(APTR)&toets,NL,&ttxt[w],NL,NL,gnum+w,NL}

#define edgt(p,x,y,q,w)	{\
	p,x,y,28,9,q,(APTR)&toetsb,NL,&etxt[w-40],NL,NL,w,NL}

struct	Gadget gbn[3] = {
 {&gbn[1],x4,y2,20,9,fd,(APTR)&toets,NL,&btxt[0],NL,NL,gnum+37,NL},
 {&gbn[2],x6,y2,20,9,fd,(APTR)&toets,NL,&btxt[1],NL,NL,gnum+38,NL},
 {NL,    x5,y2,20,9,fd,(APTR)&toets,NL,&btxt[2],NL,NL,gnum+39,NL} };

struct	Gadget ext[21] ={
	edgt(&ext[ 1],x7,y2,fn,Esin),	edgt(&ext[ 2],x8,y2,fn,Ears),
	edgt(&ext[ 3],x9,y2,fn,Esih),	edgt(&ext[ 4],x7,y3,fn,Ecos),
	edgt(&ext[ 5],x8,y3,fn,Earc),	edgt(&ext[ 6],x9,y3,fn,Ecoh),
	edgt(&ext[ 7],x7,y4,fn,Etan),	edgt(&ext[ 8],x8,y4,fn,Eart),
	edgt(&ext[ 9],x9,y4,fn,Etah),	edgt(&ext[10],x7,y5,fn,Elog),
	edgt(&ext[11],x8,y5,fn,Eexp),	edgt(&ext[12],x9,y5,fn,Epi ),
	edgt(&ext[13],x7,y6,fn,Epow),	edgt(&ext[14],x8,y6,fn,Esqr),
	edgt(&ext[15],x9,y6,ft,Emsp),	edgt(&ext[16],x7,y7,fn,Erin),
	edgt(&ext[17],x8,y7,fn,Emin),	edgt(&ext[18],x9,y7,fn,Emmin),
	edgt(&ext[19],x7,y8,fn,Erui),	edgt(&ext[20],x8,y8,fn,Emr ),
	edgt(gbn     ,x9,y8,fn,Empl ) };

struct	Gadget lwb =
 {ext,    x1,y2,20,9,fn,(APTR)&toets,NL,&ltxt,   NL,NL,gnum+36,NL};

struct	Gadget hbd =
 {&lwb,   x6,y3,20,9,fn,(APTR)&toets,NL,&htxt,   NL,NL,gnum+35,NL};

struct	Gadget tts[35] = {
	gdgt(&tts[ 1],x1,y8,fn, 0),	gdgt(&tts[ 2],x1,y7,fn, 1),
	gdgt(&tts[ 3],x2,y7,fn, 2),	gdgt(&tts[ 4],x3,y7,fn, 3),
	gdgt(&tts[ 5],x1,y6,fn, 4),	gdgt(&tts[ 6],x2,y6,fn, 5),
	gdgt(&tts[ 7],x3,y6,fn, 6),	gdgt(&tts[ 8],x1,y5,fn, 7),
	gdgt(&tts[ 9],x2,y5,fn, 8),	gdgt(&tts[10],x3,y5,fn, 9),
	gdgt(&tts[11],x1,y4,fd,10),	gdgt(&tts[12],x2,y4,fd,11),
	gdgt(&tts[13],x3,y4,fd,12),	gdgt(&tts[14],x1,y3,fd,13),
	gdgt(&tts[15],x2,y3,fn,14),	gdgt(&tts[16],x3,y3,fd,15),
	gdgt(&tts[17],x2,y8,fn,16),	gdgt(&tts[18],x4,y6,fn,17),
	gdgt(&tts[19],x5,y6,fn,18),	gdgt(&tts[20],x6,y6,fn,19),
	gdgt(&tts[21],x4,y7,fn,20),	gdgt(&tts[22],x5,y7,fn,21),
	gdgt(&tts[23],x4,y3,fd,22),	gdgt(&tts[24],x5,y3,fd,23),
	gdgt(&tts[25],x6,y4,fn,24),	gdgt(&tts[26],x4,y5,fd,25),
	gdgt(&tts[27],x5,y5,fd,26),	gdgt(&tts[28],x6,y5,fd,27),
	gdgt(&tts[29],x6,y7,fn,28),	gdgt(&tts[30],x4,y4,fn,29),
	gdgt(&tts[31],x5,y4,fn,30),	gdgt(&tts[32],x3,y8,fn,31),
	gdgt(&tts[33],x4,y8,fn,32),	gdgt(&tts[34],x5,y8,fn,33),
	gdgt(&hbd,    x6,y8,fn,34) };

struct	Gadget clkg = { NL,29,0,26,10,fn,(APTR)&ctoets,NL,NL,NL,NL,200,NL };
struct	Gadget klg = { tts,2,115,264,4,fn,(APTR)&balk,NL,NL,NL,NL,300,NL };

#ifdef	MC68882
struct Menu mijn_naam = { NL,NL,NL,640,10,MENUENABLED,
	"Calculus " VERSIE " MC68881/2  januari 1991 door Simon Bruin",NL };
#else
struct Menu mijn_naam = { NL,NL,NL,640,10,MENUENABLED,
	"Calculus " VERSIE "  januari 1991 door Simon Bruin",NL };
#endif

struct NewWindow NW = {		/* calculator window				*/
	0,0,breedte,hogte,
	pen3,pen2,
	GADGETDOWN | GADGETUP | CLOSEWINDOW | VANILLAKEY |
	RAWKEY | MOUSEBUTTONS,
	WINDOWDRAG | WINDOWCLOSE | SMART_REFRESH | ACTIVATE,
	&klg,NL,
	"Calculus " VERSIE,
	NL,NL,
	0,0,0,0,
	WBENCHSCREEN };

struct NewWindow NW2 = {	/* klok window						*/
	392,0,breedte-74,10,
	pen3,pen2,
	GADGETDOWN | GADGETUP | CLOSEWINDOW,
	WINDOWCLOSE | SIMPLE_REFRESH,
	&clkg,NL,
	NL,
	NL,NL,
	0,0,0,0,
	WBENCHSCREEN };

struct	Window		*window=NL, *OpenWindow();
struct	timerequest	Time_Req ;
struct	MsgPort		*Timer_Port=NL, *CreatePort() ;
SHORT	xstart=300, ystart=15,mode=0;

#define	dbl	0
#define flg	1
#define	g32	2

#define dec	1
#define	hex	2
#define	bin	3

struct	Zetting {
		SHORT		g_zoort;
		SHORT		mode;
} pr_zet = { dbl, dec }, vl_zet = { dbl, dec };

union Onderwerp {
		LONG		l;
		FLOAT		fl;
		DOUBLE		db;
};

struct	Register {
		union Onderwerp	getal;
		SHORT			g_zoort;
} registers[16] = {
	{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },
	{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },
	{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },
	{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl },{ 0.0, dbl } };

struct	Getal {
		struct Getal		*vorige;
		union Onderwerp		onderwerp;
		SHORT				bewerking;
		SHORT				g_zoort;
} bodem = { NL, 0.0, 0, dbl }, memory = { NL, 0.0, 0, dbl };

struct	Getal	*top = &bodem;

struct Bin {
		SHORT		dsofs;
		SHORT		bit;
		int			limit;
		int			x_aan;
		int			x_uit;
} binst = { 0, 0, 25, 252, 252 };

char inpstr[64]="                               0";
char uitpstr1[27]="                        0 ";
char uitpstr2[33]="                                ";
char clock[8];
char clstr[18]=" ";
char msstr[17]="x =     y =     ";
char *uitpstr=uitpstr1;
char errstr[33]="                           ERROR";
char hkst[5]="    ";

struct TextAttr mijnfont={ "topaz.font",9,FSF_BOLD,FPF_ROMFONT };
struct IntuiText hkts={ pen4, 0, JAM2, x2+6, y2+1, NL, (UBYTE *)hkst, NL };
struct IntuiText mtime={ pen3, pen2, JAM2, 129, 1, NL, (UBYTE *)clstr, NL };
struct IntuiText dstxt={pen2, 0, JAM2, 2, y1, &mijnfont, (UBYTE *)uitpstr1,
			&hkts};
struct IntuiText d2txt={pen2, 0, JAM2, 4, y1, NL, (UBYTE *)uitpstr2, &hkts};
struct IntuiText *dptxt=&dstxt;

SHORT raam[]={ 0,0, 10,0, 10,11, 0,11, 0,0 };
struct	Border kader_aan={ -1,-2,pen4,0,JAM1,5,raam,NL };
struct	Border kader_uit={ -1,-2,pen1,0,JAM1,5,raam,NL };

int sl=25;
long signal2;
int muis=0, grfl=0;
int gdisl=0x003D0370, bgdsl=0x003D0370,
    gdish=0x00000038, bgdsh=0x00000038;

void ddddd(f)	/* uitgang ruimt alle troep op. Als f>0 wort het programma
				   volledig geaborteerd */
short f;
{
	if (f==1) het_tocht();
	if (!mode)
	{
		xstart=window->LeftEdge;
		ystart=window->TopEdge;
	}
	if (window) CloseWindow(window);
	if (f==2) het_tocht();
	if (Timer_Port) DeletePort(Timer_Port) ;
	if (f==3) het_tocht();
	if (Time_Req.tr_node.io_Message.mn_ReplyPort)
		CloseDevice(&Time_Req) ;
	if (f==4) het_tocht();	
}

void switcw(wp)	/* wisselt van window calculator <--> klokje */
struct NewWindow *wp;
{
	if (mode)
	{
		mtime.LeftEdge=56;
		NW.LeftEdge=xstart=window->LeftEdge;
		NW.TopEdge=ystart=window->TopEdge;
	}
	if (window) CloseWindow(window);
	if ((window=OpenWindow(wp))==NL)
		ddddd(4);
	if (!mode)
	{
		mtime.LeftEdge=129;
		SetMenuStrip(window,&mijn_naam);
	}
}

void Owg()	/* opent window en instalert de timer voor de klok */
{
	mtime.LeftEdge=129;
	NW.LeftEdge=xstart;
	NW.TopEdge=ystart;
	if ((window=OpenWindow(&NW))==NL)
		ddddd(1);
	SetMenuStrip(window,&mijn_naam);
	if ((Timer_Port=CreatePort("Timer Port",0))==NL)
		ddddd(2);
	memset((char *)&Time_Req,0,sizeof(Time_Req));
	if (OpenDevice(TIMERNAME,UNIT_VBLANK,(char *)&Time_Req,0)!=NL)
		ddddd(3);
	Time_Req.tr_node.io_Message.mn_ReplyPort=Timer_Port;
	Time_Req.tr_node.io_Command=TR_ADDREQUEST;
	Time_Req.tr_node.io_Flags=0;
	Time_Req.tr_node.io_Error=0;
}

char sitemp[10] = "  ";

void inprint(s,g,l)	/*  zet getal g in string s met l digits */
char *s;
int g,l;
{
	int ul;

	ul=stci_d(&sitemp[2],g);
	if (ul>l) ul=l;
	if (l==4) 
	{
		ul-=1;
		strncpy(s,&sitemp[ul],2);
		s[2]='.';
		s[3]=sitemp[ul+2];
	}
	else
	{
		if (l==3) ul-=1;
		strncpy(s,&sitemp[ul],l);
	}
}

int zoek(ch)	/* zoekt toets op in tabel met corresponderent gadget nummer */
char ch;
{
	register int i,b;
	b=gdisl;
	for (i=0;i<31;i++)
	{
		if (b&0x80000000) return -1;
		else if (ch==gtl[i]) return i;
		b<<=1;
	}
	return -1;
}
								/* flaggen							*/
#define	BEWERKT		0x0001		/* het getal word bewerkt			*/
#define HAAKJE		0x0002
#define VERANDERT	0x0004
#define INVOER		0x0008
#define ERROR		0x0010
#define	DISPLAY		0x0020
#define RESET		0x0040
#define DBIT		0x0080
#define	BITAAN		0x0100
#define BITUIT		0x0200
#define CLEAR		0x0400

int pfe=0;

int getal2(fl)	/* brijd de bewerkings lijst met een getal uit */
int fl;
{
	struct Getal *temp;

	if (fl&BEWERKT)
	{
		temp=malloc(sizeof(struct Getal));
		temp->vorige=top; top=temp;
		top->g_zoort=pr_zet.g_zoort;
		top->onderwerp.db=0.0;
		fl^=BEWERKT; fl|=VERANDERT;
	}
	return fl;
}

int do_getal(num,fl)	/* invoer van getal */
int num, fl;
{
	static int ofs1=0, pfl=0;

	fl=getal2(fl);
	if (fl&RESET)
	{
		top->g_zoort=pr_zet.g_zoort;
		top->bewerking=0;
		fl^=RESET; fl&=~INVOER;
	}
	if (!(fl&INVOER)&&((num<17)||(num==Nmin)))
		ofs1=pfl=pfe=0;
	if ( !( (num==Npunt)&&(pfl)	/* niet meer dan een punt				*/
		||(ofs1>=binst.limit)	/* niet meer getallen dan binst.limit	*/
		||(!(top->g_zoort>>1)&&(num==0x0E)&&(pfe))) /* een e is genoeg	*/
		&& ((num<17)||(num==Nmin)) )
	{
		num+=0x30; if (num>0x39) num+=7;
		if (!(top->g_zoort&2))
		{							/* g_zoort is geen integer	*/
		   	if (pfe==1) pfe=2;
		   	if (num==0x4C) num='-';
		   	if (num==0x47) { num='.'; pfl=-1; }
		   	if (num==0x45) { pfe=1; num=0x65; }
		}
		++ofs1;
		inpstr[ofs1+30]=(char)num; inpstr[ofs1+31]=0;
		binst.dsofs=(32-sl)+ofs1-1;
		strncpy(uitpstr,&inpstr[binst.dsofs],sl);
		fl|=INVOER|DISPLAY;
	}
	fl&=~VERANDERT;
	return fl;
}

void omzet(o,g) /* zet gatal om double <-> float <-> long */ 
struct Getal *o;
SHORT g;
{
	if (o->g_zoort==g) return;

	switch (g)
	{
		case dbl:
		switch (o->g_zoort)
		{
			case flg:
			o->onderwerp.db=(DOUBLE)o->onderwerp.fl; return;
			case g32:
			o->onderwerp.db=(DOUBLE)o->onderwerp.l; return;
		}
		case flg:
		switch (o->g_zoort)
		{
			case dbl:
			o->onderwerp.fl=(FLOAT)o->onderwerp.db; return;
			case g32:
			o->onderwerp.fl=(FLOAT)o->onderwerp.l; return;
		}
		case g32:
		switch (o->g_zoort)
		{
			case dbl:
			o->onderwerp.l=(LONG)o->onderwerp.db; return;
			case flg:
			o->onderwerp.l=(LONG)o->onderwerp.fl; return;
		}
	}
}

int do_omzet(fl)	/* zet string om naar getal		*/
int fl;
{
	int i,l;
	DOUBLE temp;
	LONG ltemp;
	
	if (fl&INVOER)
	{
		pfe=0;
		i=0;
		while (inpstr[i]==' ') i++;
		top->g_zoort=pr_zet.g_zoort;
		switch(pr_zet.g_zoort)
	   	{
			case dbl:
			case flg:
			     if (inpstr[i]==0) { fl|=ERROR; break; }
			     temp = atof(&inpstr[i]);
			     if (pr_zet.g_zoort==dbl)
				top->onderwerp.db=temp;
			     else
				top->onderwerp.fl=(FLOAT)temp;
			     break;
			case g32:
			     switch(pr_zet.mode)
			     {
				case dec:
				     l=stcd_l(&inpstr[i],&ltemp);
				     break;
				case hex:
				     l=stch_l(&inpstr[i],&ltemp);
				     break;
			     }
			     if (l==0) { fl|=ERROR; break; }
			     top->onderwerp.l=ltemp;
		}
		fl^=INVOER;
	}
	return fl;
}

DOUBLE ontvfl(p)	/* returnt double */
struct Getal *p;
{
	switch(p->g_zoort)
	{
		case dbl:
		     return p->onderwerp.db;
		case flg:
		     return (DOUBLE)p->onderwerp.fl;
	}
}

void gaffl(p,db)	/* voert double in */
struct Getal *p;
DOUBLE db;
{
	switch(p->g_zoort)
	{
		case dbl:
		     p->onderwerp.db=db;
		     break;
		case flg:
		     p->onderwerp.fl=(FLOAT)db;
	}
}

int do_sbewer(num,fl) /* doet de volgende bewerkingen; <<, >> en +-		*/
int num,fl;
{
	if ((fl=do_omzet(fl))&ERROR) return fl;
	switch(num)
	{
		case Nsl:
		     top->onderwerp.l<<=1;
		     break;
		case Nsr:
		     top->onderwerp.l>>=1;
		     break;
		case Npm:
		     switch(top->g_zoort)
		     {
			  case g32:
			       top->onderwerp.l=-top->onderwerp.l;
			       break;
			  case dbl:
			  case flg:
			       gaffl(top,-ontvfl(top));
		     }
	}
	return fl|VERANDERT;
}

int do_sfbew(num,fl)	/* doet alle wiskundige bewerkingen */
int num,fl;
{
	if ((fl=do_omzet(fl))&ERROR) return fl;
	if (top->g_zoort==g32) return fl|ERROR;
	switch (num)
	{
		case Esin:
		gaffl(top,sin(ontvfl(top))); break;
		case Ears:
		gaffl(top,asin(ontvfl(top))); break;
		case Esih:
		gaffl(top,sinh(ontvfl(top))); break;
		case Ecos:
		gaffl(top,cos(ontvfl(top))); break;
		case Earc:
		gaffl(top,acos(ontvfl(top))); break;
		case Ecoh:
		gaffl(top,cosh(ontvfl(top))); break;
		case Etan:
		gaffl(top,tan(ontvfl(top))); break;
		case Eart:
		gaffl(top,atan(ontvfl(top))); break;
		case Etah:
		gaffl(top,tanh(ontvfl(top))); break;
		case Elog:
		gaffl(top,log(ontvfl(top))); break;
		case Eexp:
		gaffl(top,exp(ontvfl(top))); break;
		case Esqr:
		gaffl(top,sqrt(ontvfl(top))); break;
	}
	return fl|VERANDERT;
}

int bewint(e,o)	/* alle overige bewerkingen */
struct Getal *e, *o;
{
/*	SHORT b;

	b=abs(e->bewerking); */
	omzet(o,e->g_zoort);

	if (e->g_zoort>>1)
	{
		switch(abs(e->bewerking))
		{
			case Nmaal:
			     e->onderwerp.l=e->onderwerp.l*o->onderwerp.l; break;
			case Ndeel:
			     if (o->onderwerp.l==0) return -1;
			     e->onderwerp.l=e->onderwerp.l/o->onderwerp.l; break;
			case Nmod:
			     if (o->onderwerp.l==0) return -1;
			     e->onderwerp.l=e->onderwerp.l%o->onderwerp.l; break;
			case Nplus:
			     e->onderwerp.l=e->onderwerp.l+o->onderwerp.l; break;
			case Nmin:
			     e->onderwerp.l=e->onderwerp.l-o->onderwerp.l; break;
			case Nand:
			     e->onderwerp.l=e->onderwerp.l&o->onderwerp.l; break;
			case Nxor:
			     e->onderwerp.l=e->onderwerp.l^o->onderwerp.l; break;
			case Nor:
			     e->onderwerp.l=e->onderwerp.l|o->onderwerp.l; break;
		}
	}
	else
	{
		switch(abs(e->bewerking))
		{
			case Nmaal:
			     gaffl(e,ontvfl(e)*ontvfl(o)); break;
			case Ndeel:
			     if (ontvfl(o)==0.0) return -1;
			     gaffl(e,ontvfl(e)/ontvfl(o)); break;
			case Nmod:
			     if (ontvfl(o)==0.0) return -1;
			     gaffl(e,fmod(ontvfl(e),ontvfl(o))); break;
			case Nplus:
			     gaffl(e,ontvfl(e)+ontvfl(o)); break;
			case Nmin:
			     gaffl(e,ontvfl(e)-ontvfl(o)); break;
			case Epow:
			     gaffl(e,pow(ontvfl(e),ontvfl(o))); break;
		}
	}
	return 0;
}

int do_bewerking(n,fl) /* recursive loep die alle bewerkingen naa loopt
						  en rekening houd met alle prioriteiten */
int n,fl;
{
	struct Getal *temp;
	int a,b,c,d,e;
	static int pri[11] = { 0,0,0,1,1,0,0,0,2,3,4 };

	fl=do_omzet(fl);	/* ontvang laatst ingevoerde getal */
	if (fl&ERROR) return fl;
	if ((temp=top->vorige)==NL) return fl;
	d=top->bewerking;
	e=temp->bewerking;
	if (abs(d)==Epow) a=0;
	else a=(d==0) ? 0 : pri[abs(d)-17];
	if (abs(d)==Epow) b=0;
	else b=pri[abs(e)-17];
	c=(d<=0) ? 1 : b-a;	/* als c==1 dan heeft top een hogere prioritijd */
	if ((c<=0)||(n>Bewrk))
		{ if (bewint(temp,top)) return fl|ERROR;
		  temp->bewerking=(e<0) ? -d : d;
		  free(top);
		  top=temp;	/* een tree lager */
		  fl|=VERANDERT;
		}
	if ((n==Bewrk)&&(c<=0)&&(e>=0)) fl=do_bewerking(Bewrk,fl);
	if ((n==Haakje)&&(e>=0)) fl=do_bewerking(Haakje,fl);
	if (n==IS) fl=do_bewerking(IS,fl);
	return fl;
}

void zet_haakjes(n)	/* laat kurig zien hoeveel haakjes er gebruikt zijn */
int n;
{
	if (!n) strncpy(hkst,"    ",5);
	else {
	   strncpy(hkst,"(  )",5); inprint(&hkst[1],(int)n,2); }
}

int sthc(s,l)	/* long -> hex string */
char *s;
LONG l;
{
	int i,r;
	LONG c;
	
	r=i=(binst.limit<=8) ? binst.limit : 8;
	
	while (i)
	{
		--i;
		c=(l&0x0000000F)+0x00000030;
		if (c>0x00000039) c+=7;
		s[i]=(char)c;
		l>>=4;
	}
	return r;
}

int zetstr(s,o,p)	/* zet getal in o netjes in string s naar de wensen van p */
char *s;
struct Getal *o;
struct Zetting *p;
{
	int i;
	LONG xd,xm,xdd,c,b,*u;
	DOUBLE xp;

	if (grfl)	/* getal -> grade string */
	{
		xp=fabs(o->onderwerp.db);
		xd=(LONG)o->onderwerp.db;
		xp=(xp-fabs((DOUBLE)xd))*60;
		xm=(LONG)xp;
		xdd=(LONG)((xp-(DOUBLE)xm)*600+0.5);
		if (xdd>599) { xm+=1; xdd=0; }
		i=stcl_d(s,xd); s[i++]='°';		
		i+=stcl_d(&s[i],xm); s[i++]='\'';
		inprint(&s[i],xdd,4); i+=4;
		s[i++]='"'; s[i]='\0';
		return i;
	}
	switch (p->mode)
	{
		case dec:	/* getal -> decimale string */
		switch (o->g_zoort)
		{
			case dbl:
				 if (ontvfl(o)==(DOUBLE)((LONG)ontvfl(o)))
				 	return stcl_d(s,(LONG)ontvfl(o));
			     gcvt(ontvfl(o),14,s); break;
			case flg:
			     gcvt(ontvfl(o),7,s); break;
			case g32:
			     return stcl_d(s,o->onderwerp.l);
		} break;
		case hex:	/* getal -> hexadecimale string */
		switch (o->g_zoort)
		{
			case dbl:
			     u=(void *)&o->onderwerp.db;
			     sthc(s,u[0]); sthc(&s[8],u[1]);
			     return 16;
			case flg:
			     u=(void *)&o->onderwerp.fl;
			     return sthc(s,u[0]);
			case g32:
			     return sthc(s,o->onderwerp.l);
		}
		case bin:	/* getal -> binary string */
		if (o->g_zoort>>1)
		{
			b=o->onderwerp.l;

			for (i=0;i<binst.limit;i++)
			{
				c=(b&0x80000000)? 0x31: 0x30;
				s[i]=(char)c;
				b<<=1;
			}
			return binst.limit;
		}
	}
	i=0;
	while (s[i])  i++; 
	return i;
}

int zetgetal(fl)	/* zet getal in uitput string buffer	*/
int fl;
{
	if (fl&ERROR) {	/* zet error string						*/
	   strncpy(uitpstr,&errstr[32-sl],sl); fl|=DISPLAY; return fl^ERROR; }
	if (fl&CLEAR) {
	   inpstr[31]=0x30; inpstr[32]=0; strncpy(uitpstr,&inpstr[32-sl],sl);
	   if (pr_zet.mode==bin) { binst.bit=0; fl=do_bit(1,fl); }
	   fl|=DISPLAY; fl^=CLEAR; }
	if (fl&VERANDERT)
	{
		omzet(top,pr_zet.g_zoort);
		top->g_zoort=pr_zet.g_zoort;

		binst.dsofs=(32-sl)+zetstr(&inpstr[31],top,&pr_zet)-1;

		strncpy(uitpstr,&inpstr[binst.dsofs],sl);

		fl^=VERANDERT; fl|=DISPLAY;
	}
	return fl;
}

long	ggdis[10]={ 0x003D0370, 0x00000038,	/* dbl flg dec a 0,1 d 1 */
				    0x003F8000, 0x8FFFE038,	/* g32     dec a 2,3 d 1 */
				    0xFFFFFFFE, 0xE7FFEFF8,	/* dbl flg hex a 0,1 d 2 */
				    0x00008000, 0x8FFFE038,	/* g32     hex a 2,3 d 2 */
				    0xFFFF8000, 0x8FFFE000,	/* g32     bin a 2,3 d 3 */
};
SHORT	limits[3][3]={  { 25,25,10 },	/* dec */
						{ 16, 8, 8 },	/* hex */
						{ 25,25,32 } };	/* bin */

#define	gadan	~GADGDISABLED	/* gadget enable	*/

void zet_rgad(f)	/* enables en disables gadgets als er gebruik word
					   gemaakt van de registers >R< en <R> */
int f;
{
	register int i;
	struct Gadget *get;

	if (f)
	{ gdisl=bgdsl; gdish=bgdsh; }
	else
	{ gdisl=0x0000FFFF; gdish=0x9FFFFFFF; }

	get=tts;
	for (i=0;i<61;i++) { /* totaal buiten de regels maar ja ? */
	    if (gdisl&0x80000000L) get->Flags|=GADGDISABLED;
	    else get->Flags&=gadan;
	    if (i==31) gdisl=gdish;
	    else gdisl<<=1;
	    get=get->NextGadget; }

	RefreshGadgets(tts,window,NL);
}

int zet_gadgets(fl)	/* enables en disables gadgets bij (F,I) en (D,H en B) */
int fl;
{
	register long i;
	SHORT a,d;
	struct Gadget *get;
	if ((pr_zet.g_zoort==vl_zet.g_zoort)&&
	    (pr_zet.mode==vl_zet.mode))
	    return fl;
	a=pr_zet.g_zoort; d=pr_zet.mode;
	if ((d==bin)&&(vl_zet.mode==hex)) fl|=BITAAN;
	if ((d==dec)&&(vl_zet.mode==bin)) { 
	   binst.x_uit=binst.x_aan; fl|=BITUIT; fl^=BITAAN; }
	binst.limit=limits[d-1][a];
	if (a!=vl_zet.g_zoort) fl=do_bit(0,fl);
	a>>=1; d=d*2+a;
	if (d!=6)
	{
		d=(d==7)? d-3: d-2;
		bgdsl=gdisl=ggdis[d<<1];
		bgdsh=gdish=ggdis[(d<<1)+1];
		get=tts;
		for (i=0;i<61;i++) { /* totaal buiten de regels maar ja ? */
		    if (gdisl&0x80000000L) get->Flags|=GADGDISABLED;
		    else get->Flags&=gadan;
		    if (i==31) gdisl=gdish;
		    else gdisl<<=1;
		    get=get->NextGadget; }
		htxt.IText[1]=hh[pr_zet.mode-1];
		if (!(pr_zet.g_zoort>>1)) strncpy(ltxt.IText,&ll[pr_zet.g_zoort<<1],2);
		ttxt[Mfi].IText[1]=ff[pr_zet.g_zoort>>1];
		RefreshGadgets(tts,window,NL);
	}
	vl_zet.g_zoort=pr_zet.g_zoort;
	vl_zet.mode=pr_zet.mode;
	return fl;
}

int do_bit(num,fl)	/* regelt de speciale binare mode */
int num,fl;
{
	fl=getal2(fl);
	if (num>35) fl=do_getal(17,fl);
	fl=do_omzet(fl);
	if (num==39) {
	   top->onderwerp.l^=1<<binst.bit; return fl|VERANDERT; }
	if (binst.bit>binst.limit-1) binst.bit=binst.limit-1;
	if ((num==37)&&(binst.bit<binst.limit-1)) ++binst.bit;
	if ((num==38)&&(binst.bit)) --binst.bit;
	binst.x_uit=binst.x_aan;
	binst.x_aan=252-8*binst.bit;
	inprint(btxt[2].IText,(int)binst.bit,2);
	RefreshGadgets(gbn,window,NL);
	if (num==1) return fl|BITUIT;
	return fl|BITUIT|VERANDERT; 
}

int do_snbit(fl)	/* regelt de speciale bit invoer bij de binare mode */
int fl;
{
	int x;

	fl=getal2(fl);
	if ((x=window->MouseX-4)<0) return fl;
	if ((x/=8)>31) return fl;
	x=31-x;
	if (x==binst.bit)	/* het kadertje staat er al dus alleen het		*/
	{					/* bitje inverten								*/
		top->onderwerp.l^=1<<binst.bit;
		return fl|VERANDERT;
	}
	binst.bit=x;
	binst.x_uit=binst.x_aan;
	binst.x_aan=252-8*binst.bit;
	inprint(btxt[2].IText,(int)binst.bit,2);
	RefreshGadgets(gbn,window,NL);
	return fl|BITUIT|VERANDERT; 
}

void do_gadget(num)	/* handelt de invoer van alle gadgets af en houd het
					   display up to date */
int num;
{
	static int fl=0,aant=0,regf=0,grpl=0;
	register struct Getal *temp;
	DOUBLE dbtemp;
	if ((regf)&&(num<16))	/* registers 0 - 15 (>R< <R>) */
		{ if (regf==1)
		  { fl=do_omzet(fl);
		    registers[num].getal.db=top->onderwerp.db;
		    registers[num].g_zoort=top->g_zoort; }
		  else
		  { fl=getal2(fl); /* maakt een nieuwe plek vrij */
		    top->onderwerp.db=registers[num].getal.db;
		    top->g_zoort=registers[num].g_zoort;
		    fl|=VERANDERT; }
		  zet_rgad(1); regf=0; }

else	/* invoer getal												*/
	if ((num<17)||((pfe==1)&&(num==Nmin))) fl=do_getal(num,fl);

else	/* bewerkingen; << >> en +- (hebben maar een getal nodig	*/
	if ((num>21)&&(num<25)) { fl=do_sbewer(num,fl); grpl=0; }

else	/* bewerkingen die twee getallen nodig hebben				*/
	if ((num>16)&&(num<28)||(num==Epow))
	   { if (fl&HAAKJE) { num=-num; fl^=HAAKJE; }
	     top->bewerking=num; fl|=BEWERKT; fl=do_bewerking(Bewrk,fl); grpl=0; }

else	/* wiskundige bewerkingen									*/
	if ((num>=Esin)&&(num<=Esqr)) { fl=do_sfbew(num,fl); grpl=0; }

else	/* het getal PI												*/
	if (num== Epi) { fl=getal2(fl); gaffl(top,PI); fl|=VERANDERT; }

else	/* de = gadget												*/
	if (num== Nis ) 
		{ fl=do_bewerking(IS,fl); fl|=RESET;
		  if (aant) { aant=0; zet_haakjes(aant); fl|=DISPLAY; } }

else	/* hakje open												*/
	if (num== Nho )
		{ zet_haakjes(++aant); fl|=HAAKJE|DISPLAY; }

else	/* hakje dicht												*/
	if ((num== Nhd )&&(aant))
		{ fl=do_bewerking(Haakje,fl); zet_haakjes(--aant); }

else	/* reister in >R<											*/
	if (num== Erin )
		{ regf=1; zet_rgad(0); }

else	/* register uit <R>											*/
	if (num== Erui )
		{ regf=2; zet_rgad(0); }

else	/* memorie in Min											*/
	if (num== Emin )
		{ fl=do_omzet(fl);
		  memory.onderwerp.db=top->onderwerp.db;
		  memory.g_zoort=top->g_zoort; }

else	/* memorie uit Mr											*/
	if (num== Emr )
		{ fl=do_getal(18,fl);
		  top->onderwerp.db=memory.onderwerp.db;
		  top->g_zoort=top->g_zoort;
		  fl|=VERANDERT; }

else	/* (memorie) - getal M-										*/
	if (num== Emmin )
		{ fl=do_omzet(fl);
		  memory.bewerking=Nmin;
		  if (bewint(&memory,top)) fl|=ERROR;
		  else {
		  fl=do_getal(18,fl);
		  top->onderwerp.db=memory.onderwerp.db;
		  top->g_zoort=memory.g_zoort;
		  fl|=VERANDERT; } }

else	/* (memorie) + getal M+										*/
	if (num== Empl )
		{
			fl=do_omzet(fl);
			memory.bewerking=Nplus;
			if (bewint(&memory,top)) fl|=ERROR;
			else
			{
				fl=do_getal(18,fl);
				top->onderwerp.db=memory.onderwerp.db;
				top->g_zoort=memory.g_zoort;
				fl|=VERANDERT;
			}
		}

else	/* invoer of display van graden								*/
	if (num== Ngra ) 
	{
		if ((!(fl&INVOER))&&(ontvfl(top)!=0.0))	/* getal in top en	*/
			grfl=1;				/* niks ingevoert dus print graden	*/
		else
		{
			dbtemp=ontvfl(top);	/* bewaar getal in top				*/
			fl=do_omzet(fl);	/* getal van invoerstring in top	*/
			grpl++;				/* if (grpl==1) top==graden			*/
			if (grpl==2)		/* minuten							*/
				gaffl(top,(dbtemp+ontvfl(top)/60.0));
			if (grpl==3)		/* seconden							*/
			{
				gaffl(top,(dbtemp+ontvfl(top)/3600.0));
				grpl=0;
			}
			grfl=1;
		}
		fl|=VERANDERT;
	}

else	/* cancel													*/
	if (num== NMCA ) 
		{ if (regf) { zet_rgad(1); regf=0; } else
		  if (fl&HAAKJE) { zet_haakjes(--aant); fl^=HAAKJE; } else
		  if (fl&BEWERKT) { top->bewerking=0; fl^=BEWERKT; } else
		  fl|=RESET|CLEAR; grpl=0; }

else	/* clear en error											*/
	if ((num== NMC )||(fl&ERROR))
		{ if (regf) { zet_rgad(1); regf=0; }
		  if (top->vorige==NL)
		  for (temp=top;temp==NL;temp=temp->vorige) free(temp);
		  top=&bodem; top->onderwerp.db=0.0;
		  if (aant) { aant=0; zet_haakjes(aant); }
		  top->bewerking=0; fl|=RESET|CLEAR; grpl=0; }

else	/* omgang tussen decimaal, hexadecimaal en binar			*/
	if (num== Mhbd ) 
		{ fl=do_omzet(fl); if (++pr_zet.mode>bin) pr_zet.mode=dec;
		  if (!(pr_zet.g_zoort&2)&&(pr_zet.mode==bin)) pr_zet.mode=dec;
		  if (pr_zet.mode==bin) { sl=32; dptxt=&d2txt; uitpstr=uitpstr2; }
		  else { sl=25; dptxt=&dstxt; uitpstr=uitpstr1; }
		  fl|=VERANDERT; }

else	/* omgang tussen double en float (single)					*/
	if (num== Mdfl )
		{ fl=do_omzet(fl); pr_zet.g_zoort^=1;
		  fl|=VERANDERT; }

else	/* omgang tussen float en integer							*/
	if (num== Mfi )
		{ fl=do_omzet(fl); pr_zet.g_zoort^=2;
		  fl|=VERANDERT; }

else	/* speciale binare mode										*/
	if ((num>36)&&(num<40)) fl=do_bit(num,fl);
else
	if (num==100) fl=do_snbit(fl);

	fl=zet_gadgets(fl); /* update's gadgets (an en disables)		*/
	fl=zetgetal(fl); if (grfl) { grfl=0; fl|=VERANDERT; }

	if (fl&BITUIT)	/* kadertje om bit uit							*/
		{ DrawBorder(window->RPort,&kader_uit,binst.x_uit,y1);
		  fl^=BITUIT; fl|=DISPLAY; }
	if (fl&DISPLAY)
		{ PrintIText(window->RPort,dptxt,0,0); fl^=DISPLAY; }
	if (fl&BITAAN)	/* kadertje om bit aan							*/
		  DrawBorder(window->RPort,&kader_aan,binst.x_aan,y1);
}

void Zet_clk()	/* verzorgt de display van de klok					*/
{
	char *p;

	getclk(clock);
	p=stptime(&clstr[1],5,&clock[4]);
	p[0]=' '; p[1]=' '; p+=2;
	stpdate(p,6,&clock[1]);
	PrintIText(window->RPort,&mtime,0,0);
}

long Doe_um(mh)	/* main antry										*/
hand_d *mh;
{
	struct IntuiMessage *mes;
	struct Gadget *gad;
	struct Message *msg;
	long class,gmdt;
	int code,k;

	Owg();

	signal2=mh->plopupsig|mh->quitsig|1<<Timer_Port->mp_SigBit;
	PrintIText(window->RPort,&dstxt,0,0);
	Zet_clk();
	Time_Req.tr_time.tv_secs=5;
	Time_Req.tr_time.tv_micro=0;
	SendIO((char *)&Time_Req.tr_node);

	for (;;)
	{
		gmdt=Wait((1L<<window->UserPort->mp_SigBit)|
		signal2);

		if (gmdt&(mh->plopupsig|mh->quitsig))
		{
			if (!mode) do_gadget(34);
			AbortIO((char *)&Time_Req.tr_node);
			ddddd(0); return gmdt;
		}

		if (gmdt&mh->muissig)
		{
			strcpy(&clstr[1],msstr);
			inprint(&clstr[5],window->WScreen->MouseX,3);
			inprint(&clstr[13],window->WScreen->MouseY,3);
			PrintIText(window->RPort,&mtime,0,0);
		}
		while ((mes=(struct IntuiMessage *)GetMsg(window->UserPort))!=NL)
		{
			class=mes->Class;
			code=mes->Code;
			gad=(struct Gadget *)mes->IAddress;
			ReplyMsg(mes);
			switch(class)
			{
				case GADGETUP:
					if (gad->GadgetID==200)
					{
						mode=0; switcw(&NW);
						PrintIText(window->RPort,&dstxt,0,0);
						Zet_clk();
					}
					else if (gad->GadgetID==300)
					{
						do_gadget(34);			/* clear */
						if (muis)
						{
							signal2&=(~mh->muissig);
							muis=0;
						}
						mode=-1; switcw(&NW2);
						Zet_clk();
					}
					else if (gad->GadgetID==Emsp)
					{
						muis=!muis;
						if (muis) signal2|=mh->muissig;
						else
						{
							signal2&=(~mh->muissig);
							Zet_clk();
						}
					}
					else do_gadget(gad->GadgetID);
					break;
				case VANILLAKEY:
					if ((k=zoek((char)code))!=-1) do_gadget(k); break;
				case CLOSEWINDOW:
					if (!mode) do_gadget(34);
					AbortIO((char *)&Time_Req.tr_node);
					ddddd(0); return NULL;
				case MOUSEBUTTONS:
					if ((pr_zet.mode==bin)&&(code==SELECTUP)&&
						(window->MouseY<y2)&&
						(window->MouseY>y1))
						do_gadget(100);
					break;
			}
		}
		if (msg=GetMsg(Timer_Port)!=0)
		{
			if (!muis) Zet_clk();
			Time_Req.tr_time.tv_secs=5;
			Time_Req.tr_time.tv_micro=0;
			SendIO((char *)&Time_Req.tr_node);
		}
	}
}

