// PC.SR

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


get "BRAVO1.DF";
get "VM.DF";
get "CHAR.DF";
get "MSG.DF"
get "NEWMSG.DF"


// Incoming Procedures

external	[
	ult;
	ugt;
	umin;
	getvp;
	mult;
	puts;
	stnum;
	stsize;
	errhlta;
	stget;
	move;
	cpparabounds;
	movec;
	DoFop;
	mapfc;
	GetSi;
	];


// Incoming Statics

external	[
	ckproc;
	ckperr;
	ppcd;
	vpc;
	vcpput;
	rgmpbifb;
	mpfnof;
	mpfrfc;
	cblind;
	deltacp;
	vcp;
	rgmaccp;
	cpscrt;
	parsacred;
	parofbounds;
	pctb;
	rgpctb;
	vbifr;
	vfn;
	vfc;
	vmacfr;
	rglastused;
	lrutime;
	rgpcd;
	vbp;
	vlook1;
	vlook2;
	vfb;
	vfr;
	rglook1;
	vfOldtab;
	vdxtb;
	look1std
	look2std
	];


// Outgoing Procedures

external	[
	binsearcha;
	ckbinsearcha;
	mapcp;
	mapcpb;
	prevscrvch;
	getvch
	putvch
	getint;
// 	putint;
	cprealch;
	establishpc;
	establishrun;
	findparapc;
	];


// Outgoing Statics

external	[
	vpw;
	vlb;
	vchremain;
	vpa;
	pfwpg;
	vdoc;
	rcnew;
	vchremainb;
	mppccp;
	vmapstatus;
	vchremainorig;
	vchtxremain;
	vchfrremain;
	vfopPc;
	vtxstatus;
	vcuripar;
	vfopPara;
	vmapstate;
	vbpofsrc;
	ttblsacred
	vestRun
	]


// Local Statics

static	[
	vpw;
	vlb;
	vchremain;
	vpa;
	pfwpg;
	vdoc;
	rcnew;
	vchremainb;
	mppccp;
	vmapstatus;
	vchremainorig;
	vchtxremain;
	vchfrremain;
	vfopPc;
	vtxstatus;
	vcuripar;
	vfopPara;
	vmapstate;
	vbpofsrc;
	ttblsacred
	vestRun
	]


//B I N S E A R C H A
//threshold search for k in tbl
// catalogue no. = SPE-59
let binsearcha(tbl, maxi, k) = valof
[
let ttbl = tbl-1;
let u = maxi;
let l = 1;
let i = nil;
if ult(k, tbl ! maxi) do
	[
	i = (u+l) rshift 1;
	test ugt((ttbl ! i), k) ifso
		u = i-1
	ifnot	[
		test ( not ugt( (ttbl ! (i+1)), k)) ifso l = i+1
		ifnot resultis i-1
		]
	] repeat
resultis maxi;
]


//C K B I N S E A R C H A 
//checks to see if tbl!i <= k < tbl!(i+1)
// catalogue no. = SPE-63
and ckbinsearcha(tbl, i, k) be
[
ckproc = "ckbinsearch";
ckperr = i;
if ( ugt(k, (tbl ! i))) % (not ugt( (tbl ! (i+1)), k)) do
	errhlta(127);
]


// M A P C P B
// returns the number of characters which can be 
// reverse accessed without another mapcpb call, as well as the location
// of cp in vpw and vlb
// catalogue no. = SPE-76
and mapcpb(doc, cp) be
[
vmapstatus = statusblind;
mapcp(doc, cp);
test ppcd >> PCD.live ifso
	vchremainb = rcnew+1
ifnot	[
	let pgremainb = rcnew << PCD.rc+1;
	let pcremainb = cp-(mppccp ! vpc)+1;
	vchremainb = umin(pcremainb, pgremainb);
	]
]


// P R E V S C R V C H 
// catalogue no. = 138
and prevscrvch( ) be 
[
vcpput = vcpput-1;
let vpa = nil;
vpa << VPA.fn = fnscrfs;
vpa << VPA.fp = (rgmpbifb ! fnscr) ! ((mpfnof ! fnscr) >> OF.macbi-1);
let pfb = getvp(vpa);
let fr = pfb >> FB.macfr-1;
mpfrfc = pfb+pfb >> FB.mpfrfc;
mpfrfc ! fr = mpfrfc ! fr-1;
cblind = cblind+1;
deltacp = deltacp-1;
]


// G E T V C H
// catalogue no. = 135
and getvch( ) = valof
[
let char = nil;
if (vmapstatus eq statusblind) % (vchremain eq 0) then mapcp(vdoc, vcp) ;
test vlb ifso
	[
	char = vpw >> lh;
	vlb = false;
	]
ifnot	[
	char = vpw >> rh;
	vlb = true;
	vpw = vpw+1;
	]
vchremain = vchremain-1;
vcp = vcp+1;
resultis char;
]


