// BRAVOCALC Module

// Last modified October 25, 1979  6:45 PM by Taft

get "bravo1.DF";
get "CHAR.DF";
get "CALC.DF";
get "doc.df"
get "select.df"
get "display.df"
get "vm.df"
get "rn1.df"
get "com.df"
get "msg.df"

// Incoming Procedures

external [
	replacea
	RbFromRlRi
	RdFromRlRbRi
	RealAdd;
	RealSub;
	RealMult;
	RealDiv;
	RealFromInt
	RealFromSt;
	StFromReal;
	stcopy;
	move;
	readsel;
	selectwholedoc;
	deleted
	insertc
	stsize
	InsertBuf;
	ClearBuf;
	setsel;
	InsertK;
	FixDispReal
	updatedisplay;
	FChInSb
	MakeCurrentBuf;
	BufToRi
	];

// Incoming Statics

external [
	vrldsys
	rgmaccp
	cdigitpoint;
	frealmode;
	vintradix;
	sbpast;
	deltacp;
	cpscrt;
	selmain;
	vesccom;
	vselcaret;
	chcom;
	vchterm;
	parstd
	look1std
	look2std
	];

// Outgoing Procedures

external [
	PushCalc;
	PopCalc;
	FCalc;
	RealMove;
	FCalcNum;
	FCalcNumTerm;
	];

// Outgoing Statics

external [
	vchccom;
	vfcalcst;
	vrealw;
	vrealz;
	vrealy;
	vrealx;
	]; 

// Local Statics

static	[
	vchccom;
	vfcalcst;
	vrealw;
	vrealz;
	vrealy;
	vrealx;
	];

// P U S H C A L C
//
let PushCalc() be
	[
	RealMove(vrealw,vrealz);
	RealMove(vrealz,vrealy);
	RealMove(vrealy,vrealx);
	]

// P O P C A L C
//
and PopCalc() be
	[
	RealMove(vrealx,vrealy);
	RealMove(vrealy,vrealz);
	RealMove(vrealz,vrealw);
	]

// R E A L M O V E
//
and RealMove(r1,r2) be
	[
	move(r2,r1,cwmaxreal);
	]


// F C A L C
//
and FCalc(cf,fhp; numargs carg) = valof
	[
	if carg ls 2 then fhp= fhpsel
	let chcom= cf>>CF.chcom
	if chcom eq $c then chcom= cf>>CF.w0
	let ab = nil
	let realop = vec cwmaxreal;
	let realres = vec cwmaxreal;
	let selop = vec sell;
	let tsb = vec (cchmaxreal+5)/2+1;
	let treal = vec cwmaxreal
	tsb ! 0 = 0;
	if chcom eq $~ then
		[ RealMove(realop,vrealx);
		RealMove(vrealx,vrealy);
		RealMove(vrealy,realop);
		goto display;
		]
	if chcom eq $↑ then
		[ RealMove(realop,vrealx);
		PopCalc();
		RealMove(vrealw,realop);
		goto display;
		]
	switchon fhp into
		[ 
case fhpnumber:	selop >> SEL.ww = 0
		selop >> SEL.doc = doctx2
		selop >> SEL.type = schar
		setsel(selop,0,rgmaccp ! doctx2-1);
		endcase;

case fhpsel:	move(selmain,selop,sell);endcase;

case fhpoptor:	RealMove(realop,vrealx);
		PopCalc();
		goto operator;
		]
	readsel(tsb,selop >> SEL.doc,selop >> SEL.cpfirst,selop >> SEL.cplast,cchmaxreal);
	if RealFromSt(realop,tsb) eq realnil then
		[
		ab<<AB.crid = 2	// Illegal number - 
		ab<<AB.nrid = 0
		resultis ab
		]
operator:		switchon chcom into
			[
 case $\:		PushCalc();
			RealMove(vrealx,realop);
			RealMove(realres,vrealx);endcase;

case $+:			RealAdd(realres,vrealx,realop);endcase;
case $=:			RealAdd(realres,vrealx,realop);endcase;
	
case $-:			RealSub(realres,vrealx,realop);endcase;

case $←:
case $**:		RealMult(realres,vrealx,realop);endcase;

case $%:		RealMult(realres,vrealx,realop)
		RealFromInt(treal,100)
		RealDiv(realres,realres,treal); endcase;

case $/:			if RealDiv(realres,vrealx,realop) eq realnil then
				[
				ab<<AB.crid = 2	// Divide by zero - 
				ab<<AB.nrid = 2
				FixDispReal()
				resultis ab
				]
			]
	RealMove(vrealx,realres);
display:	FixDispReal()
	resultis abnil
	]


// F C A L C N U M
//
and FCalcNum(cf) = valof
	[
	let chcom= cf>>CF.chcom
	let sel= cf>>CF.sel
	let ab = nil
	let tri,trb,tcp = nil,nil,nil
	let trd = vec lrd
	unless cf>>CF.frepeat do
		[ let txno = 2;
		vfcalcst = 0;
		ClearBuf(txno)
		tri = BufToRi(txno)
		trb = RbFromRlRi(vrldsys,tri)
		trd = RdFromRlRbRi(trd,vrldsys,trb,tri)
		tcp = trd>>RD.cp
		vselcaret >> SEL.doc = docsys;
		vselcaret >> SEL.ww = wwsys;
		setsel(vselcaret,tcp,tcp);
		vselcaret >> SEL.type = scaret;
		vselcaret >> SEL.toggle = 0;
		let tsiz = InsertK(wwsys,tcp,look1std,look2std,parstd,0,
		 (chcom eq $#?-1,chcom),FCalcNumTerm);
		if tsiz eq 0 then
			[
			ab<<AB.crid = 2	// No insertion - 
			ab<<AB.nrid = 6
			resultis ab
			]
		replacea(doctx0+txno,0,rgmaccp!txno,docsys,tcp,tsiz)
		replacea(docsys,tcp,tsiz,0,0,0)
		InsertBuf(txno,doctx0+txno,0,rgmaccp!txno);
		updatedisplay();
		cf>>CF.chcom = vchterm;
		if cf>>CF.chcom eq chesc then cf>>CF.chcom= $\
		chcom= cf>>CF.chcom
		]
	unless FChInSb(chcom,"+=-/**\%←") do
		[
		ab<<AB.crid = 2	// Operator missing - 
		ab<<AB.nrid = 4
		resultis ab
		]
	resultis FCalc(cf,fhpnumber);
	]


// F C A L C N U M T E R M
//
and FCalcNumTerm(ch,deltacp) = valof
	[
	resultis ((deltacp ne 0) & FChInSb(ch,"\+=-**/%←"))
	]