// G E T I N T 
//
and getint(doc, radix; numargs N) = valof
[
if N eq 1 then radix = 10;
let sum = 0;
vmapstatus = statusblind;
vdoc = doc;
let maccp = rgmaccp ! doc;
if vcp eq maccp then resultis sum;
let digit = getvch();
let nega = false;
test digit eq $- ifso
	[
	nega = true;
	digit = 0;
	]
ifnot	digit = digit-$0
while digit ls 10 & digit ge 0 do
	[ 
	sum = mult(sum, radix)+digit;
	if vcp eq maccp then break;
	digit = getvch( )-$0;
	]
vcp = vcp-1;
vmapstatus = statusblind;
resultis nega ? -sum, sum;
]


// P U T V C H 
// catalogue no. = SPE-107
and putvch(char) be
[
(mpfnof ! fnscr) >> OF.pos = cpscrt+deltacp;
puts(fnscr, char);
vcpput = vcpput+1;
]


// P U T I N T
//
// and putint(int, radix; numargs N) = valof
// [ if N eq 1 then radix = 10;
// let stint = vec 5;
// stnum(stint, int, radix);
// let tsiz = stsize(stint);
// if tsiz gr 9 then errhlta(129);
// for i = 0 to tsiz-1 do
// 	putvch(stget(stint, i));
// resultis tsiz;
// ]


// C P R E A L C H 
//
and cprealch(doc, cp) = valof
[
resultis cp;
]


// M A P C P
// returns the number of characters which can be 
// accessed without another mapcp call, as well as the location
// of cp in vpw and vlb
// catalogue no. = SPE-76
and mapcp(doc, cp, parstatus; numargs n) be
[
if n ls 3 then parstatus = parnotneeded;
if parstatus eq parneeded then
	[
	test (vcuripar >> IPAR.doc eq doc) & (not ugt(vcuripar >> IPAR.cpfirst, cp)) & (not ult(vcuripar >> IPAR.cplast, cp)) ifso
		[
		parstatus = parnotneeded;
		move(vcuripar >> IPAR.par, parsacred, parovhd);
		]
	ifnot	[
		cpparabounds(doc, cp, lv (vcuripar >> IPAR.cpfirst), lv (vcuripar >> IPAR.cptrailer), lv (vcuripar >> IPAR.cplast));
		move(parofbounds, parsacred, parovhd);
		vcuripar >> IPAR.par = parsacred;
		vcuripar >> IPAR.doc = doc;
		unless parsacred>>PAR.fOldtab do
			[
			let siTtbl = parsacred>>PAR.siTtbl
			if siTtbl eq siTtblNil then errhlta(130)
			GetSi(ttblsacred, siTtbl, lnttblMax)
			movec(ttblsacred+ttblsacred>>TTBL.cw, ttblsacred +
				offampTtbl+itbMax-1, xtbNil)
			]
		if vfopPara ne fopNil then
			DoFop(vfopPara, 0, 0, parsacred, ttblsacred);
		vfOldtab = parsacred>>PAR.fOldtab ne 0
		if vfOldtab then
			vdxtb = parsacred>>PAR.dxtb
		]
	]
pctb = rgpctb ! doc;
mppccp = lv(pctb >> PCTB.rvmppccp);
// mapstatus = 0 means statusblind (i.e. non sequential call)
if vmapstatus & (vmapstatus ne resetchpters) then
	[
	vchtxremain = vchtxremain-vchremainorig;
	vchfrremain = vchfrremain-vchremainorig;
	]
let newstatus = vtxstatus;
let tfr = nil;
vpc = vmapstate >> MAPSTATE.pc;
vbifr = vmapstate >> MAPSTATE.bifr;
vfn = vmapstate >> MAPSTATE.fn;
vfc = vmapstate >> MAPSTATE.fc;
vbpofsrc = -1;
vestRun = false
switchon vmapstatus into
	[ 
case statusblind:
	vpc = binsearcha(mppccp, (pctb >> PCTB.macpc), cp);
	newstatus = establishpc(doc, vpc, cp);
	if (not (ppcd >> PCD.live)) & ((mpfnof ! vfn) >> OF.formatted) then
		mapfc(vfn, vfc);
	establishrun((parstatus & parneeded) ne 0);
	endcase;
case endofpiece:
	vpc = vpc+1;
	newstatus = establishpc(doc, vpc, cp);
	vbifr = ppcd >> PCD.bifr;
	establishrun(parstatus);
	endcase;
case endofpage:
	newstatus = establishpc(doc, vpc, cp);
	if vchfrremain then
		endcase;
case endofrun:
	tfr = vbifr << FBFR.fr;
	test (tfr+1 eq vmacfr) ifso
		[
		vbifr << FBFR.fb = vbifr << FBFR.fb+1;
		vbifr << FBFR.fr = 0;
		]
	ifnot	vbifr << FBFR.fr = tfr+1;
	establishrun(parstatus)
	endcase;
case resetchpters:
	newstatus = establishpc(doc, vpc, cp);
	]
unless vbpofsrc eq -1 then rglastused ! vbpofsrc = lrutime;
test  ult(vchfrremain, vchtxremain) ifso
	[
	vchremain = vchfrremain;
	vtxstatus = newstatus;
	newstatus = endofrun;
	]
ifnot	vchremain = vchtxremain;
vchremainorig = vchremain;
vmapstatus = newstatus;
vmapstate >> MAPSTATE.pc = vpc;
vmapstate >> MAPSTATE.bifr = vbifr;
vmapstate >> MAPSTATE.fn = vfn;
vmapstate >> MAPSTATE.fc = vfc;
if vmapstatus eq resetchpters then errhlta(131);
]


// E S T A B L I S H P C
//
and establishpc(doc, pc, cp) = valof
[
pctb = rgpctb ! doc;
mppccp = lv(pctb >> PCTB.rvmppccp);
if pc eq pctb >> PCTB.macpc then errhlta(131);
let cppcrel = cp-mppccp ! pc;
// ***
rgpcd = pctb+pctb >> PCTB.rgpcd;
ppcd = rgpcd+(pc lshift 2);
vfopPc = ppcd >> PCD.fop;
// test ppcd >> PCD.live ifnot
// 	[
	rcnew = cppcrel+(ppcd >> PCD.rc);
	vpa = (ppcd >> PCD.vpa)+rcnew << PCD.p;
	vfn = vpa << VPA.fn;
	vfc = ((vpa << VPA.fp) lshift 9)+(rcnew << PCD.rc);
	pfwpg = getvp(vpa);
	vbpofsrc = vbp
	rglastused ! vbpofsrc = -1
	vpw = pfwpg+(rcnew << PCD.rc  rshift  1);
	test (rcnew << odd) ifso
		vlb = false;
	ifnot	vlb = true;
	let pgremain = (#177777 << PCD.rc)+1-(rcnew << PCD.rc);
	let pcremain = (mppccp ! (vpc+1))-cp;
	test ult(pgremain, pcremain) ifso
		[
		vchtxremain = pgremain;
		resultis endofpage;
		]
	ifnot	[
		vchtxremain = pcremain;
		resultis endofpiece;
		]
// 	]
// ifso	[
//	let lpn = (ppcd >> PCD.vpa) << VPA.fn;
// 	let tlp = rglp ! lpn;
// 	rcnew = cp-(mppccp ! vpc);
// 	vpw = lv(tlp >> LP.rvbody)+((rcnew+1) rshift 1);
// 	test rcnew << odd ifso
// 		vlb = true
// 	ifnot vlb = false;
// 	vchtxremain = (mppccp ! (vpc+1))-(cp);
// 	resultis endofpiece;
// 	]
]


// E S T A B L I S H R U N
//
and establishrun(parstatus) be
[
vestRun = true
test (ppcd >> PCD.live) % not ((mpfnof  ! vfn) >> OF.formatted) ifso
	[
	vlook1 = look1std;
	vlook2 = look2std;
	vchfrremain = ppcd >> PCD.live ? vchtxremain, -1;
	]
ifnot	[
	vfb = (rgmpbifb ! vfn) ! (vbifr << FBFR.fb);
	vfr = vbifr << FBFR.fr;
	let tvpa = nil;
	tvpa << VPA.fn = fnscrfs;
	tvpa << VPA.fp = vfb;
	let pfb = getvp(tvpa);
	vmacfr = pfb >> FB.macfr;
	rglook1 = pfb+pfb >> FB.rglook1;
	vlook1 = rglook1 ! vfr;
	vlook2 = (pfb+pfb >> FB.rglook2) ! vfr;
	mpfrfc = pfb+pfb >> FB.mpfrfc;
	if vmapstatus eq endofrun then vfc = mpfrfc ! vfr;
	vchfrremain = (mpfrfc ! (vfr+1))-vfc;
	]
let tmacfr = vmacfr;
let tbifr = vbifr;
if vfopPc ne fopNil then
	DoFop(vfopPc, lv vlook1, lv vlook2, 0, 0)
if ppcd>>PCD.visibuf then
	vlook1 = vlook1 % visibufbits
if (parstatus eq paronfly) % (parstatus eq paratrun) then
	errhlta(128);
vmacfr = tmacfr;
vbifr = tbifr;
]


// F I N D P A R A P C
//
and findparapc(pcstart) = valof
[
let pc = pcstart+1;
let lastpc = pctb >> PCTB.macpc-1;
let tpcd = rgpcd+(pc lshift 2);
until (tpcd >> PCD.paraend) % (pc eq lastpc) do
	[
	pc = pc+1;
	tpcd = tpcd+4;
	]
resultis pc;
]